def tensor_constraint(dim, rank, rots, mappings=None, other_constraits=None): """ rank: of tensor rots: list of rotation matrix (Cartesian) mappings: mapping function (0..N-1 to 0..N-1 one-to-one) """ if rank <= 0: null = scipy.sparse.identity(1) else: dimtensor = dim**rank pi = [list(range(rank))] * len(rots) if mappings is None else mappings assert len(pi) == len(rots), ValueError( 'Number of matrices and mappings %d != %d' % (len(rots), len(pi))) Bmats = [ fct_trans_c(rank, dim, rots[i], pi[i]) - scipy.sparse.identity(dimtensor) for i in range(len(rots)) ] if other_constraits is not None: Bmats.extend([m for m in other_constraits if m.shape[0] > 0]) if len(Bmats) > 0: Bmat = scipy.sparse.vstack(Bmats) null = mychop(get_nullspace(Bmat), 1e-12) else: null = scipy.sparse.identity(dimtensor) return null
def symmetrize_site_tensors(self, tlist): """ symmetrize tensors on atoms, one orbit at a time :param tlist: :return: """ tensors=np.array(tlist) rank = np.array(tensors[0]).ndim dim = tensors[0].shape[0] tensors_s = np.zeros_like(tensors) for i,orb in enumerate(self.orbits): cmat= tensor_constraint(3, rank, [self.spacegroup[ig].rot for ig,pi in orb.isotropy if ig>0]) # print('debug sublatice', i , orb.pointgroup_symbol[0], self.name_orb[i], 'shape', cmat.shape) # print('debug sublat', i, 'cmat', cmat, 'orbit', orb, 'isotropy', orb.isotropy) tr_mat = scipy.sparse.vstack([fct_trans_c(rank, dim, self.spacegroup[orb.clusters_ig[ic]].rot, np.arange(rank, dtype=int)).dot(cmat.T) for ic in range(self.orbits[i].multiplicity)]) t_s = get_symmetrized_lsq(tr_mat, tensors[self.l_list_of_orb[i]].reshape((-1))) tensors_s[self.l_list_of_orb[i]] = t_s.reshape(tensors[self.l_list_of_orb[i]].shape) return tensors_s