Commit c7613727 authored by Joseph Weston's avatar Joseph Weston

Merge branch 'feature/basic-operators' into 'master'

add factory functions for fundamental discrete symmetries

Closes #5 and #4

See merge request !1
parents 7d81d779 651b8f3d
Pipeline #20677 passed with stage
in 2 minutes and 56 seconds
......@@ -19,8 +19,7 @@
"outputs": [],
"source": [
"import numpy as np\n",
"import sympy\n",
"sympy.init_printing(print_builtin=True)"
"import sympy"
]
},
{
......@@ -267,21 +266,17 @@
"outputs": [],
"source": [
"# Identity\n",
"E = qsymm.groups.identity(3)\n",
"E = qsymm.identity(3)\n",
"# Inversion\n",
"I = qsymm.PointGroupElement(-np.eye(3))\n",
"I = qsymm.inversion(3)\n",
"# 4-fold rotation\n",
"C4 = qsymm.PointGroupElement(np.array([[1, 0, 0],\n",
" [0, 0, 1],\n",
" [0, -1, 0]]))\n",
"C4 = qsymm.rotation(1/4, [1, 0, 0])\n",
"# 3-fold rotation\n",
"C3 = qsymm.PointGroupElement(np.array([[0, 0, 1],\n",
" [1, 0, 0],\n",
" [0, 1, 0]]))\n",
"C3 = qsymm.rotation(1/3, [1, 1, 1])\n",
"# Time reversal\n",
"TR = qsymm.PointGroupElement(np.eye(3), conjugate=True)\n",
"TR = qsymm.time_reversal(3)\n",
"# Particle-hole\n",
"PH = qsymm.PointGroupElement(np.eye(3), conjugate=True, antisymmetry=True)\n",
"PH = qsymm.particle_hole(3)\n",
"\n",
"cubic_gens = {I, C4, C3, TR, PH}"
]
......@@ -410,7 +405,7 @@
},
"outputs": [],
"source": [
"TR.apply(H)"
"TR.apply(H).tosympy(nsimplify=True)"
]
},
{
......@@ -476,7 +471,7 @@
"metadata": {},
"outputs": [],
"source": [
"sz.apply(H)"
"sz.apply(H).tosympy(nsimplify=True)"
]
},
{
......@@ -518,7 +513,7 @@
"metadata": {},
"outputs": [],
"source": [
"discrete_symm[:5]"
"discrete_symm"
]
},
{
......@@ -592,7 +587,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.6.6"
"version": "3.7.1"
}
},
"nbformat": 4,
......
......@@ -8,9 +8,7 @@
"source": [
"import numpy as np\n",
"import sympy\n",
"from collections import OrderedDict\n",
"\n",
"sympy.init_printing(print_builtin=True)"
"from collections import OrderedDict"
]
},
{
......@@ -45,12 +43,12 @@
"outputs": [],
"source": [
"# Time reversal\n",
"TR = qsymm.PointGroupElement(sympy.eye(2), True, False, np.eye(2))\n",
"TR = qsymm.time_reversal(2, U=np.eye(2))\n",
"\n",
"# Chiral symmetry\n",
"C = qsymm.PointGroupElement(sympy.eye(2), False, True, np.array([[1, 0], [0, -1]]))\n",
"C = qsymm.chiral(2, U=np.array([[1, 0], [0, -1]]))\n",
"\n",
"# Atom A rotates into A, B into B.\n",
"# Atom A rotates into A, B into B, use exact sympy representation\n",
"sphi = 2*sympy.pi/3\n",
"RC3 = sympy.Matrix([[sympy.cos(sphi), -sympy.sin(sphi)],\n",
" [sympy.sin(sphi), sympy.cos(sphi)]])\n",
......@@ -105,7 +103,17 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"Scale the bond length in terms of the graphene lattice constant, and have the function return a list of BlochModel objects."
"Scale the bond length in terms of the graphene lattice constant, and have the function return a list of BlochModel objects. For this we can use a more convenient definition of the rotation"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"C3 = qsymm.rotation(1/3, U=np.eye(2))\n",
"symmetries = [C, TR, C3]"
]
},
{
......@@ -114,6 +122,7 @@
"metadata": {},
"outputs": [],
"source": [
"norbs = OrderedDict([('A', 1), ('B', 1)]) # A and B atom per unit cell, one orbital each\n",
"hopping_vectors = [('A', 'B', [0, 1/np.sqrt(3)])] # Hopping between neighbouring A and B atoms"
]
},
......@@ -158,10 +167,10 @@
"outputs": [],
"source": [
"# Time reversal\n",
"TR = qsymm.PointGroupElement(sympy.eye(2), True, False, np.eye(3))\n",
"TR = qsymm.time_reversal(2, np.eye(3))\n",
"\n",
"# Mirror symmetry \n",
"Mx = qsymm.PointGroupElement(sympy.Matrix([[-1, 0], [0, 1]]), False, False, np.diag([1, -1, 1]))\n",
"Mx = qsymm.mirror([1, 0], np.diag([1, -1, 1]))\n",
"\n",
"# Threefold rotation on d_z^2, d_xy, d_x^2-y^2 states.\n",
"C3U = np.array([[1, 0, 0],\n",
......@@ -175,12 +184,7 @@
"C3U2 = C3U2[mask][:, mask]\n",
"assert np.allclose(C3U, C3U2)\n",
"\n",
"# The spatial part of the symmetry must be provided as a symbolic matrix\n",
"# or an integer array\n",
"sphi = 2*sympy.pi/3\n",
"C3R = sympy.Matrix([[sympy.cos(sphi), -sympy.sin(sphi)],\n",
" [sympy.sin(sphi), sympy.cos(sphi)]])\n",
"C3 = qsymm.PointGroupElement(C3R, False, False, C3U)\n",
"C3 = qsymm.rotation(1/3, U=C3U)\n",
"\n",
"symmetries = [TR, Mx, C3]"
]
......@@ -232,7 +236,7 @@
"metadata": {},
"outputs": [],
"source": [
"family = qsymm.bloch_family(hopping_vectors, symmetries, norbs)"
"family = qsymm.bloch_family(hopping_vectors, symmetries, norbs, bloch_model=True)"
]
},
{
......@@ -320,7 +324,7 @@
"glide = qsymm.groups.symmetry_from_permutation(np.array([[-1, 0],[0, 1]]), perm_glide, norbs, onsite_glide)\n",
"\n",
"# TR\n",
"time_reversal = qsymm.PointGroupElement(np.eye(2), True, False, np.eye(4))\n",
"time_reversal = qsymm.time_reversal(2, np.eye(4))\n",
"\n",
"gens = {glide, inversion, time_reversal}\n",
"sg = qsymm.groups.generate_group(gens)\n",
......@@ -398,11 +402,11 @@
" perm_C4, norbs, onsite_C4)\n",
"\n",
"# Fermionic TR\n",
"time_reversal = qsymm.PointGroupElement(np.eye(2), True, False, \n",
"time_reversal = qsymm.time_reversal(2, \n",
" np.kron(np.eye(4), qsymm.groups.spin_rotation(2*np.pi * np.array([0, 1/2, 0]), S)))\n",
"\n",
"# define strange PH symmetry\n",
"particle_hole = qsymm.PointGroupElement(np.eye(2), True, True, np.eye(8))\n",
"particle_hole = qsymm.particle_hole(2, np.eye(8))\n",
"\n",
"gens = {C4, time_reversal, particle_hole}\n",
"\n",
......@@ -420,20 +424,13 @@
"print(len(family), [len(fam) for fam in family])\n",
"qsymm.display_family(family)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": []
}
],
"metadata": {
"kernelspec": {
"display_name": "new_dev",
"display_name": "Python 3",
"language": "python",
"name": "new_dev"
"name": "python3"
},
"language_info": {
"codemirror_mode": {
......@@ -445,7 +442,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.6.7"
"version": "3.7.1"
}
},
"nbformat": 4,
......
......@@ -10,9 +10,7 @@
"source": [
"import numpy as np\n",
"import sympy\n",
"import tinyarray as ta\n",
"\n",
"sympy.init_printing(print_builtin=True)"
"import tinyarray as ta"
]
},
{
......@@ -26,18 +24,6 @@
"import qsymm"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"scrolled": false
},
"outputs": [],
"source": [
"# Spin matrices\n",
"S = qsymm.groups.spin_matrices(1/2)"
]
},
{
"cell_type": "markdown",
"metadata": {},
......@@ -63,22 +49,13 @@
"outputs": [],
"source": [
"# C3 rotational symmetry - invariant under 2pi/3\n",
"phi = 2 * np.pi / 3\n",
"C3U = qsymm.groups.spin_rotation([0, 0, phi], S)\n",
"sphi = 2*sympy.pi/3\n",
"C3R = sympy.Matrix([[sympy.cos(sphi), -sympy.sin(sphi)],\n",
" [sympy.sin(sphi), sympy.cos(sphi)]])\n",
"C3 = qsymm.PointGroupElement(C3R, False, False, C3U)\n",
"C3 = qsymm.rotation(1/3, spin=1/2)\n",
"\n",
"# Time reversal\n",
"TRU = qsymm.groups.spin_rotation([0, np.pi, 0], S)\n",
"TRR = np.eye(2)\n",
"TR = qsymm.PointGroupElement(TRR, True, False, TRU)\n",
"TR = qsymm.time_reversal(2, spin=1/2)\n",
"\n",
"# Mirror symmetry in x\n",
"MxU = qsymm.groups.spin_rotation([np.pi, 0, 0], S)\n",
"MxR = np.diag([-1, 1])\n",
"Mx = qsymm.PointGroupElement(MxR, False, False, MxU)\n",
"Mx = qsymm.mirror([1, 0], spin=1/2)\n",
"\n",
"symmetries = [C3, TR, Mx]"
]
......@@ -176,16 +153,14 @@
" [0.0, -1.0, 0.0, 0.0],\n",
" [0.0, 0.0, 1.0, 0.0],\n",
" [0.0, 0.0, 0.0, -1.0]])\n",
"pR = -np.eye(2)\n",
"pS = qsymm.PointGroupElement(pR, False, False, pU)\n",
"pS = qsymm.inversion(2, U=pU)\n",
"\n",
"# Time reversal\n",
"trU = np.array([[0.0, 0.0, -1.0, 0.0],\n",
" [0.0, 0.0, 0.0, -1.0],\n",
" [1.0, 0.0, 0.0, 0.0],\n",
" [0.0, 1.0, 0.0, 0.0]])\n",
"trR = np.eye(2)\n",
"trS = qsymm.PointGroupElement(trR, True, False, trU)\n",
"trS = qsymm.time_reversal(2, U=trU)\n",
"\n",
"# Rotation\n",
"phi = 2.0*np.pi/4.0 # Impose 4-fold rotational symmetry\n",
......@@ -193,10 +168,7 @@
" [0.0, np.exp(-1j*3*phi/2), 0.0, 0.0],\n",
" [0.0, 0.0, np.exp(1j*phi/2), 0.0],\n",
" [0.0, 0.0, 0.0, np.exp(1j*3*phi/2)]])\n",
"sphi = 2*sympy.pi/4\n",
"rotR = sympy.Matrix([[sympy.cos(sphi), -sympy.sin(sphi)],\n",
" [sympy.sin(sphi), sympy.cos(sphi)]])\n",
"rotS = qsymm.PointGroupElement(rotR, False, False, rotU)\n",
"rotS = qsymm.rotation(1/4, U=rotU)\n",
"\n",
"symmetries = [rotS, trS, pS]"
]
......@@ -290,20 +262,15 @@
"outputs": [],
"source": [
"# Spatial inversion\n",
"pU = np.array([[1.0, 0.0, 0.0, 0.0],\n",
" [0.0, -1.0, 0.0, 0.0],\n",
" [0.0, 0.0, 1.0, 0.0],\n",
" [0.0, 0.0, 0.0, -1.0]])\n",
"pR = -np.eye(3)\n",
"pS = qsymm.PointGroupElement(pR, False, False, pU)\n",
"pU = np.diag([1, -1, 1, -1])\n",
"pS = qsymm.inversion(3, pU)\n",
"\n",
"# Time reversal\n",
"trU = np.array([[0.0, 0.0, -1.0, 0.0],\n",
" [0.0, 0.0, 0.0, -1.0],\n",
" [1.0, 0.0, 0.0, 0.0],\n",
" [0.0, 1.0, 0.0, 0.0]])\n",
"trR = np.eye(3)\n",
"trS = qsymm.PointGroupElement(trR, True, False, trU)\n",
"trS = qsymm.time_reversal(3, trU)\n",
"\n",
"# Rotation\n",
"phi = 2.0*np.pi/3.0 # Impose 3-fold rotational symmetry\n",
......@@ -311,12 +278,7 @@
" [0.0, np.exp(1j*phi/2), 0.0, 0.0],\n",
" [0.0, 0.0, np.exp(-1j*phi/2), 0.0],\n",
" [0.0, 0.0, 0.0, np.exp(-1j*phi/2)]])\n",
"sphi = 2*sympy.pi/3 # Impose 3-fold rotational symmetry\n",
"rotR = sympy.Matrix([[sympy.cos(sphi), -sympy.sin(sphi), 0],\n",
" [sympy.sin(sphi), sympy.cos(sphi), 0],\n",
" [0, 0, 1]])\n",
"\n",
"rotS = qsymm.PointGroupElement(rotR, False, False, rotU)\n",
"rotS = qsymm.rotation(1/3, axis=[0, 0, 1], U=rotU)\n",
"\n",
"symmetries = [rotS, trS, pS]"
]
......@@ -494,28 +456,20 @@
},
"outputs": [],
"source": [
"# Double spin-1/2 representation\n",
"spin = [np.kron(s, np.eye(2)) for s in qsymm.groups.spin_matrices(1/2)]\n",
"# C3 rotational symmetry\n",
"C3U = np.kron(qsymm.groups.spin_rotation([0, 0, 2 * np.pi / 3], S), np.eye(2))\n",
"sphi = 2*sympy.pi/3\n",
"C3R = sympy.Matrix([[sympy.cos(sphi), -sympy.sin(sphi), 0],\n",
" [sympy.sin(sphi), sympy.cos(sphi), 0],\n",
" [0, 0, 1]])\n",
"C3 = qsymm.PointGroupElement(C3R, False, False, C3U)\n",
"C3 = qsymm.rotation(1/3, axis=[0, 0, 1], spin=spin)\n",
"\n",
"# Time reversal\n",
"TRU = np.kron(qsymm.groups.spin_rotation([0, np.pi, 0], S), np.eye(2))\n",
"TRR = np.eye(3)\n",
"TR = qsymm.PointGroupElement(TRR, True, False, TRU)\n",
"TR = qsymm.time_reversal(3, spin=spin)\n",
"\n",
"# Mirror x\n",
"MxU = np.kron(qsymm.groups.spin_rotation([np.pi, 0, 0], S), np.eye(2))\n",
"MxR = np.diag([-1, 1, 1])\n",
"Mx = qsymm.PointGroupElement(MxR, False, False, MxU)\n",
"Mx = qsymm.mirror([1, 0, 0], spin=spin)\n",
"\n",
"# Inversion\n",
"IU = np.kron(np.eye(2), np.diag([1, -1]))\n",
"IR = -np.eye(3)\n",
"I = qsymm.PointGroupElement(IR, False, False, IU)"
"I = qsymm.inversion(3, IU)"
]
},
{
......@@ -554,10 +508,9 @@
"outputs": [],
"source": [
"identity_terms = qsymm.continuum_hamiltonian([qsymm.groups.identity(dim, 1)], dim, total_power)\n",
"for term in identity_terms:\n",
" for key, val in term.items():\n",
" term[key] = np.kron(val, np.eye(4))\n",
" term.shape = (4, 4)\n",
"identity_terms = [qsymm.Model({key: np.kron(val, np.eye(4))\n",
" for key, val in term.items()})\n",
" for term in identity_terms]\n",
"\n",
"Hamiltonian_family = qsymm.hamiltonian_generator.subtract_family(Hamiltonian_family, identity_terms, prettify=True)\n",
"qsymm.display_family(Hamiltonian_family)\n",
......@@ -669,7 +622,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.6.5"
"version": "3.7.1"
}
},
"nbformat": 4,
......
......@@ -15,7 +15,6 @@
"# qsymm\n",
"import qsymm\n",
"\n",
"sympy.init_printing(print_builtin=True)\n",
"np.set_printoptions(precision=2, suppress=True, linewidth=150)"
]
},
......@@ -52,9 +51,16 @@
"Hkeky = qsymm.Model(hamkeky, momenta=['k_x', 'k_y'])\n",
"candidates = qsymm.groups.hexagonal()\n",
"sgy, cg = qsymm.symmetries(Hkeky, candidates)\n",
"print(len(sgy))\n",
"print(sorted([qsymm.groups.name_PG_elements(g) for g in sgy]))\n",
"print(cg)"
"print(len(sgy), len(cg))"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"sgy"
]
},
{
......@@ -84,7 +90,7 @@
"\n",
"dd_sg = []\n",
"for subgroup, gens in all_subgroups.items():\n",
" print(len(subgroup),' ' , end='\\r')\n",
" # print(len(subgroup))\n",
" family = qsymm.continuum_hamiltonian(gens, 2, 0)\n",
" family = qsymm.hamiltonian_generator.subtract_family(family, identity_terms)\n",
" if family == []:\n",
......@@ -126,9 +132,13 @@
"source": [
"rdd_sg = []\n",
"for subgroup, gens in all_subgroups.items():\n",
" print(len(subgroup),' ', end='\\r')\n",
" # print(len(subgroup),' ', end='\\r')\n",
" invs = {qsymm.inversion(2) * g for g in [qsymm.identity(2),\n",
" qsymm.time_reversal(2),\n",
" qsymm.particle_hole(2),\n",
" qsymm.chiral(2)]}\n",
" # Skip subgroups that have inversion\n",
" if [g for g in subgroup if g.R == -sympy.eye(2)]:\n",
" if subgroup & invs:\n",
" continue\n",
" family = qsymm.continuum_hamiltonian(gens, 2, 0)\n",
" family = qsymm.hamiltonian_generator.subtract_family(family, identity_terms)\n",
......@@ -199,7 +209,8 @@
"metadata": {},
"outputs": [],
"source": [
"qsymm.symmetries(Hkeky, candidates=[], continuous_rotations=True, prettify=True)"
"_, cg = qsymm.symmetries(Hkeky, candidates=[], continuous_rotations=True, prettify=True)\n",
"cg"
]
},
{
......@@ -219,7 +230,8 @@
"hamkeko = 'vs * (k_x * kron(eye(2), sigma_x) + k_y * kron(sigma_z, sigma_y)) + Delta * kron(sigma_y, sigma_y)'\n",
"display(sympify(hamkeko))\n",
"Hkeko = qsymm.Model(hamkeko, momenta=['k_x', 'k_y'])\n",
"qsymm.symmetries(Hkeko, candidates=[], continuous_rotations=True, prettify=True)"
"_, cg = qsymm.symmetries(Hkeko, candidates=[], continuous_rotations=True, prettify=True)\n",
"cg"
]
},
{
......@@ -372,10 +384,10 @@
"norbs = OrderedDict([(site, 1) for site in sites])\n",
"\n",
"# Time reversal\n",
"TR = qsymm.PointGroupElement(sympy.eye(2), True, False, np.eye(6))\n",
"TR = qsymm.time_reversal(2, U=np.eye(6))\n",
"\n",
"# Chiral symmetry\n",
"C = qsymm.PointGroupElement(sympy.eye(2), False, True, np.kron(np.eye(3), ([[1, 0], [0, -1]])))\n",
"C = qsymm.chiral(2, U=np.kron(np.eye(3), ([[1, 0], [0, -1]])))\n",
"\n",
"# Atom A rotates into B, B into A.\n",
"sphi = 2*sympy.pi/3\n",
......@@ -484,7 +496,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.6.8"
"version": "3.7.1"
}
},
"nbformat": 4,
......
......@@ -3,7 +3,9 @@ from . import linalg
from . import hamiltonian_generator
from . import symmetry_finder
from . import model
from .groups import PointGroupElement, ContinuousGroupGenerator
from .groups import (
PointGroupElement, ContinuousGroupGenerator, identity,
time_reversal, particle_hole, chiral, inversion, rotation, mirror)
from .model import Model, BlochModel
from .hamiltonian_generator import continuum_hamiltonian, continuum_pairing, display_family, \
bloch_family
......
This diff is collapsed.
......@@ -4,6 +4,7 @@ import sympy
import itertools as it
import scipy.linalg as la
from copy import deepcopy
import tinyarray as ta
from .linalg import matrix_basis, nullspace, sparse_basis, family_to_vectors, rref, allclose
from .model import Model, BlochModel, _commutative_momenta, e, I
......@@ -639,6 +640,11 @@ def bloch_family(hopping_vectors, symmetries, norbs, onsites=True,
conserved = [g for g in symmetries if isinstance(g, ContinuousGroupGenerator)]
if not all([(g.R is None or np.allclose(g.R, np.zeros_like(g.R))) for g in conserved]):
raise ValueError('Bloch Hamiltonian cannot have continuous rotation symmetry.')
if (not bloch_model) and any(isinstance(g.R, ta.ndarray_float) for g in pg):
raise ValueError('Cannot generate Bloch Hamiltonian in Model format using '
'floating point rotation matrices. To avoid this error, use '
'only PointGroupElements that are defined with exact sympy '
'rotation matrices or use `bloch_model=True`.')
# Check dimensionality
dim = len(hopping_vectors[0][-1])
......
This diff is collapsed.
......@@ -7,8 +7,8 @@ from .. import kwant_rmt
from ..hamiltonian_generator import continuum_hamiltonian, check_symmetry, \
bloch_family, make_basis_pretty, constrain_family, continuum_variables, \
continuum_pairing, remove_duplicates, subtract_family
from ..groups import PointGroupElement, Model
from ..model import _commutative_momenta
from ..groups import PointGroupElement, Model, time_reversal, chiral, rotation
from ..model import _commutative_momenta, Model, BlochModel
from ..linalg import nullspace, family_to_vectors
......@@ -109,6 +109,40 @@ def test_bloch_generator():
assert any([member == other for other in again])
def test_graphene():
# Test Model
# Time reversal
TR = time_reversal(2, U=np.eye(2))
# Chiral symmetry
C = chiral(2, U=np.array([[1, 0], [0, -1]]))
# Atom A rotates into A, B into B, use exact sympy representation
sphi = 2*sympy.pi/3
RC3 = sympy.Matrix([[sympy.cos(sphi), -sympy.sin(sphi)],
[sympy.sin(sphi), sympy.cos(sphi)]])
C3 = PointGroupElement(RC3, False, False, np.eye(2))
symmetries = [C, TR, C3]
norbs = [('A', 1), ('B', 1)] # A and B atom per unit cell, one orbital each
hopping_vectors = [('A', 'B', [0, 1])] # Hopping between neighbouring A and B atoms
family = bloch_family(hopping_vectors, symmetries, norbs)
assert len(family) == 1
result = Model({'e**(sqrt(3)*I*k_x/2 + I*k_y/2)': np.array([[0, 0], [1, 0]]),
'e**(-sqrt(3)*I*k_x/2 - I*k_y/2)': np.array([[0, 1], [0, 0]]),
'e**(sqrt(3)*I*k_x/2 - I*k_y/2)': np.array([[0, 1], [0, 0]]),
'e**(-I*k_y)': np.array([[0, 0], [1, 0]]),
'e**(-sqrt(3)*I*k_x/2 + I*k_y/2)': np.array([[0, 0], [1, 0]]),
'e**(I*k_y)': np.array([[0, 1], [0, 0]])
},
normalize=True,
momenta=('k_x', 'k_y'))
assert family[0] == result
# Test BlochModel
C3 = rotation(1/3, U=np.eye(2))
symmetries = [C, TR, C3]
family = bloch_family(hopping_vectors, symmetries, norbs, bloch_model=True)
assert len(family) == 1
assert family[0] == BlochModel(result)
def test_continuum_variables():
dim = 2
......
......@@ -103,8 +103,7 @@ def test_disc_finder(verbose = False):
Hs = Model({kwant_continuum.sympify('a_' + str(i)) : H for i, H in enumerate(Hs)},
momenta=[])
# Find symmetry operators
sg = {PointGroupElement(np.empty((0, 0)), c, a)
for c, a in [[True, False], [True, True], [False, True]]}
sg = {time_reversal(0), particle_hole(0), chiral(0)}
sg, Ps = discrete_symmetries(Hs, sg)
if verbose:
print('sym', sg)
......@@ -173,8 +172,7 @@ def test_disc_finder(verbose = False):
Hs = Model({kwant_continuum.sympify('a_' + str(i)) : H for i, H in enumerate(Hs)},
momenta=[])
# Find symmetry operators
sg = {PointGroupElement(np.empty((0, 0)), c, a)
for c, a in [[True, False], [True, True], [False, True]]}
sg = {time_reversal(0), particle_hole(0), chiral(0)}
sg, Ps = discrete_symmetries(Hs, sg)
if verbose:
print('sym', sg)
......@@ -243,8 +241,7 @@ def test_disc_finder(verbose = False):
Hs = Model({kwant_continuum.sympify('a_' + str(i)) : H for i, H in enumerate(Hs)},
momenta=[])
# Find symmetry operators
sg = {PointGroupElement(np.empty((0, 0)), c, a)
for c, a in [[True, False], [True, True], [False, True]]}
sg = {time_reversal(0), particle_hole(0), chiral(0)}
sg, Ps = discrete_symmetries(Hs, sg)
if verbose:
print('sym', sg)
......@@ -316,8 +313,7 @@ def test_disc_finder(verbose = False):
# Find the symmetry operator
Hs = Model({kwant_continuum.sympify('a_' + str(i)) : H for i, H in enumerate(Hs)},
momenta=[])
sg = {PointGroupElement(np.empty((0, 0)), c, a)
for c, a in [[True, False], [True, True], [False, True]]}
sg = {time_reversal(0), particle_hole(0), chiral(0)}
sg, Ps = discrete_symmetries(Hs, sg)
assert [P.shape for P in Ps] == [(1, 2*dim, dim), (1, 2*dim, dim)]
assert len(sg) == 2
......@@ -355,8 +351,7 @@ def test_disc_finder(verbose = False):
assert np.allclose(H, T.dot(H.conj()).dot(T.T.conj()))
Hs = Model({kwant_continuum.sympify('a_' + str(i)) : H for i, H in enumerate(Hs)},
momenta=[])
sg = {PointGroupElement(np.empty((0, 0)), c, a)
for c, a in [[True, False], [True, True], [False, True]]}
sg = {time_reversal(0), particle_hole(0), chiral(0)}
sg, Ps = discrete_symmetries(Hs, sg)
assert [P.shape for P in Ps] == [(1, 3*dim, dim), (1, 3*dim, dim), (1, 3*dim, dim)]
assert len(sg) == 2
......@@ -392,8 +387,7 @@ def test_disc_finder(verbose = False):
assert np.allclose(H, T.dot(H.conj()).dot(T.T.conj()))
Hs = Model({kwant_continuum.sympify('a_' + str(i)) : H for i, H in enumerate(Hs)},
momenta=[])
sg = {PointGroupElement(np.empty((0, 0)), c, a)
for c, a in [[True, False], [True, True], [False, True]]}
sg = {time_reversal(0), particle_hole(0), chiral(0)}
sg, Ps = discrete_symmetries(Hs, sg)
assert [P.shape for P in Ps] == [(2, 2*dim, dim)]
assert len(sg) == 2
......@@ -427,8 +421,7 @@ def test_disc_finder(verbose = False):
h1, t_mat.dot(h1.conj()).dot(t_mat.T.conj())))
Hs = Model({kwant_continuum.sympify('a_' + str(i)) : H for i, H in enumerate(Hs)},
momenta=[])
sg = {PointGroupElement(np.empty((0, 0)), c, a)
for c, a in [[True, False], [True, True], [False, True]]}
sg = {time_reversal(0), particle_hole(0), chiral(0)}
sg, Ps = discrete_symmetries(Hs, sg)
assert sorted([P.shape for P in Ps]) == sorted([(1, 4*dim, dim), (1, 4*dim, dim), (2, 4*dim, dim)])
assert len(sg) == 2
......@@ -470,8 +463,8 @@ def test_continuum():
C3 = PointGroupElement(np.array([[0, 0, 1],
[1, 0, 0],
[0, 1, 0]], int), False, False, None)
TR = PointGroupElement(eye, True, False, None)
PH = PointGroupElement(eye, True, True, None)
TR = time_reversal(realspace_dim=3)
PH = particle_hole(realspace_dim=3)
cubic_gens = {I, C4, C3, TR, PH}
cubic_group = generate_group(cubic_gens)
assert len(cubic_group) == 192
......@@ -538,8 +531,8 @@ def test_bloch():
C6 = PointGroupElement(sympy.ImmutableMatrix([[sympy.Rational(1, 2), sympy.sqrt(3)/2],
[-sympy.sqrt(3)/2, sympy.Rational(1, 2)]]),
False, False, None)
TR = PointGroupElement(eyesym, True, False, None)
PH = PointGroupElement(eyesym, True, True, None)
TR = time_reversal(realspace_dim=2)
PH = particle_hole(realspace_dim=2)
gens_hex_2D ={Mx, C6, TR, PH}
hex_group_2D = generate_group(gens_hex_2D)
assert len(hex_group_2D) == 48
......
......@@ -28,22 +28,25 @@ def test_sparse_basis():
def test_spatial_types():
S1 = PointGroupElement(sympy.eye(2), True, True,
np.random.rand(3, 3))
S1 = PointGroupElement(sympy.eye(2), False, False,
np.eye(3))
S2 = PointGroupElement(sympy.Matrix([[0, 1], [1, 0]]), True, False,
np.random.rand(3, 3))
np.eye(3))
S3 = PointGroupElement(np.eye(2), False, False,
np.random.rand(3, 3))
S4 = PointGroupElement(np.array([[0, 1.2], [1.5, 0]]), True, False,
np.random.rand(3, 3))
1j * np.eye(3))
C6s = PointGroupElement(sympy.ImmutableMatrix(
[[sympy.Rational(1, 2), sympy.sqrt(3)/2],
[-sympy.sqrt(3)/2, sympy.Rational(1, 2)]]
))
C6f = PointGroupElement(np.array(
[[1/2, np.sqrt(3)/2],
[-np.sqrt(3)/2, 1/2]]
))
# Multiplying or comparing objects allowed if both or neither have sympy spatial parts
S = S1 * S2
assert S2**2 == S1
assert not S1 == S2
S = S3 * S4
assert not S3 == S4
assert S1 == S3
assert C6s == C6f
# Mixing sympy with other types raises an error
with raises(ValueError):
S = S1 * S3
with raises(ValueError):
S4 == S2
S = C6s * C6f
......@@ -20,10 +20,7 @@
"source": [
"import numpy as np\n",
"import sympy\n",
"import qsymm\n",
"\n",
"sympy.init_printing(print_builtin=True)\n",
"np.set_printoptions(precision=2, suppress=True, linewidth=150)"
"import qsymm"
]
},
{
......@@ -115,8 +112,7 @@
"outputs": [],
"source": [
"sg, cg = qsymm.symmetries(H1, cubic_group)\n",
"print(len(sg))\n",
"print(cg)"
"print(len(sg), len(cg))"
]
},
{
......@@ -148,7 +144,40 @@
},
"outputs": [],
"source": [
"print([qsymm.groups.name_PG_elements(g) for g in sg])"
"sg"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Detailed printout in LateX format."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"extensions": {
"jupyter_dashboards": {
"version": 1,
"views": {
"grid_default": {
"col": 0,
"height": 7,
"hidden": false,
"row": 14,
"width": 4
},
"report_default": {}
}
}
}
},
"outputs": [],
"source": [
"from IPython.display import display, Math\n",