def test_fourfold_rotation_symm_3x3(self): """ Test rotation symmetry by diagonalizing random spin system with and without using it :return: """ cluster = geom.Geometry.createSquareGeometry(3, 3, 0, 0, bc1_open=False, bc2_open=False) jx = np.random.rand() jy = np.random.rand() jz = np.random.rand() hx = np.random.rand() hy = np.random.rand() hz = np.random.rand() # diagonalize full hamiltonian spin_model = tvi.spinSystem(cluster, jx, jy, jz, hx, hy, hz, use_ryd_detunes=0) hamiltonian_full = spin_model.createH() eig_vals_full, eig_vects_full = spin_model.diagH(hamiltonian_full) # use rotationl symmetry cx, cy = spin_model.geometry.get_center_of_mass() rot_fn = symm.getRotFn(4, cx=cx, cy=cy) rot_cycles, max_cycle_len_rot = symm.findSiteCycles( rot_fn, spin_model.geometry) rot_op = spin_model.get_xform_op(rot_cycles) symm_projs, _ = symm.getZnProjectors(rot_op, 4) eig_vals_sectors = [] for ii, proj in enumerate(symm_projs): h_sector = spin_model.createH(projector=proj) eig_vals_sector, eig_vects_sector = spin_model.diagH(h_sector) eig_vals_sectors.append(eig_vals_sector) # why only accurate to 10 decimal places? eigs_all_sectors = np.sort(np.concatenate(eig_vals_sectors)) max_diff = np.abs(eig_vals_full - eigs_all_sectors).max() self.assertAlmostEqual(max_diff, 0, 10)
def test_c4_symmetry_3by3(self): """ Test fourfold rotational symmetry (generated by 90 degree rotation) on a 3x3 Hubbard cluster with open boundary conditions. :return: """ U = 20 * (np.random.rand() - 0.5) t = np.random.rand() gm = geom.Geometry.createSquareGeometry(3, 3, 0, 0, bc1_open=False, bc2_open=False) model = ed_fermions.fermions(gm, U, t, ns=np.array([1, 1])) # no symmetry hamiltonian_full = model.createH(projector=model.n_projector) eig_vals_full, eig_vects_full = model.diagH(hamiltonian_full) # use rotationl symmetry cx, cy = model.geometry.get_center_of_mass() rot_fn = symm.getRotFn(4, cx=cx, cy=cy) rot_cycles, max_cycle_len_rot = symm.findSiteCycles( rot_fn, model.geometry) rot_op = model.n_projector.dot( model.get_xform_op(rot_cycles).dot( model.n_projector.conj().transpose())) symm_projs, _ = symm.getZnProjectors(rot_op, 4) eig_vals_sectors = [] for ii, proj in enumerate(symm_projs): h_sector = model.createH(projector=proj.dot(model.n_projector)) eig_vals_sector, eig_vects_sector = model.diagH(h_sector) eig_vals_sectors.append(eig_vals_sector) # why only accurate to 10 decimal places? eigs_all_sectors = np.sort(np.concatenate(eig_vals_sectors)) max_diff = np.abs(eig_vals_full - eigs_all_sectors).max() self.assertAlmostEqual(max_diff, 0, 10)
n_list = np.array([]) k_list = np.array([]) projector_list = [] sf = ed_fermions.fermions(gm, 0, t, us_same_species=0, potentials=0, nspecies=1) # number subspace projectors n_species_op = sf.get_sum_op(sf.n_op, 0, format="boson") n_projs, ns = sf.get_subspace_projs(n_species_op, print_results=False) # translation op xtransl_op_full = sf.get_xform_op(xtransl_cycles) # get all projectors for n, n_proj in zip(ns, n_projs): xtransl_op = n_proj * xtransl_op_full * n_proj.conj().transpose() symm_projs, kxs = symm.getZnProjectors(xtransl_op, max_cycle_len_translx) for kx, symm_proj in zip(kxs, symm_projs): curr_proj = symm_proj * n_proj if curr_proj.size > 0: projector_list.append(curr_proj) k_list = np.concatenate((k_list, np.array([kx]))) n_list = np.concatenate((n_list, np.array([n]))) max_proj_size = np.max([p.shape[0] for p in projector_list]) mean_proj_size = np.mean([p.shape[0] for p in projector_list]) print("Subspace projectors: max size=%d, mean size=%.1f, number=%d" % (max_proj_size, mean_proj_size, len(projector_list))) # loop over interactions_4 and solve for each symmetry sector
inv_fn = symm.getInversionFn(cx, cy) inv_cycles, _ = symm.findSiteCycles(inv_fn, ss.geometry) inv_op = ss.get_xform_op(inv_cycles) # get projectors on mz subspace mz_projs, mzs = ss.get_subspace_projs(sz_op.tocsr()) # sequentially get projectors on mz the x-translation (then spin flip for mz=0 sector only) projs = [] mzs_all = [] kxs_all = [] spin_parity_all = [] space_parity_all = [] for p, mz in zip(mz_projs, mzs): tx_op_sub = p * tx_op * p.conj().transpose() tx_projs, kxs = symm.getZnProjectors(tx_op_sub, ss.geometry.nsites) if mz == 0: for tp, kx in zip(tx_projs, kxs): sz_flip_op_sub = tp * p * sz_flip_op * p.conj().transpose() * tp.conj().transpose() sz_projs, spin_parities = symm.getZnProjectors(sz_flip_op_sub, 2) spin_parities = np.round(np.exp(1j * spin_parities).real) for pp, parity in zip(sz_projs, spin_parities): if (pp * tp * p).shape[0] != 0: if kx == 0 or kx == np.pi: inv_op_sub = pp * tp * p * inv_op * \ p.conj().transpose() * tp.conj().transpose() * pp.conj().transpose() inv_projs, space_parities = symm.getZnProjectors(inv_op_sub, 2) space_parities = np.round(np.exp(1j * space_parities).real)
# y-translations if not bc2_open: ytransl_fn = symm.getTranslFn(np.array([[0], [1]])) ytransl_cycles, max_cycle_len_transly = symm.findSiteCycles(ytransl_fn, gm) ytransl_op = h.n_projector * h.get_xform_op( ytransl_cycles) * h.n_projector.conj().transpose() # get projectors if not bc1_open and not bc2_open: projs, kxs, kys = symm.get2DTranslationProjectors(xtransl_op, max_cycle_len_translx, ytransl_op, max_cycle_len_transly, print_all) elif not bc2_open: projs, kys = symm.getZnProjectors(ytransl_op, max_cycle_len_transly, print_all) kxs = np.zeros(kys.shape) elif not bc1_open: projs, kxs = symm.getZnProjectors(xtransl_op, max_cycle_len_translx, print_all) kys = np.zeros(kxs.shape) else: projs = [sp.identity(h.geometry.nsites)] # produce operators and structures for storing operators current_op_x = h.n_projector * h.get_current_op(np.array( [[1], [0]])) * h.n_projector.conj().transpose() eigvals_sectors = [] kx_ops_sectors = [] current_ops_x_sector = [] # creation op, site 0
def test_ising_model_5x5(self): """ Test diagonalization of 5x5 ising model with periodic boundary conditions. reference: J. Phys. A: Math. Gen 33 6683 (2000). "Finite-size scaling in the transverse Ising model on a square lattice" by C J Hamer https://doi.org/10.1088/0305-4470/33/38/303 :return: """ cluster = geom.Geometry.createSquareGeometry(5, 5, 0, 0, bc1_open=False, bc2_open=False) # paper definition of hamiltonian differs by a factor of two from mine jz_critical = -2 * 0.32669593806 h_transverse = 2 * 1.0 spin_model = tvi.spinSystem(cluster, jx=0.0, jy=0.0, jz=jz_critical, hx=h_transverse, hy=0.0, hz=0.0, use_ryd_detunes=0) # symmetry swapping up/down spins spin_swap_op = spin_model.get_swap_up_down_op() # x-translations xtransl_fn = symm.getTranslFn(np.array([[1], [0]])) xtransl_cycles, max_cycle_len_translx = symm.findSiteCycles( xtransl_fn, spin_model.geometry) xtransl_op = spin_model.get_xform_op(xtransl_cycles) xtransl_op = xtransl_op # y-translations ytransl_fn = symm.getTranslFn(np.array([[0], [1]])) ytransl_cycles, max_cycle_len_transly = symm.findSiteCycles( ytransl_fn, spin_model.geometry) ytransl_op = spin_model.get_xform_op(ytransl_cycles) ytransl_op = ytransl_op symm_projs, kxs, kys = symm.get2DTranslationProjectors( xtransl_op, max_cycle_len_translx, ytransl_op, max_cycle_len_transly) eig_vals_sectors = [] full_proj_list = [] hfull = spin_model.createH() for ii, proj in enumerate(symm_projs): spin_swap_proj_op = proj * spin_swap_op * proj.conj().transpose() # char_table = np.array([[1, 1], [1, -1]]) # ccs = [[sp.eye(spin_swap_proj_op.shape[0], format="csr")], [spin_swap_proj_op]] swap_projs, phase = symm.getZnProjectors(spin_swap_proj_op, 2) for jj, sproj in enumerate(swap_projs): full_proj_list.append(sproj * proj) h_sector = sproj * proj * hfull * proj.conj().transpose( ) * sproj.conj().transpose() eig_vals_sector, eig_vects_sector = spin_model.diagH( h_sector, print_results=True) eig_vals_sectors.append(eig_vals_sector) # why only accurate to 10 decimal places? eigs_all_sectors = np.sort(np.concatenate(eig_vals_sectors)) min_eig_per_site = eigs_all_sectors[0] / spin_model.geometry.nsites + 1 self.assertAlmostEqual(min_eig_per_site, -0.064637823298, 11)