3
0
mirror of https://github.com/triqs/dft_tools synced 2024-12-23 04:43:42 +01:00

[block_structure] create_matrix etc.

This commit is contained in:
Gernot J. Kraberger 2018-09-17 13:32:50 +02:00 committed by Hermann Schnait
parent f0b1599379
commit 8e4c923d21
3 changed files with 189 additions and 27 deletions

View File

@ -598,6 +598,36 @@ class BlockStructure(object):
blocks blocks
""" """
return self._create_gf_or_matrix(ish, gf_function, BlockGf, space, **kwargs)
def create_matrix(self, ish=0, space='solver', dtype=np.complex_):
""" Create a zero matrix having the correct structure.
For ``space='solver'``, the structure is according to
``gf_struct_solver``, else according to ``gf_struct_sumk``.
Parameters
----------
ish : int
shell index
If ``space='solver'``, the index of the of the inequivalent correlated shell,
if ``space='sumk'``, the index of the correlated shell
space : 'solver' or 'sumk'
which space the structure should correspond to
"""
def gf_function(indices):
return np.zeros((len(indices), len(indices)), dtype=dtype)
def block_function(name_list, block_list):
d = dict()
for i in range(len(name_list)):
d[name_list[i]] = block_list[i]
return d
return self._create_gf_or_matrix(ish, gf_function, block_function, space)
def _create_gf_or_matrix(self, ish=0, gf_function=GfImFreq, block_function=BlockGf, space='solver', **kwargs):
if space == 'solver': if space == 'solver':
gf_struct = self.gf_struct_solver gf_struct = self.gf_struct_solver
elif space == 'sumk': elif space == 'sumk':
@ -611,7 +641,7 @@ class BlockStructure(object):
for n in names: for n in names:
G = gf_function(indices=gf_struct[ish][n], **kwargs) G = gf_function(indices=gf_struct[ish][n], **kwargs)
blocks.append(G) blocks.append(G)
G = BlockGf(name_list=names, block_list=blocks) G = block_function(name_list=names, block_list=blocks)
return G return G
def check_gf(self, G, ish=None, space='solver'): def check_gf(self, G, ish=None, space='solver'):
@ -636,6 +666,34 @@ class BlockStructure(object):
which space the structure should correspond to which space the structure should correspond to
""" """
return self._check_gf_or_matrix(G, ish, space)
def check_matrix(self, G, ish=None, space='solver'):
""" check whether the matrix G has the right structure
This throws an error if the structure of G is not the same
as ``gf_struct_solver`` (for ``space=solver``) or
``gf_struct_sumk`` (for ``space=sumk``)..
Parameters
----------
G : dict of matrices or list of dict of matrices
matrix to check
if it is a list, there should be as many entries as there
are shells, and the check is performed for all shells (unless
ish is given).
ish : int
shell index
default: 0 if G is just one matrix is given,
check all if list of dicts is given
space : 'solver' or 'sumk'
which space the structure should correspond to
"""
return self._check_gf_or_matrix(G, ish, space)
def _check_gf_or_matrix(self, G, ish=None, space='solver'):
if space == 'solver': if space == 'solver':
gf_struct = self.gf_struct_solver gf_struct = self.gf_struct_solver
elif space == 'sumk': elif space == 'sumk':
@ -658,16 +716,28 @@ class BlockStructure(object):
if ish is None: if ish is None:
ish = 0 ish = 0
for block in gf_struct[ish]: if isinstance(G, BlockGf):
assert block in G.indices,\ for block in gf_struct[ish]:
"block " + block + " not in G (shell {})".format(ish) assert block in G.indices,\
for block, gf in G: "block " + block + " not in G (shell {})".format(ish)
assert block in gf_struct[ish],\ for block, gf in G:
"block " + block + " not in struct (shell {})".format(ish) assert block in gf_struct[ish],\
assert list(gf.indices) == 2 * [map(str, gf_struct[ish][block])],\ "block " + block + " not in struct (shell {})".format(ish)
"block " + block + " has wrong indices (shell {})".format(ish) assert list(gf.indices) == 2 * [map(str, gf_struct[ish][block])],\
"block " + block + \
" has wrong indices (shell {})".format(ish)
else:
for block in gf_struct[ish]:
assert block in G,\
"block " + block + " not in G (shell {})".format(ish)
for block, gf in G.iteritems():
assert block in gf_struct[ish],\
"block " + block + " not in struct (shell {})".format(ish)
assert range(len(gf)) == 2 * [map(str, gf_struct[ish][block])],\
"block " + block + \
" has wrong indices (shell {})".format(ish)
def convert_gf(self, G, G_struct, ish_from=0, ish_to=None, show_warnings=True, def convert_gf(self, G, G_struct=None, ish_from=0, ish_to=None, show_warnings=True,
G_out=None, space_from='solver', space_to='solver', ish=None, **kwargs): G_out=None, space_from='solver', space_to='solver', ish=None, **kwargs):
""" Convert BlockGf from its structure to this structure. """ Convert BlockGf from its structure to this structure.
@ -714,6 +784,56 @@ class BlockStructure(object):
ish_from = ish ish_from = ish
ish_to = ish ish_to = ish
return self._convert_gf_or_matrix(G, G_struct, ish_from, ish_to,
show_warnings, G_out, space_from, space_to, **kwargs)
def convert_matrix(self, G, G_struct=None, ish_from=0, ish_to=None, show_warnings=True,
G_out=None, space_from='solver', space_to='solver'):
""" Convert matrix from its structure to this structure.
.. warning::
Elements that are zero in the new structure due to
the new block structure will be just ignored, thus
approximated to zero.
Parameters
----------
G : dict of numpy array
the matrix that should be converted
G_struct : BlockStructure or str
the structure of that G or None (then, this structure
is used)
ish_from : int
shell index of the input structure
ish_to : int
shell index of the output structure; if None (the default),
it is the same as ish_from
show_warnings : bool or float
whether to show warnings when elements of the Green's
function get thrown away
if float, set the threshold for the magnitude of an element
about to be thrown away to trigger a warning
(default: 1.e-10)
G_out : dict of numpy array
the output numpy array (if not given, a new one is
created)
space_from : 'solver' or 'sumk'
whether the matrix ``G`` corresponds to the
solver or sumk structure of ``G_struct``
space_to : 'solver' or 'sumk'
whether the output matrix should be according to
the solver of sumk structure of this structure
**kwargs :
options passed to the constructor for the new Gf
"""
return self._convert_gf_or_matrix(G, G_struct, ish_from, ish_to,
show_warnings, G_out, space_from, space_to)
def _convert_gf_or_matrix(self, G, G_struct=None, ish_from=0, ish_to=None, show_warnings=True,
G_out=None, space_from='solver', space_to='solver', **kwargs):
if ish_to is None: if ish_to is None:
ish_to = ish_from ish_to = ish_from
@ -751,35 +871,56 @@ class BlockStructure(object):
raise Exception( raise Exception(
"Argument space_to has to be either 'solver' or 'sumk'.") "Argument space_to has to be either 'solver' or 'sumk'.")
# create a Green's function to hold the result if isinstance(G, BlockGf):
if G_out is None: # create a Green's function to hold the result
if not 'mesh' in kwargs and not 'beta' in kwargs: if G_out is None:
kwargs['mesh'] = G.mesh if not 'mesh' in kwargs and not 'beta' in kwargs:
G_out = self.create_gf(ish=ish_to, space=space_to, **kwargs) kwargs['mesh'] = G.mesh
G_out = self.create_gf(ish=ish_to, space=space_to, **kwargs)
else:
self.check_gf(G_out, ish=ish_to, space=space_to)
elif isinstance(G, dict):
if G_out is None:
G_out = self.create_matrix(ish=ish_to, space=space_to)
else:
self.check_matrix(G_out, ish=ish_to, space=space_to)
else: else:
self.check_gf(G_out, ish=ish_to, space=space_to) raise Exception('G is neither BlockGf nor dict.')
for block_to in gf_struct_to.keys(): for block_to in gf_struct_to.keys():
if isinstance(G, BlockGf):
G_out[block_to].zero()
else:
G_out[block_to][:] = 0.0
block_intermediate = block_mapping_to[block_to] block_intermediate = block_mapping_to[block_to]
block_from = block_mapping_from[block_intermediate] block_from = block_mapping_from[block_intermediate]
T_to = eff_trans_to[block_to] T_to = eff_trans_to[block_to]
g_help = G_out[block_to].copy() g_help = G_out[block_to].copy()
for block in block_from: for block in block_from:
T_from = eff_trans_from[block] T_from = eff_trans_from[block]
g_help.from_L_G_R(np.dot(T_to, np.conjugate(np.transpose(T_from))), if isinstance(G, BlockGf):
G[block], g_help.from_L_G_R(np.dot(T_to, np.conjugate(np.transpose(T_from))),
np.dot(T_from, np.conjugate(np.transpose(T_to)))) G[block],
G_out[block_to] << G_out[block_to] + g_help np.dot(T_from, np.conjugate(np.transpose(T_to))))
G_out[block_to] << G_out[block_to] + g_help
else:
g_help = np.dot(np.dot(T_to, np.conjugate(np.transpose(T_from))),
np.dot(G[block],
np.dot(T_from, np.conjugate(np.transpose(T_to)))))
G_out[block_to] += g_help
if show_warnings: if show_warnings:
# we back-transform it # we back-transform it
G_back = G_struct.convert_gf(G_out, self, ish_from=ish_to, G_back = G_struct._convert_gf_or_matrix(G_out, self, ish_from=ish_to,
ish_to=ish_from, ish_to=ish_from,
show_warnings=False, # else we get an endless loop show_warnings=False, # else we get an endless loop
space_from=space_to, space_to=space_from, **kwargs) space_from=space_to, space_to=space_from, **kwargs)
for name, gf in G_back: for name, gf in (G_back if isinstance(G, BlockGf) else G_back.iteritems()):
maxdiff = np.max(np.abs(G_back[name].data - G[name].data), if isinstance(G, BlockGf):
axis=0) maxdiff = np.max(np.abs(G_back[name].data - G[name].data),
axis=0)
else:
maxdiff = G_back[name] - G[name]
if np.any(maxdiff > warning_threshold): if np.any(maxdiff > warning_threshold):
warn('Block {} maximum difference:\n'.format(name) warn('Block {} maximum difference:\n'.format(name)
+ str(maxdiff)) + str(maxdiff))

View File

@ -776,6 +776,9 @@ class SumkDFT(object):
------- -------
G_out G_out
""" """
assert isinstance(G_loc, list), "G_loc must be a list (with elements for each correlated shell)"
if G_out is None: if G_out is None:
G_out = [self.block_structure.create_gf(ish=ish, mesh=G_loc[self.inequiv_to_corr[ish]].mesh) G_out = [self.block_structure.create_gf(ish=ish, mesh=G_loc[self.inequiv_to_corr[ish]].mesh)
for ish in range(self.n_inequiv_shells)] for ish in range(self.n_inequiv_shells)]
@ -1009,6 +1012,8 @@ class SumkDFT(object):
the Green's function transformed into the new block structure the Green's function transformed into the new block structure
""" """
assert isinstance(G, list), "G must be a list (with elements for each correlated shell)"
gf = self._get_hermitian_quantity_from_gf(G) gf = self._get_hermitian_quantity_from_gf(G)
# initialize the variables # initialize the variables

View File

@ -31,6 +31,15 @@ cmp(original_bs.effective_transformation_solver,
'down_0': np.array([[1., 0., 0.], 'down_0': np.array([[1., 0., 0.],
[0., 1., 0.]])}]) [0., 1., 0.]])}])
created_matrix = original_bs.create_matrix()
cmp(created_matrix,
{'up_0': np.array([[0. + 0.j, 0. + 0.j],
[0. + 0.j, 0. + 0.j]]),
'up_1': np.array([[0. + 0.j]]),
'down_1': np.array([[0. + 0.j]]),
'down_0': np.array([[0. + 0.j, 0. + 0.j],
[0. + 0.j, 0. + 0.j]])})
# check pick_gf_struct_solver # check pick_gf_struct_solver
pick1 = original_bs.copy() pick1 = original_bs.copy()
@ -152,6 +161,13 @@ with warnings.catch_warnings(record=True) as w:
assert issubclass(w[-1].category, UserWarning) assert issubclass(w[-1].category, UserWarning)
assert "Block up_1 maximum difference" in str(w[-1].message) assert "Block up_1 maximum difference" in str(w[-1].message)
m2 = map1.convert_matrix(created_matrix, original_bs, show_warnings=True)
cmp(m2,
{'down': np.array([[0. + 0.j, 0. + 0.j, 0. + 0.j],
[0. + 0.j, 0. + 0.j, 0. + 0.j],
[0. + 0.j, 0. + 0.j, 0. + 0.j]]),
'up_0': np.array([[0. + 0.j]]),
'down_1': np.array([[0. + 0.j]])})
# check full_structure # check full_structure
full = BlockStructure.full_structure( full = BlockStructure.full_structure(