2013-07-23 19:49:42 +02:00
|
|
|
|
2016-05-09 10:19:56 +02:00
|
|
|
##########################################################################
|
2013-07-23 19:49:42 +02:00
|
|
|
#
|
|
|
|
# TRIQS: a Toolbox for Research in Interacting Quantum Systems
|
|
|
|
#
|
|
|
|
# Copyright (C) 2011 by M. Aichhorn, L. Pourovskii, V. Vildosola
|
|
|
|
#
|
|
|
|
# TRIQS is free software: you can redistribute it and/or modify it under the
|
|
|
|
# terms of the GNU General Public License as published by the Free Software
|
|
|
|
# Foundation, either version 3 of the License, or (at your option) any later
|
|
|
|
# version.
|
|
|
|
#
|
|
|
|
# TRIQS is distributed in the hope that it will be useful, but WITHOUT ANY
|
|
|
|
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
|
|
|
# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
|
|
|
# details.
|
|
|
|
#
|
|
|
|
# You should have received a copy of the GNU General Public License along with
|
|
|
|
# TRIQS. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
#
|
2016-05-09 10:19:56 +02:00
|
|
|
##########################################################################
|
2013-07-23 19:49:42 +02:00
|
|
|
|
2016-05-09 10:19:56 +02:00
|
|
|
import copy
|
|
|
|
import numpy
|
2013-07-23 19:49:42 +02:00
|
|
|
from types import *
|
2017-04-05 20:58:01 +02:00
|
|
|
from pytriqs.gf import *
|
2013-07-23 19:49:42 +02:00
|
|
|
from pytriqs.archive import *
|
|
|
|
import pytriqs.utility.mpi as mpi
|
|
|
|
|
2016-05-09 10:19:56 +02:00
|
|
|
|
2013-07-23 19:49:42 +02:00
|
|
|
class Symmetry:
|
2015-03-12 00:01:12 +01:00
|
|
|
"""
|
|
|
|
This class provides the routines for applying symmetry operations for the k sums.
|
|
|
|
It contains the permutations of the atoms in the unit cell, and the corresponding
|
|
|
|
rotational matrices for each symmetry operation.
|
|
|
|
"""
|
2013-07-23 19:49:42 +02:00
|
|
|
|
2016-05-09 10:19:56 +02:00
|
|
|
def __init__(self, hdf_file, subgroup=None):
|
2015-03-12 00:01:12 +01:00
|
|
|
"""
|
|
|
|
Initialises the class.
|
2016-05-09 10:19:56 +02:00
|
|
|
|
2015-03-12 00:01:12 +01:00
|
|
|
Parameters
|
|
|
|
----------
|
|
|
|
hdf_file : string
|
|
|
|
Base name of the hdf5 archive with the symmetry data.
|
|
|
|
subgroup : string, optional
|
|
|
|
Name of subgroup storing correlated-shell symmetry data. If not given, it is assumed that
|
|
|
|
the data is stored at the root of the hdf5 archive.
|
|
|
|
"""
|
2013-07-23 19:49:42 +02:00
|
|
|
|
2020-04-08 21:55:39 +02:00
|
|
|
assert isinstance(hdf_file, str), "Symmetry: hdf_file must be a filename."
|
2014-11-14 18:13:43 +01:00
|
|
|
self.hdf_file = hdf_file
|
2016-05-09 10:19:56 +02:00
|
|
|
things_to_read = ['n_symm', 'n_atoms', 'perm',
|
|
|
|
'orbits', 'SO', 'SP', 'time_inv', 'mat', 'mat_tinv']
|
|
|
|
for it in things_to_read:
|
|
|
|
setattr(self, it, 0)
|
2013-07-23 19:49:42 +02:00
|
|
|
|
2014-11-14 18:13:43 +01:00
|
|
|
if mpi.is_master_node():
|
2016-05-09 10:19:56 +02:00
|
|
|
# Read the stuff on master:
|
2018-12-06 23:28:49 +01:00
|
|
|
with HDFArchive(hdf_file, 'r') as ar:
|
|
|
|
if subgroup is None:
|
|
|
|
ar2 = ar
|
|
|
|
else:
|
|
|
|
ar2 = ar[subgroup]
|
2013-07-23 19:49:42 +02:00
|
|
|
|
2018-12-06 23:28:49 +01:00
|
|
|
for it in things_to_read:
|
|
|
|
setattr(self, it, ar2[it])
|
2013-07-23 19:49:42 +02:00
|
|
|
del ar2
|
|
|
|
|
2014-10-31 18:52:32 +01:00
|
|
|
# Broadcasting
|
2016-05-09 10:19:56 +02:00
|
|
|
for it in things_to_read:
|
|
|
|
setattr(self, it, mpi.bcast(getattr(self, it)))
|
2014-09-22 19:24:33 +02:00
|
|
|
|
2013-07-23 19:49:42 +02:00
|
|
|
# now define the mapping of orbitals:
|
2014-11-14 18:13:43 +01:00
|
|
|
# self.orb_map[iorb] = jorb gives the permutation of the orbitals as given in the list, when the
|
2013-07-23 19:49:42 +02:00
|
|
|
# permutation of the atoms is done:
|
|
|
|
self.n_orbits = len(self.orbits)
|
2016-05-09 10:19:56 +02:00
|
|
|
self.orb_map = [[0 for iorb in range(
|
|
|
|
self.n_orbits)] for i_symm in range(self.n_symm)]
|
2014-11-14 18:13:43 +01:00
|
|
|
for i_symm in range(self.n_symm):
|
2013-07-23 19:49:42 +02:00
|
|
|
for iorb in range(self.n_orbits):
|
|
|
|
srch = copy.deepcopy(self.orbits[iorb])
|
2016-05-09 10:19:56 +02:00
|
|
|
srch['atom'] = self.perm[i_symm][self.orbits[iorb]['atom'] - 1]
|
2014-11-14 18:13:43 +01:00
|
|
|
self.orb_map[i_symm][iorb] = self.orbits.index(srch)
|
2014-09-22 19:24:33 +02:00
|
|
|
|
2016-05-09 10:19:56 +02:00
|
|
|
def symmetrize(self, obj):
|
2015-03-12 00:01:12 +01:00
|
|
|
"""
|
|
|
|
Symmetrizes a given object.
|
2016-05-09 10:19:56 +02:00
|
|
|
|
2015-03-12 00:01:12 +01:00
|
|
|
Parameters
|
|
|
|
----------
|
|
|
|
obj : list
|
|
|
|
object to symmetrize. It has to be given as list, where its length is determined by the number
|
|
|
|
of equivalent members of the object. Two types of objects are supported:
|
2016-05-09 10:19:56 +02:00
|
|
|
|
2015-03-12 00:01:12 +01:00
|
|
|
- BlockGf : list of Green's functions,
|
|
|
|
- Matrices : The format is taken from density matrices as obtained from Green's functions (DictType).
|
2016-05-09 10:19:56 +02:00
|
|
|
|
2015-03-12 00:01:12 +01:00
|
|
|
Returns
|
|
|
|
-------
|
|
|
|
symm_obj : list
|
|
|
|
Symmetrized object, of the same type as input object.
|
|
|
|
"""
|
2014-09-22 19:24:33 +02:00
|
|
|
|
2016-05-09 10:19:56 +02:00
|
|
|
assert isinstance(
|
|
|
|
obj, list), "symmetrize: obj has to be a list of objects."
|
|
|
|
assert len(
|
|
|
|
obj) == self.n_orbits, "symmetrize: obj has to be a list of the same length as defined in the init."
|
2013-07-23 19:49:42 +02:00
|
|
|
|
2016-05-09 10:19:56 +02:00
|
|
|
if isinstance(obj[0], BlockGf):
|
|
|
|
# here the result is stored, it is a BlockGf!
|
|
|
|
symm_obj = [obj[i].copy() for i in range(len(obj))]
|
|
|
|
for iorb in range(self.n_orbits):
|
|
|
|
symm_obj[iorb].zero() # set to zero
|
2013-07-23 19:49:42 +02:00
|
|
|
else:
|
2016-05-09 10:19:56 +02:00
|
|
|
# if not a BlockGf, we assume it is a matrix (density matrix), has
|
|
|
|
# to be complex since self.mat is complex!
|
|
|
|
symm_obj = [copy.deepcopy(obj[i]) for i in range(len(obj))]
|
2013-07-23 19:49:42 +02:00
|
|
|
for iorb in range(self.n_orbits):
|
2020-04-08 21:55:39 +02:00
|
|
|
if isinstance(symm_obj[iorb], dict):
|
2016-05-09 10:19:56 +02:00
|
|
|
for ii in symm_obj[iorb]:
|
|
|
|
symm_obj[iorb][ii] *= 0.0
|
2013-07-23 19:49:42 +02:00
|
|
|
else:
|
|
|
|
symm_obj[iorb] *= 0.0
|
2014-09-22 19:24:33 +02:00
|
|
|
|
2014-11-14 18:13:43 +01:00
|
|
|
for i_symm in range(self.n_symm):
|
2013-07-23 19:49:42 +02:00
|
|
|
for iorb in range(self.n_orbits):
|
2014-11-26 16:24:02 +01:00
|
|
|
l = self.orbits[iorb]['l'] # s, p, d, or f
|
|
|
|
dim = self.orbits[iorb]['dim']
|
2014-11-14 18:13:43 +01:00
|
|
|
jorb = self.orb_map[i_symm][iorb]
|
2014-09-22 19:24:33 +02:00
|
|
|
|
2016-05-09 10:19:56 +02:00
|
|
|
if isinstance(obj[0], BlockGf):
|
2014-09-22 19:24:33 +02:00
|
|
|
|
2013-07-23 19:49:42 +02:00
|
|
|
tmp = obj[iorb].copy()
|
2016-05-09 10:19:56 +02:00
|
|
|
if self.time_inv[i_symm]:
|
|
|
|
tmp << tmp.transpose()
|
|
|
|
for bname, gf in tmp:
|
|
|
|
tmp[bname].from_L_G_R(self.mat[i_symm][iorb], tmp[bname], self.mat[
|
|
|
|
i_symm][iorb].conjugate().transpose())
|
|
|
|
tmp *= 1.0 / self.n_symm
|
2013-07-23 19:49:42 +02:00
|
|
|
symm_obj[jorb] += tmp
|
|
|
|
|
|
|
|
else:
|
|
|
|
|
2020-04-08 21:55:39 +02:00
|
|
|
if isinstance(obj[iorb], dict):
|
2013-07-23 19:49:42 +02:00
|
|
|
for ii in obj[iorb]:
|
2014-11-14 18:13:43 +01:00
|
|
|
if self.time_inv[i_symm] == 0:
|
2016-05-09 10:19:56 +02:00
|
|
|
symm_obj[jorb][ii] += numpy.dot(numpy.dot(self.mat[i_symm][iorb], obj[iorb][ii]),
|
2014-11-14 18:13:43 +01:00
|
|
|
self.mat[i_symm][iorb].conjugate().transpose()) / self.n_symm
|
2013-07-23 19:49:42 +02:00
|
|
|
else:
|
2016-05-09 10:19:56 +02:00
|
|
|
symm_obj[jorb][ii] += numpy.dot(numpy.dot(self.mat[i_symm][iorb], obj[iorb][ii].conjugate()),
|
2014-11-14 18:13:43 +01:00
|
|
|
self.mat[i_symm][iorb].conjugate().transpose()) / self.n_symm
|
2013-07-23 19:49:42 +02:00
|
|
|
else:
|
2014-11-14 18:13:43 +01:00
|
|
|
if self.time_inv[i_symm] == 0:
|
2016-05-09 10:19:56 +02:00
|
|
|
symm_obj[jorb] += numpy.dot(numpy.dot(self.mat[i_symm][iorb], obj[iorb]),
|
2014-11-14 18:13:43 +01:00
|
|
|
self.mat[i_symm][iorb].conjugate().transpose()) / self.n_symm
|
2013-07-23 19:49:42 +02:00
|
|
|
else:
|
2016-05-09 10:19:56 +02:00
|
|
|
symm_obj[jorb] += numpy.dot(numpy.dot(self.mat[i_symm][iorb], obj[iorb].conjugate()),
|
2014-11-14 18:13:43 +01:00
|
|
|
self.mat[i_symm][iorb].conjugate().transpose()) / self.n_symm
|
2014-09-22 19:24:33 +02:00
|
|
|
|
2014-10-31 18:52:32 +01:00
|
|
|
# Markus: This does not what it is supposed to do, check how this should work (keep for now)
|
2014-11-14 18:13:43 +01:00
|
|
|
# if (self.SO == 0) and (self.SP == 0):
|
2013-07-23 19:49:42 +02:00
|
|
|
# # add time inv:
|
|
|
|
#mpi.report("Add time inversion")
|
|
|
|
# for iorb in range(self.n_orbits):
|
|
|
|
# if (isinstance(symm_obj[0],BlockGf)):
|
|
|
|
# tmp = symm_obj[iorb].copy()
|
2014-10-28 16:19:28 +01:00
|
|
|
# tmp << tmp.transpose()
|
2014-11-14 09:43:28 +01:00
|
|
|
# for bname,gf in tmp: tmp[bname].from_L_G_R(self.mat_tinv[iorb],tmp[bname],self.mat_tinv[iorb].transpose().conjugate())
|
2013-07-23 19:49:42 +02:00
|
|
|
# symm_obj[iorb] += tmp
|
|
|
|
# symm_obj[iorb] /= 2.0
|
2014-09-22 19:24:33 +02:00
|
|
|
#
|
2013-07-23 19:49:42 +02:00
|
|
|
# else:
|
2020-04-08 21:55:39 +02:00
|
|
|
# if isinstance(symm_obj[iorb], dict):
|
2013-07-23 19:49:42 +02:00
|
|
|
# for ii in symm_obj[iorb]:
|
|
|
|
# symm_obj[iorb][ii] += numpy.dot(numpy.dot(self.mat_tinv[iorb],symm_obj[iorb][ii].conjugate()),
|
|
|
|
# self.mat_tinv[iorb].transpose().conjugate())
|
|
|
|
# symm_obj[iorb][ii] /= 2.0
|
|
|
|
# else:
|
|
|
|
# symm_obj[iorb] += numpy.dot(numpy.dot(self.mat_tinv[iorb],symm_obj[iorb].conjugate()),
|
|
|
|
# self.mat_tinv[iorb].transpose().conjugate())
|
|
|
|
# symm_obj[iorb] /= 2.0
|
2014-09-22 19:24:33 +02:00
|
|
|
|
2013-07-23 19:49:42 +02:00
|
|
|
return symm_obj
|