From 6c908e9c6e7f29179f8f8895afc0cf4f03a76ae7 Mon Sep 17 00:00:00 2001 From: "Gernot J. Kraberger" <16017581+gkraberger@users.noreply.github.com> Date: Wed, 29 Aug 2018 11:29:46 +0200 Subject: [PATCH 01/57] block_structure: add check_gf method --- python/block_structure.py | 40 ++++++++++++++++++++++++ test/blockstructure.py | 65 ++++++++++++++++++++------------------- 2 files changed, 74 insertions(+), 31 deletions(-) diff --git a/python/block_structure.py b/python/block_structure.py index f1501409..21f8e790 100644 --- a/python/block_structure.py +++ b/python/block_structure.py @@ -281,6 +281,46 @@ class BlockStructure(object): G = BlockGf(name_list = names, block_list = blocks) return G + def check_gf(self, G, ish=None): + """ check whether the Green's function G has the right structure + This throws an error if the structure of G is not the same + as ``gf_struct_solver``. + + Parameters + ---------- + G : BlockGf or list of BlockGf + Green's function 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 Green's function is given, + check all if list of Green's functions is given + """ + + if isinstance(G, list): + assert len(G) == len(self.gf_struct_solver),\ + "list of G does not have the correct length" + if ish is None: + ishs = range(len(self.gf_struct_solver)) + else: + ishs = [ish] + for ish in ishs: + self.check_gf(G[ish], ish=ish) + return + + if ish is None: + ish = 0 + + for block in self.gf_struct_solver[ish]: + assert block in G.indices,\ + "block " + block + " not in G (shell {})".format(ish) + for block, gf in G: + assert block in self.gf_struct_solver[ish],\ + "block " + block + " not in struct (shell {})".format(ish) + assert list(gf.indices) == 2 * [map(str, self.gf_struct_solver[ish][block])],\ + "block " + block + " has wrong indices (shell {})".format(ish) def convert_gf(self,G,G_struct,ish=0,show_warnings=True,**kwargs): """ Convert BlockGf from its structure to this structure. diff --git a/test/blockstructure.py b/test/blockstructure.py index f7a68e5b..0123a141 100644 --- a/test/blockstructure.py +++ b/test/blockstructure.py @@ -4,7 +4,7 @@ from pytriqs.gf import * from pytriqs.utility.comparison_tests import assert_block_gfs_are_close from triqs_dft_tools.block_structure import BlockStructure -SK = SumkDFT('blockstructure.in.h5',use_dft_blocks=True) +SK = SumkDFT('blockstructure.in.h5', use_dft_blocks=True) original_bs = SK.block_structure @@ -13,56 +13,59 @@ pick1 = original_bs.copy() pick1.pick_gf_struct_solver([{'up_0': [1], 'up_1': [0], 'down_1': [0]}]) # check loading a block_structure from file -SK.block_structure = SK.load(['block_structure'],'mod')[0] +SK.block_structure = SK.load(['block_structure'], 'mod')[0] assert SK.block_structure == pick1, 'loading SK block structure from file failed' # check SumkDFT backward compatibility -sk_pick1 = BlockStructure(gf_struct_sumk = SK.gf_struct_sumk, - gf_struct_solver = SK.gf_struct_solver, - solver_to_sumk = SK.solver_to_sumk, - sumk_to_solver = SK.sumk_to_solver, - solver_to_sumk_block = SK.solver_to_sumk_block, - deg_shells = SK.deg_shells) +sk_pick1 = BlockStructure(gf_struct_sumk=SK.gf_struct_sumk, + gf_struct_solver=SK.gf_struct_solver, + solver_to_sumk=SK.solver_to_sumk, + sumk_to_solver=SK.sumk_to_solver, + solver_to_sumk_block=SK.solver_to_sumk_block, + deg_shells=SK.deg_shells) assert sk_pick1 == pick1, 'constructing block structure from SumkDFT properties failed' # check pick_gf_struct_sumk pick2 = original_bs.copy() -pick2.pick_gf_struct_sumk([{'up': [1, 2], 'down': [0,1]}]) +pick2.pick_gf_struct_sumk([{'up': [1, 2], 'down': [0, 1]}]) # check map_gf_struct_solver -mapping = [{ ('down_0', 0):('down', 0), - ('down_0', 1):('down', 2), - ('down_1', 0):('down', 1), - ('up_0', 0) :('down_1', 0), - ('up_0', 1) :('up_0', 0) }] +mapping = [{('down_0', 0): ('down', 0), + ('down_0', 1): ('down', 2), + ('down_1', 0): ('down', 1), + ('up_0', 0): ('down_1', 0), + ('up_0', 1): ('up_0', 0)}] map1 = original_bs.copy() map1.map_gf_struct_solver(mapping) # check create_gf -G1 = original_bs.create_gf(beta=40,n_points=3) +G1 = original_bs.create_gf(beta=40, n_points=3) i = 1 -for block,gf in G1: +for block, gf in G1: gf << SemiCircular(i) - i+=1 + i += 1 +original_bs.check_gf(G1) +original_bs.check_gf([G1]) # check approximate_as_diagonal offd = original_bs.copy() offd.approximate_as_diagonal() # check map_gf_struct_solver -G2 = map1.convert_gf(G1,original_bs,beta=40,n_points=3,show_warnings=False) +G2 = map1.convert_gf(G1, original_bs, beta=40, n_points=3, show_warnings=False) # check full_structure -full = BlockStructure.full_structure([{'up_0': [0, 1], 'up_1': [0], 'down_1': [0], 'down_0': [0, 1]}],None) +full = BlockStructure.full_structure( + [{'up_0': [0, 1], 'up_1': [0], 'down_1': [0], 'down_0': [0, 1]}], None) # check __eq__ -assert full==full, 'equality not correct (equal structures not equal)' -assert pick1==pick1, 'equality not correct (equal structures not equal)' -assert pick1!=pick2, 'equality not correct (different structures not different)' -assert original_bs!=offd, 'equality not correct (different structures not different)' +assert full == full, 'equality not correct (equal structures not equal)' +assert pick1 == pick1, 'equality not correct (equal structures not equal)' +assert pick1 != pick2, 'equality not correct (different structures not different)' +assert original_bs != offd, 'equality not correct (different structures not different)' if mpi.is_master_node(): - with HDFArchive('blockstructure.out.h5','w') as ar: + with HDFArchive('blockstructure.out.h5', 'w') as ar: ar['original_bs'] = original_bs ar['pick1'] = pick1 ar['pick2'] = pick2 @@ -75,10 +78,10 @@ if mpi.is_master_node(): # cannot use h5diff because BlockStructure testing is not implemented # there (and seems difficult to implement because it would mix triqs # and dft_tools) - with HDFArchive('blockstructure.out.h5','r') as ar,\ - HDFArchive('blockstructure.ref.h5','r') as ar2: - for k in ar2: - if isinstance(ar[k],BlockGf): - assert_block_gfs_are_close(ar[k],ar2[k],1.e-6) - else: - assert ar[k]==ar2[k], '{} not equal'.format(k) + with HDFArchive('blockstructure.out.h5', 'r') as ar,\ + HDFArchive('blockstructure.ref.h5', 'r') as ar2: + for k in ar2: + if isinstance(ar[k], BlockGf): + assert_block_gfs_are_close(ar[k], ar2[k], 1.e-6) + else: + assert ar[k] == ar2[k], '{} not equal'.format(k) From 2b490d14857c3b00bb0aea6b013fe4a05d8097f4 Mon Sep 17 00:00:00 2001 From: "Gernot J. Kraberger" <16017581+gkraberger@users.noreply.github.com> Date: Wed, 29 Aug 2018 12:03:14 +0200 Subject: [PATCH 02/57] block_structure: convert_gf: add G_out, let G_struct be sumk --- python/block_structure.py | 63 ++++++++++++++++++++++++++------------- test/blockstructure.py | 13 ++++++-- 2 files changed, 53 insertions(+), 23 deletions(-) diff --git a/python/block_structure.py b/python/block_structure.py index 21f8e790..0f792d2a 100644 --- a/python/block_structure.py +++ b/python/block_structure.py @@ -283,6 +283,7 @@ class BlockStructure(object): def check_gf(self, G, ish=None): """ check whether the Green's function G has the right structure + This throws an error if the structure of G is not the same as ``gf_struct_solver``. @@ -322,8 +323,9 @@ class BlockStructure(object): assert list(gf.indices) == 2 * [map(str, self.gf_struct_solver[ish][block])],\ "block " + block + " has wrong indices (shell {})".format(ish) - def convert_gf(self,G,G_struct,ish=0,show_warnings=True,**kwargs): - """ Convert BlockGf from its structure to this structure. + def convert_gf(self, G, G_struct, ish=0, show_warnings=True, + G_out=None, **kwargs): + """ Convert BlockGf from its structure to this (solver) structure. .. warning:: @@ -335,8 +337,9 @@ class BlockStructure(object): ---------- G : BlockGf the Gf that should be converted - G_struct : GfStructure - the structure of that G + G_struct : BlockStructure or str + the structure of that G or 'sumk' (then, the structure of + the sumk Green's function of this BlockStructure is used) ish : int shell index show_warnings : bool or float @@ -354,30 +357,50 @@ class BlockStructure(object): warning_threshold = show_warnings show_warnings = True - G_new = self.create_gf(ish=ish,**kwargs) - for block in G_struct.gf_struct_solver[ish].keys(): - for i1 in G_struct.gf_struct_solver[ish][block]: - for i2 in G_struct.gf_struct_solver[ish][block]: - i1_sumk = G_struct.solver_to_sumk[ish][(block,i1)] - i2_sumk = G_struct.solver_to_sumk[ish][(block,i2)] + # we offer the possibility to convert to convert from sumk_dft + from_sumk = False + if isinstance(G_struct, str) and G_struct == 'sumk': + gf_struct_in = {block: indices + for block, indices in self.gf_struct_sumk[ish]} + from_sumk = True + else: + gf_struct_in = G_struct.gf_struct_solver[ish] + + # create a Green's function to hold the result + if G_out is None: + G_out = self.create_gf(ish=ish, **kwargs) + else: + self.check_gf(G_out, ish=ish) + + for block in gf_struct_in.keys(): + for i1 in gf_struct_in[block]: + for i2 in gf_struct_in[block]: + if from_sumk: + i1_sumk = (block, i1) + i2_sumk = (block, i2) + else: + i1_sumk = G_struct.solver_to_sumk[ish][(block, i1)] + i2_sumk = G_struct.solver_to_sumk[ish][(block, i2)] + i1_sol = self.sumk_to_solver[ish][i1_sumk] i2_sol = self.sumk_to_solver[ish][i2_sumk] if i1_sol[0] is None or i2_sol[0] is None: if show_warnings: if mpi.is_master_node(): - warn(('Element {},{} of block {} of G is not present '+ - 'in the new structure').format(i1,i2,block)) + warn(('Element {},{} of block {} of G is not present ' + + 'in the new structure').format(i1, i2, block)) continue - if i1_sol[0]!=i2_sol[0]: - if show_warnings and np.max(np.abs(G[block][i1,i2].data)) > warning_threshold: + if i1_sol[0] != i2_sol[0]: + if (show_warnings and + np.max(np.abs(G[block][i1, i2].data)) > warning_threshold): if mpi.is_master_node(): - warn(('Element {},{} of block {} of G is approximated '+ - 'to zero to match the new structure. Max abs value: {}').format( - i1,i2,block,np.max(np.abs(G[block][i1,i2].data)))) + warn(('Element {},{} of block {} of G is approximated ' + + 'to zero to match the new structure. Max abs value: {}').format( + i1, i2, block, np.max(np.abs(G[block][i1, i2].data)))) continue - G_new[i1_sol[0]][i1_sol[1],i2_sol[1]] = \ - G[block][i1,i2] - return G_new + G_out[i1_sol[0]][i1_sol[1], i2_sol[1]] = \ + G[block][i1, i2] + return G_out def approximate_as_diagonal(self): """ Create a structure for a GF with zero off-diagonal elements. diff --git a/test/blockstructure.py b/test/blockstructure.py index 0123a141..b96f38aa 100644 --- a/test/blockstructure.py +++ b/test/blockstructure.py @@ -40,10 +40,9 @@ map1.map_gf_struct_solver(mapping) # check create_gf G1 = original_bs.create_gf(beta=40, n_points=3) -i = 1 +widths = dict(up_0=1, up_1=2, down_0=4, down_1=3) for block, gf in G1: - gf << SemiCircular(i) - i += 1 + gf << SemiCircular(widths[block]) original_bs.check_gf(G1) original_bs.check_gf([G1]) @@ -58,6 +57,14 @@ G2 = map1.convert_gf(G1, original_bs, beta=40, n_points=3, show_warnings=False) full = BlockStructure.full_structure( [{'up_0': [0, 1], 'up_1': [0], 'down_1': [0], 'down_0': [0, 1]}], None) +G_sumk = BlockGf(mesh=G1.mesh, gf_struct=original_bs.gf_struct_sumk[0]) +for i in range(3): + G_sumk['up'][i, i] << SemiCircular(1 if i < 2 else 2) + G_sumk['down'][i, i] << SemiCircular(4 if i < 2 else 3) +G3 = original_bs.convert_gf(G_sumk, 'sumk', beta=40, n_points=3) +assert_block_gfs_are_close(G1, G3) + + # check __eq__ assert full == full, 'equality not correct (equal structures not equal)' assert pick1 == pick1, 'equality not correct (equal structures not equal)' From f0de5c62b59ad37fcff88fbf3f8d979309476561 Mon Sep 17 00:00:00 2001 From: "Gernot J. Kraberger" <16017581+gkraberger@users.noreply.github.com> Date: Wed, 29 Aug 2018 19:36:20 +0200 Subject: [PATCH 03/57] block_structure: add gf_struct_***_list and _dict now sumk is given in the list format and solver is given in the dict format --- python/block_structure.py | 84 +++++++++++++++++++++++++++++++++++---- python/sumk_dft.py | 16 ++++++++ test/blockstructure.py | 8 ++++ 3 files changed, 100 insertions(+), 8 deletions(-) diff --git a/python/block_structure.py b/python/block_structure.py index 0f792d2a..c5f0bf68 100644 --- a/python/block_structure.py +++ b/python/block_structure.py @@ -5,6 +5,7 @@ from ast import literal_eval import pytriqs.utility.mpi as mpi from warnings import warn + class BlockStructure(object): """ Contains information about the Green function structure. @@ -37,12 +38,13 @@ class BlockStructure(object): maps from the solver block to the sumk block for *inequivalent* correlated shell ish """ - def __init__(self,gf_struct_sumk=None, - gf_struct_solver=None, - solver_to_sumk=None, - sumk_to_solver=None, - solver_to_sumk_block=None, - deg_shells=None): + + def __init__(self, gf_struct_sumk=None, + gf_struct_solver=None, + solver_to_sumk=None, + sumk_to_solver=None, + solver_to_sumk_block=None, + deg_shells=None): self.gf_struct_sumk = gf_struct_sumk self.gf_struct_solver = gf_struct_solver self.solver_to_sumk = solver_to_sumk @@ -50,6 +52,73 @@ class BlockStructure(object): self.solver_to_sumk_block = solver_to_sumk_block self.deg_shells = deg_shells + @property + def gf_struct_solver_list(self): + """ The structure of the solver Green's function + + This is returned as a + list (for each shell) + of lists (for each block) + of tuples (block_name, block_indices). + + That is, + ``gf_struct_solver_list[ish][b][0]`` + is the name of the block number ``b`` of shell ``ish``, and + ``gf_struct_solver_list[ish][b][1]`` + is a list of its indices. + + The list for each shell is sorted alphabetically by block name. + """ + # we sort by block name in order to get a reproducible result + return [sorted([(k, v) for k, v in gfs.iteritems()], key=lambda x: x[0]) + for gfs in self.gf_struct_solver] + + @property + def gf_struct_sumk_list(self): + """ The structure of the sumk Green's function + + This is returned as a + list (for each shell) + of lists (for each block) + of tuples (block_name, block_indices) + + That is, + ``gf_struct_sumk_list[ish][b][0]`` + is the name of the block number ``b`` of shell ``ish``, and + ``gf_struct_sumk_list[ish][b][1]`` + is a list of its indices. + """ + return self.gf_struct_sumk + + @property + def gf_struct_solver_dict(self): + """ The structure of the solver Green's function + + This is returned as a + list (for each shell) + of dictionaries. + + That is, + ``gf_struct_solver_dict[ish][bname]`` + is a list of the indices of block ``bname`` of shell ``ish``. + """ + return self.gf_struct_solver + + @property + def gf_struct_sumk_dict(self): + """ The structure of the sumk Green's function + + This is returned as a + list (for each shell) + of dictionaries. + + That is, + ``gf_struct_sumk_dict[ish][bname]`` + is a list of the indices of block ``bname`` of shell ``ish``. + """ + return [{block: indices for block, indices in gfs} + for gfs in self.gf_struct_sumk] + @classmethod def full_structure(cls,gf_struct,corr_to_inequiv): """ Construct structure that maps to itself. @@ -360,8 +429,7 @@ class BlockStructure(object): # we offer the possibility to convert to convert from sumk_dft from_sumk = False if isinstance(G_struct, str) and G_struct == 'sumk': - gf_struct_in = {block: indices - for block, indices in self.gf_struct_sumk[ish]} + gf_struct_in = self.gf_struct_sumk_dict[ish] from_sumk = True else: gf_struct_in = G_struct.gf_struct_solver[ish] diff --git a/python/sumk_dft.py b/python/sumk_dft.py index 825b6b5d..66d7faac 100644 --- a/python/sumk_dft.py +++ b/python/sumk_dft.py @@ -2057,3 +2057,19 @@ class SumkDFT(object): def __set_deg_shells(self,value): self.block_structure.deg_shells = value deg_shells = property(__get_deg_shells,__set_deg_shells) + + @property + def gf_struct_solver_list(self): + return self.block_structure.gf_struct_solver_list + + @property + def gf_struct_sumk_list(self): + return self.block_structure.gf_struct_sumk_list + + @property + def gf_struct_solver_dict(self): + return self.block_structure.gf_struct_solver_dict + + @property + def gf_struct_sumk_dict(self): + return self.block_structure.gf_struct_sumk_dict diff --git a/test/blockstructure.py b/test/blockstructure.py index b96f38aa..eac85863 100644 --- a/test/blockstructure.py +++ b/test/blockstructure.py @@ -64,6 +64,14 @@ for i in range(3): G3 = original_bs.convert_gf(G_sumk, 'sumk', beta=40, n_points=3) assert_block_gfs_are_close(G1, G3) +assert original_bs.gf_struct_sumk_list ==\ + [[('up', [0, 1, 2]), ('down', [0, 1, 2])]] +assert original_bs.gf_struct_solver_dict ==\ + [{'up_0': [0, 1], 'up_1': [0], 'down_1': [0], 'down_0': [0, 1]}] +assert original_bs.gf_struct_sumk_dict ==\ + [{'down': [0, 1, 2], 'up': [0, 1, 2]}] +assert original_bs.gf_struct_solver_list ==\ + [[('down_0', [0, 1]), ('down_1', [0]), ('up_0', [0, 1]), ('up_1', [0])]] # check __eq__ assert full == full, 'equality not correct (equal structures not equal)' From d0f0c208650e5e8bc68de0014ca745a24e534498 Mon Sep 17 00:00:00 2001 From: "Gernot J. Kraberger" <16017581+gkraberger@users.noreply.github.com> Date: Thu, 30 Aug 2018 20:24:21 +0200 Subject: [PATCH 04/57] change isinstance for new TRIQS this fixes test analyse_block_structure_from_gf --- python/sumk_dft.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/python/sumk_dft.py b/python/sumk_dft.py index 66d7faac..5f84a3e5 100644 --- a/python/sumk_dft.py +++ b/python/sumk_dft.py @@ -868,7 +868,7 @@ class SumkDFT(object): the output G(tau) or A(w) """ # make a GfImTime from the supplied GfImFreq - if all(isinstance(g_sh._first(), GfImFreq) for g_sh in G): + if all(isinstance(g_sh.mesh, MeshImFreq) for g_sh in G): gf = [BlockGf(name_block_generator = [(name, GfImTime(beta=block.mesh.beta, indices=block.indices,n_points=len(block.mesh)+1)) for name, block in g_sh], make_copies=False) for g_sh in G] @@ -876,15 +876,15 @@ class SumkDFT(object): for name, g in gf[ish]: g.set_from_inverse_fourier(G[ish][name]) # keep a GfImTime from the supplied GfImTime - elif all(isinstance(g_sh._first(), GfImTime) for g_sh in G): + elif all(isinstance(g_sh.mesh, MeshImTime) for g_sh in G): gf = G # make a spectral function from the supplied GfReFreq - elif all(isinstance(g_sh._first(), GfReFreq) for g_sh in G): + elif all(isinstance(g_sh.mesh, MeshReFreq) for g_sh in G): gf = [g_sh.copy() for g_sh in G] for ish in range(len(gf)): for name, g in gf[ish]: g << 1.0j*(g-g.conjugate().transpose())/2.0/numpy.pi - elif all(isinstance(g_sh._first(), GfReTime) for g_sh in G): + elif all(isinstance(g_sh.mesh, MeshReTime) for g_sh in G): def get_delta_from_mesh(mesh): w0 = None for w in mesh: From ef979199af73f2987b9c0a2fe07fb64a53b99174 Mon Sep 17 00:00:00 2001 From: "Gernot J. Kraberger" <16017581+gkraberger@users.noreply.github.com> Date: Thu, 30 Aug 2018 20:49:12 +0200 Subject: [PATCH 05/57] sumk_dft: split transform_to_solver_blocks from extract_G_loc this is done in a backward-compatible manner --- python/block_structure.py | 28 +++++++++++++++ python/sumk_dft.py | 76 ++++++++++++++++++++++++++++----------- 2 files changed, 83 insertions(+), 21 deletions(-) diff --git a/python/block_structure.py b/python/block_structure.py index c5f0bf68..2af7dffe 100644 --- a/python/block_structure.py +++ b/python/block_structure.py @@ -1,3 +1,28 @@ + +########################################################################## +# +# TRIQS: a Toolbox for Research in Interacting Quantum Systems +# +# Copyright (C) 2018 by G. J. Kraberger +# Copyright (C) 2018 by Simons Foundation +# Authors: G. J. Kraberger, O. Parcollet +# +# 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 . +# +########################################################################## + + import copy import numpy as np from pytriqs.gf import GfImFreq, BlockGf @@ -417,6 +442,9 @@ class BlockStructure(object): 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 : BlockGf + the output Green's function (if not given, a new one is + created) **kwargs : options passed to the constructor for the new Gf """ diff --git a/python/sumk_dft.py b/python/sumk_dft.py index 5f84a3e5..23b91593 100644 --- a/python/sumk_dft.py +++ b/python/sumk_dft.py @@ -3,6 +3,7 @@ # # TRIQS: a Toolbox for Research in Interacting Quantum Systems # +# Copyright (C) 2018 by G. J. Kraberger # Copyright (C) 2011 by M. Aichhorn, L. Pourovskii, V. Vildosola # # TRIQS is free software: you can redistribute it and/or modify it under the @@ -631,29 +632,34 @@ class SumkDFT(object): for bname, gf in SK_Sigma_imp[icrsh]: gf << self.rotloc(icrsh, gf, direction='toGlobal') - def extract_G_loc(self, mu=None, iw_or_w='iw', with_Sigma=True, with_dc=True, broadening=None): + def extract_G_loc(self, mu=None, iw_or_w='iw', with_Sigma=True, with_dc=True, broadening=None, + transform_to_solver_blocks=True): r""" Extracts the local downfolded Green function by the Brillouin-zone integration of the lattice Green's function. Parameters ---------- mu : real, optional - Input chemical potential. If not provided the value of self.chemical_potential is used as mu. + Input chemical potential. If not provided the value of self.chemical_potential is used as mu. with_Sigma : boolean, optional - If True then the local GF is calculated with the self-energy self.Sigma_imp. + If True then the local GF is calculated with the self-energy self.Sigma_imp. with_dc : boolean, optional - If True then the double-counting correction is subtracted from the self-energy in calculating the GF. + If True then the double-counting correction is subtracted from the self-energy in calculating the GF. broadening : float, optional - Imaginary shift for the axis along which the real-axis GF is calculated. - If not provided, broadening will be set to double of the distance between mesh points in 'mesh'. - Only relevant for real-frequency GF. + Imaginary shift for the axis along which the real-axis GF is calculated. + If not provided, broadening will be set to double of the distance between mesh points in 'mesh'. + Only relevant for real-frequency GF. + transform_to_solver_blocks : bool, optional + If True (default), the returned G_loc will be transformed to the block structure ``gf_struct_solver``, + else it will be in ``gf_struct_sumk``. Returns ------- - G_loc_inequiv : list of BlockGf (Green's function) objects - List of the local Green's functions for all inequivalent correlated shells, - rotated into the corresponding local frames. - + G_loc : list of BlockGf (Green's function) objects + List of the local Green's functions for all (inequivalent) correlated shells, + rotated into the corresponding local frames. + If ``transform_to_solver_blocks`` is True, it will be one per correlated shell, else one per + inequivalent correlated shell. """ if mu is None: @@ -712,20 +718,48 @@ class SumkDFT(object): G_loc[icrsh][bname] << self.rotloc( icrsh, gf, direction='toLocal') + if transform_to_solver_blocks: + return self.transform_to_solver_blocks(G_loc) + + return G_loc + + def transform_to_solver_blocks(self, G_loc, G_out=None): + """ transform G_loc from sumk to solver space + + Parameters + ---------- + G_loc : list of BlockGf + a list of one BlockGf per correlated shell with a structure + according to ``gf_struct_sumk``, e.g. as returned by + :py:meth:`.extract_G_loc` with ``transform_to_solver_blocks=False``. + G_out : list of BlockGf + a list of one BlockGf per *inequivalent* correlated shell + with a structure according to ``gf_struct_solver``. + The output Green's function (if not given, a new one is + created) + + Returns + ------- + G_out + """ + if G_out is None: + G_out = [BlockGf(mesh=G_loc[0].mesh, + gf_struct=[(k, v) for k, v in self.gf_struct_solver[ish].iteritems()]) + for ish in range(self.n_inequiv_shells)] + else: + for ish in range(self.n_inequiv_shells): + self.block_structure.check_gf(G_out, ish=ish) + # transform to CTQMC blocks: for ish in range(self.n_inequiv_shells): - for block, inner in self.gf_struct_solver[ish].iteritems(): - for ind1 in inner: - for ind2 in inner: - block_sumk, ind1_sumk = self.solver_to_sumk[ - ish][(block, ind1)] - block_sumk, ind2_sumk = self.solver_to_sumk[ - ish][(block, ind2)] - G_loc_inequiv[ish][block][ind1, ind2] << G_loc[ - self.inequiv_to_corr[ish]][block_sumk][ind1_sumk, ind2_sumk] + self.block_structure.convert_gf( + G=G_loc[self.inequiv_to_corr[ish]], + G_struct='sumk', + ish=ish, + G_out=G_out[ish]) # return only the inequivalent shells: - return G_loc_inequiv + return G_out def analyse_block_structure(self, threshold=0.00001, include_shells=None, dm=None, hloc=None): r""" From d8a26931234ca6f8aa0eac0345ce1b93084c0435 Mon Sep 17 00:00:00 2001 From: "Gernot J. Kraberger" <16017581+gkraberger@users.noreply.github.com> Date: Thu, 30 Aug 2018 21:55:59 +0200 Subject: [PATCH 06/57] block_structure: introduce space parameter in methods convert_gf, create_gf, check_gf --- python/block_structure.py | 125 +++++++++++++++++++++++++++----------- python/sumk_dft.py | 9 +-- test/blockstructure.py | 2 +- 3 files changed, 96 insertions(+), 40 deletions(-) diff --git a/python/block_structure.py b/python/block_structure.py index 2af7dffe..e256dfcb 100644 --- a/python/block_structure.py +++ b/python/block_structure.py @@ -349,8 +349,11 @@ class BlockStructure(object): self.sumk_to_solver[ish]=su2so self.solver_to_sumk_block[ish]=so2su_block - def create_gf(self,ish=0,gf_function=GfImFreq,**kwargs): - """ Create a zero BlockGf having the gf_struct_solver structure. + def create_gf(self, ish=0, gf_function=GfImFreq, space='solver', **kwargs): + """ Create a zero BlockGf having the correct structure. + + For ``space='solver'``, the structure is according to + ``gf_struct_solver``, else according to ``gf_struct_sumk``. When using GfImFreq as gf_function, typically you have to supply beta as keyword argument. @@ -359,27 +362,40 @@ class BlockStructure(object): ---------- 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 gf_function : constructor function used to construct the Gf objects constituting the individual blocks; default: GfImFreq + space : 'solver' or 'sumk' + which space the structure should correspond to **kwargs : options passed on to the Gf constructor for the individual blocks """ - names = self.gf_struct_solver[ish].keys() - blocks=[] + if space == 'solver': + gf_struct = self.gf_struct_solver + elif space == 'sumk': + gf_struct = self.gf_struct_sumk_dict + else: + raise Exception( + "Argument space has to be either 'solver' or 'sumk'.") + + names = gf_struct[ish].keys() + blocks = [] for n in names: - G = gf_function(indices=self.gf_struct_solver[ish][n],**kwargs) + G = gf_function(indices=gf_struct[ish][n], **kwargs) blocks.append(G) - G = BlockGf(name_list = names, block_list = blocks) + G = BlockGf(name_list=names, block_list=blocks) return G - def check_gf(self, G, ish=None): + def check_gf(self, G, ish=None, space='solver'): """ check whether the Green's function G has the right structure This throws an error if the structure of G is not the same - as ``gf_struct_solver``. + as ``gf_struct_solver`` (for ``space=solver``) or + ``gf_struct_sumk`` (for ``space=sumk``).. Parameters ---------- @@ -392,34 +408,44 @@ class BlockStructure(object): shell index default: 0 if G is just one Green's function is given, check all if list of Green's functions is given + space : 'solver' or 'sumk' + which space the structure should correspond to """ + if space == 'solver': + gf_struct = self.gf_struct_solver + elif space == 'sumk': + gf_struct = self.gf_struct_sumk_dict + else: + raise Exception( + "Argument space has to be either 'solver' or 'sumk'.") + if isinstance(G, list): - assert len(G) == len(self.gf_struct_solver),\ + assert len(G) == len(gf_struct),\ "list of G does not have the correct length" if ish is None: - ishs = range(len(self.gf_struct_solver)) + ishs = range(len(gf_struct)) else: ishs = [ish] for ish in ishs: - self.check_gf(G[ish], ish=ish) + self.check_gf(G[ish], ish=ish, space=space) return if ish is None: ish = 0 - for block in self.gf_struct_solver[ish]: + for block in gf_struct[ish]: assert block in G.indices,\ "block " + block + " not in G (shell {})".format(ish) for block, gf in G: - assert block in self.gf_struct_solver[ish],\ + assert block in gf_struct[ish],\ "block " + block + " not in struct (shell {})".format(ish) - assert list(gf.indices) == 2 * [map(str, self.gf_struct_solver[ish][block])],\ + assert list(gf.indices) == 2 * [map(str, gf_struct[ish][block])],\ "block " + block + " has wrong indices (shell {})".format(ish) - def convert_gf(self, G, G_struct, ish=0, show_warnings=True, - G_out=None, **kwargs): - """ Convert BlockGf from its structure to this (solver) structure. + def convert_gf(self, G, G_struct, ish_from=0, ish_to=None, show_warnings=True, + G_out=None, space_from='solver', space_to='solver', ish=None, **kwargs): + """ Convert BlockGf from its structure to this structure. .. warning:: @@ -432,10 +458,13 @@ class BlockStructure(object): G : BlockGf the Gf that should be converted G_struct : BlockStructure or str - the structure of that G or 'sumk' (then, the structure of - the sumk Green's function of this BlockStructure is used) - ish : int - shell index + 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 @@ -445,41 +474,67 @@ class BlockStructure(object): G_out : BlockGf the output Green's function (if not given, a new one is created) + space_from : 'solver' or 'sumk' + whether the Green's function ``G`` corresponds to the + solver or sumk structure of ``G_struct`` + space_to : 'solver' or 'sumk' + whether the output Green's function should be according to + the solver of sumk structure of this structure **kwargs : options passed to the constructor for the new Gf """ + if ish is not None: + warn( + 'The parameter ish in convert_gf is deprecated. Use ish_from and ish_to instead.') + ish_from = ish + ish_to = ish + + if ish_to is None: + ish_to = ish_from + warning_threshold = 1.e-10 if isinstance(show_warnings, float): warning_threshold = show_warnings show_warnings = True - # we offer the possibility to convert to convert from sumk_dft - from_sumk = False - if isinstance(G_struct, str) and G_struct == 'sumk': - gf_struct_in = self.gf_struct_sumk_dict[ish] - from_sumk = True + if G_struct is None: + G_struct = self + + if space_from == 'solver': + gf_struct_in = G_struct.gf_struct_solver[ish_from] + elif space_from == 'sumk': + gf_struct_in = G_struct.gf_struct_sumk_dict[ish_from] else: - gf_struct_in = G_struct.gf_struct_solver[ish] + raise Exception( + "Argument space_from has to be either 'solver' or 'sumk'.") # create a Green's function to hold the result if G_out is None: - G_out = self.create_gf(ish=ish, **kwargs) + G_out = self.create_gf(ish=ish_to, space=space_to, **kwargs) else: - self.check_gf(G_out, ish=ish) + self.check_gf(G_out, ish=ish_to, space=space_to) for block in gf_struct_in.keys(): for i1 in gf_struct_in[block]: for i2 in gf_struct_in[block]: - if from_sumk: + if space_from == 'sumk': i1_sumk = (block, i1) i2_sumk = (block, i2) - else: - i1_sumk = G_struct.solver_to_sumk[ish][(block, i1)] - i2_sumk = G_struct.solver_to_sumk[ish][(block, i2)] + elif space_from == 'solver': + i1_sumk = G_struct.solver_to_sumk[ish_from][(block, i1)] + i2_sumk = G_struct.solver_to_sumk[ish_from][(block, i2)] + + if space_to == 'sumk': + i1_sol = i1_sumk + i2_sol = i2_sumk + elif space_to == 'solver': + i1_sol = self.sumk_to_solver[ish_to][i1_sumk] + i2_sol = self.sumk_to_solver[ish_to][i2_sumk] + else: + raise Exception( + "Argument space_to has to be either 'solver' or 'sumk'.") - i1_sol = self.sumk_to_solver[ish][i1_sumk] - i2_sol = self.sumk_to_solver[ish][i2_sumk] if i1_sol[0] is None or i2_sol[0] is None: if show_warnings: if mpi.is_master_node(): diff --git a/python/sumk_dft.py b/python/sumk_dft.py index 23b91593..1b93373c 100644 --- a/python/sumk_dft.py +++ b/python/sumk_dft.py @@ -743,8 +743,7 @@ class SumkDFT(object): G_out """ if G_out is None: - G_out = [BlockGf(mesh=G_loc[0].mesh, - gf_struct=[(k, v) for k, v in self.gf_struct_solver[ish].iteritems()]) + 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)] else: for ish in range(self.n_inequiv_shells): @@ -754,8 +753,10 @@ class SumkDFT(object): for ish in range(self.n_inequiv_shells): self.block_structure.convert_gf( G=G_loc[self.inequiv_to_corr[ish]], - G_struct='sumk', - ish=ish, + G_struct=None, + ish_from=self.inequiv_to_corr[ish], + ish_to=ish, + space_from='sumk', G_out=G_out[ish]) # return only the inequivalent shells: diff --git a/test/blockstructure.py b/test/blockstructure.py index eac85863..7333620c 100644 --- a/test/blockstructure.py +++ b/test/blockstructure.py @@ -61,7 +61,7 @@ G_sumk = BlockGf(mesh=G1.mesh, gf_struct=original_bs.gf_struct_sumk[0]) for i in range(3): G_sumk['up'][i, i] << SemiCircular(1 if i < 2 else 2) G_sumk['down'][i, i] << SemiCircular(4 if i < 2 else 3) -G3 = original_bs.convert_gf(G_sumk, 'sumk', beta=40, n_points=3) +G3 = original_bs.convert_gf(G_sumk, None, space_from='sumk', beta=40, n_points=3) assert_block_gfs_are_close(G1, G3) assert original_bs.gf_struct_sumk_list ==\ From 9076baf9d66b01ef931fbf703086af5d16bcc069 Mon Sep 17 00:00:00 2001 From: "Gernot J. Kraberger" <16017581+gkraberger@users.noreply.github.com> Date: Thu, 30 Aug 2018 22:39:35 +0200 Subject: [PATCH 07/57] sumk_dft: split transform_to_sumk_blocks from put_Sigma this is done in a backward-compatible manner --- python/sumk_dft.py | 102 ++++++++++++++++++++++++++++++--------------- 1 file changed, 68 insertions(+), 34 deletions(-) diff --git a/python/sumk_dft.py b/python/sumk_dft.py index 1b93373c..08eedafc 100644 --- a/python/sumk_dft.py +++ b/python/sumk_dft.py @@ -576,61 +576,95 @@ class SumkDFT(object): return G_latt - def set_Sigma(self, Sigma_imp): - self.put_Sigma(Sigma_imp) + def set_Sigma(self, Sigma_imp, transform_to_sumk_blocks=True): + self.put_Sigma(Sigma_imp, transform_to_sumk_blocks) - def put_Sigma(self, Sigma_imp): + def put_Sigma(self, Sigma_imp, transform_to_sumk_blocks=True): r""" - Inserts the impurity self-energies into the sumk_dft class. + Insert the impurity self-energies into the sumk_dft class. Parameters ---------- Sigma_imp : list of BlockGf (Green's function) objects - List containing impurity self-energy for all inequivalent correlated shells. - Self-energies for equivalent shells are then automatically set by this function. - The self-energies can be of the real or imaginary-frequency type. + List containing impurity self-energy for all (inequivalent) correlated shells. + Self-energies for equivalent shells are then automatically set by this function. + The self-energies can be of the real or imaginary-frequency type. + transform_to_sumk_blocks : bool, optional + If True (default), the input Sigma_imp will be transformed to the block structure ``gf_struct_sumk``, + else it has to be given in ``gf_struct_sumk``. """ - assert isinstance( - Sigma_imp, list), "put_Sigma: Sigma_imp has to be a list of Sigmas for the correlated shells, even if it is of length 1!" - assert len( - Sigma_imp) == self.n_inequiv_shells, "put_Sigma: give exactly one Sigma for each inequivalent corr. shell!" + if transform_to_sumk_blocks: + Sigma_imp = self.transform_to_sumk_blocks(Sigma_imp) - # init self.Sigma_imp_(i)w: - if all( (isinstance(gf, Gf) and isinstance (gf.mesh, MeshImFreq)) for bname, gf in Sigma_imp[0]): + assert isinstance(Sigma_imp, list),\ + "put_Sigma: Sigma_imp has to be a list of Sigmas for the correlated shells, even if it is of length 1!" + assert len(Sigma_imp) == self.n_corr_shells,\ + "put_Sigma: give exactly one Sigma for each corr. shell!" + + if all((isinstance(gf, Gf) and isinstance(gf.mesh, MeshImFreq)) for bname, gf in Sigma_imp[0]): # Imaginary frequency Sigma: - self.Sigma_imp_iw = [BlockGf(name_block_generator=[(block, GfImFreq(indices=inner, mesh=Sigma_imp[0].mesh)) - for block, inner in self.gf_struct_sumk[icrsh]], make_copies=False) + self.Sigma_imp_iw = [self.block_structure.create_gf(ish=icrsh, mesh=Sigma_imp[icrsh].mesh, space='sumk') for icrsh in range(self.n_corr_shells)] SK_Sigma_imp = self.Sigma_imp_iw - elif all( isinstance(gf, Gf) and isinstance (gf.mesh, MeshReFreq) for bname, gf in Sigma_imp[0]): + elif all(isinstance(gf, Gf) and isinstance(gf.mesh, MeshReFreq) for bname, gf in Sigma_imp[0]): # Real frequency Sigma: - self.Sigma_imp_w = [BlockGf(name_block_generator=[(block, GfReFreq(indices=inner, mesh=Sigma_imp[0].mesh)) - for block, inner in self.gf_struct_sumk[icrsh]], make_copies=False) + self.Sigma_imp_w = [self.block_structure.create_gf(ish=icrsh, mesh=Sigma_imp[icrsh].mesh, gf_function=GfReFreq, space='sumk') for icrsh in range(self.n_corr_shells)] SK_Sigma_imp = self.Sigma_imp_w else: - raise ValueError, "put_Sigma: This type of Sigma is not handled." + raise ValueError, "put_Sigma: This type of Sigma is not handled, give either BlockGf of GfReFreq or GfImFreq." + + # rotation from local to global coordinate system: + for icrsh in range(self.n_corr_shells): + for bname, gf in SK_Sigma_imp[icrsh]: + if self.use_rotations: + gf << self.rotloc(icrsh, + Sigma_imp[icrsh][bname], + direction='toGlobal') + else: + gf << Sigma_imp[icrsh][bname] + + def transform_to_sumk_blocks(self, Sigma_imp, Sigma_out=None): + r""" transform Sigma from solver to sumk space + + Parameters + ---------- + Sigma_imp : list of BlockGf (Green's function) objects + List containing impurity self-energy for all inequivalent correlated shells. + The self-energies can be of the real or imaginary-frequency type. + Sigma_out : list of BlockGf + list of one BlockGf per correlated shell with the block structure + according to ``gf_struct_sumk``; if None, it will be created + """ + + assert isinstance(Sigma_imp, list),\ + "transform_to_sumk_blocks: Sigma_imp has to be a list of Sigmas for the inequivalent correlated shells, even if it is of length 1!" + assert len(Sigma_imp) == self.n_inequiv_shells,\ + "transform_to_sumk_blocks: give exactly one Sigma for each inequivalent corr. shell!" + + if Sigma_out is None: + Sigma_out = [self.block_structure.create_gf(ish=icrsh, mesh=Sigma_imp[self.corr_to_inequiv[icrsh]].mesh, space='sumk') + for icrsh in range(self.n_corr_shells)] + else: + for icrsh in range(self.n_corr_shells): + self.block_structure.check_gf(Sigma_out, + ish=icrsh, + space='sumk') # transform the CTQMC blocks to the full matrix: for icrsh in range(self.n_corr_shells): # ish is the index of the inequivalent shell corresponding to icrsh ish = self.corr_to_inequiv[icrsh] - for block, inner in self.gf_struct_solver[ish].iteritems(): - for ind1 in inner: - for ind2 in inner: - block_sumk, ind1_sumk = self.solver_to_sumk[ - ish][(block, ind1)] - block_sumk, ind2_sumk = self.solver_to_sumk[ - ish][(block, ind2)] - SK_Sigma_imp[icrsh][block_sumk][ - ind1_sumk, ind2_sumk] << Sigma_imp[ish][block][ind1, ind2] - - # rotation from local to global coordinate system: - if self.use_rotations: - for icrsh in range(self.n_corr_shells): - for bname, gf in SK_Sigma_imp[icrsh]: - gf << self.rotloc(icrsh, gf, direction='toGlobal') + self.block_structure.convert_gf( + G=Sigma_imp[ish], + G_struct=None, + space_from='solver', + space_to='sumk', + ish_from=ish, + ish_to=icrsh, + G_out=Sigma_out[icrsh]) + return Sigma_out def extract_G_loc(self, mu=None, iw_or_w='iw', with_Sigma=True, with_dc=True, broadening=None, transform_to_solver_blocks=True): From 31cb7a0ea4794413d463c86dd1982cae20769c03 Mon Sep 17 00:00:00 2001 From: "Gernot J. Kraberger" <16017581+gkraberger@users.noreply.github.com> Date: Fri, 31 Aug 2018 17:52:01 +0200 Subject: [PATCH 08/57] block_structure: prepare for transformation this includes some TODOs that need to be fixed --- python/block_structure.py | 112 ++++++++++++++++++++++++++++++++------ python/sumk_dft.py | 3 + 2 files changed, 97 insertions(+), 18 deletions(-) diff --git a/python/block_structure.py b/python/block_structure.py index e256dfcb..1d5bb3b2 100644 --- a/python/block_structure.py +++ b/python/block_structure.py @@ -62,6 +62,43 @@ class BlockStructure(object): maps from the solver block to the sumk block for *inequivalent* correlated shell ish + deg_shells : list of lists of lists OR list of lists of dicts + In the simple format, ``deg_shells[ish][grp]`` is a list of + block names; ``ish`` is the index of the inequivalent correlated shell, + ``grp`` is the index of the group of symmetry-related blocks. + When the name of two blocks is in the same group, that means that + these two blocks are the same by symmetry. + + In the more general format, ``deg_shells[ish][grp]`` is a + dictionary whose keys are the block names that are part of the + group. The values of the dict for each key are tuples ``(v, conj)``, + where ``v`` is a transformation matrix with the same matrix dimensions + as the block and ``conj`` is a bool (whether or not to conjugate). + Two blocks with ``v_1, conj_1`` and ``v_2, conj_2`` being in the same + symmetry group means that + + .. math:: + + C_1(v_1^\dagger G_1 v_1) = C_2(v_2^\dagger G_2 v_2), + + where the :math:`G_i` are the Green's functions of the block, + and the functions :math:`C_i` conjugate their argument if the bool + ``conj_i`` is ``True``. + transformation : list of numpy.array or list of dict + a list with entries for each ``ish`` giving transformation matrices + that are used on the Green's function in ``sumk`` space when before + converting to the ``solver`` space + Up to the change in block structure, + + .. math:: + + G_{solver} = T G_{sumk} T^\dagger + + if :math:`T` is the ``transformation`` of that particular shell. + + Note that for each shell this can either be a numpy array which + applies to all blocks or a dict with a transformation matrix for + each block. """ def __init__(self, gf_struct_sumk=None, @@ -69,13 +106,15 @@ class BlockStructure(object): solver_to_sumk=None, sumk_to_solver=None, solver_to_sumk_block=None, - deg_shells=None): + deg_shells=None, + transformation=None): self.gf_struct_sumk = gf_struct_sumk self.gf_struct_solver = gf_struct_solver self.solver_to_sumk = solver_to_sumk self.sumk_to_solver = sumk_to_solver self.solver_to_sumk_block = solver_to_sumk_block self.deg_shells = deg_shells + self.transformation = transformation @property def gf_struct_solver_list(self): @@ -144,6 +183,13 @@ class BlockStructure(object): return [{block: indices for block, indices in gfs} for gfs in self.gf_struct_sumk] + @property + def effective_transformation(self): + # TODO: if transformation is None, return np.eye + # TODO: zero out all the lines of the transformation that are + # not included in gf_struct_solver + return self.transformation + @classmethod def full_structure(cls,gf_struct,corr_to_inequiv): """ Construct structure that maps to itself. @@ -294,6 +340,10 @@ class BlockStructure(object): but the sumk Gf. """ + # TODO: when there is a transformation matrix, this should + # first zero out the corresponding rows of (a copy of) T and then + # pick_gf_struct_solver all lines of (the copy of) T that have at least + # one non-zero entry gfs = [] # construct gfs, which is the equivalent of new_gf_struct @@ -309,9 +359,8 @@ class BlockStructure(object): gfs[ish][ind_sol[0]].append(ind_sol[1]) self.pick_gf_struct_solver(gfs) - - def map_gf_struct_solver(self,mapping): - """ Map the Green function structure from one struct to another. + def map_gf_struct_solver(self, mapping): + r""" Map the Green function structure from one struct to another. Parameters ---------- @@ -319,35 +368,51 @@ class BlockStructure(object): the dict consists of elements (from_block,from_index) : (to_block,to_index) that maps from one structure to the other + (one for each shell; use a mapping ``None`` for a shell + you want to leave unchanged) + + Examples + -------- + + Consider a `gf_struct_solver` consisting of two :math:`1 \times 1` + blocks, `block_1` and `block_2`. Say you want to have a new block + structure where you merge them into one block because you want to + introduce an off-diagonal element. You could perform the mapping + via:: + + map_gf_struct_solver([{('block_1',0) : ('block', 0) + ('block_2',0) : ('block', 1)}]) """ for ish in range(len(mapping)): + if mapping[ish] is None: + continue gf_struct = {} so2su = {} su2so = {} so2su_block = {} - for frm,to in mapping[ish].iteritems(): + for frm, to in mapping[ish].iteritems(): if not to[0] in gf_struct: - gf_struct[to[0]]=[] + gf_struct[to[0]] = [] gf_struct[to[0]].append(to[1]) - so2su[to]=self.solver_to_sumk[ish][frm] - su2so[self.solver_to_sumk[ish][frm]]=to + so2su[to] = self.solver_to_sumk[ish][frm] + su2so[self.solver_to_sumk[ish][frm]] = to if to[0] in so2su_block: if so2su_block[to[0]] != \ - self.solver_to_sumk_block[ish][frm[0]]: + self.solver_to_sumk_block[ish][frm[0]]: warn("solver block '{}' maps to more than one sumk block: '{}', '{}'".format( - to[0],so2su_block[to[0]],self.solver_to_sumk_block[ish][frm[0]])) + to[0], so2su_block[to[0]], self.solver_to_sumk_block[ish][frm[0]])) else: - so2su_block[to[0]]=\ + so2su_block[to[0]] =\ self.solver_to_sumk_block[ish][frm[0]] for k in self.sumk_to_solver[ish].keys(): if not k in su2so: - su2so[k] = (None,None) - self.gf_struct_solver[ish]=gf_struct - self.solver_to_sumk[ish]=so2su - self.sumk_to_solver[ish]=su2so - self.solver_to_sumk_block[ish]=so2su_block + su2so[k] = (None, None) + self.gf_struct_solver[ish] = gf_struct + self.solver_to_sumk[ish] = so2su + self.sumk_to_solver[ish] = su2so + self.solver_to_sumk_block[ish] = so2su_block def create_gf(self, ish=0, gf_function=GfImFreq, space='solver', **kwargs): """ Create a zero BlockGf having the correct structure. @@ -484,6 +549,8 @@ class BlockStructure(object): options passed to the constructor for the new Gf """ + # TODO: use effective_transformation here + if ish is not None: warn( 'The parameter ish in convert_gf is deprecated. Use ish_from and ish_to instead.') @@ -607,7 +674,7 @@ class BlockStructure(object): for prop in [ "gf_struct_sumk", "gf_struct_solver", "solver_to_sumk", "sumk_to_solver", "solver_to_sumk_block", - "deg_shells"]: + "deg_shells","transformation"]: if not compare(getattr(self,prop),getattr(other,prop)): return False return True @@ -620,9 +687,13 @@ class BlockStructure(object): ret = {} for element in [ "gf_struct_sumk", "gf_struct_solver", - "solver_to_sumk_block","deg_shells"]: + "solver_to_sumk_block","deg_shells", + "transformation"]: ret[element] = getattr(self,element) + if ret["transformation"] is None: + ret["transformation"] = "None" + def construct_mapping(mapping): d = [] for ish in range(len(mapping)): @@ -648,6 +719,9 @@ class BlockStructure(object): d[ish][literal_eval(k)] = literal_eval(v) return d + if 'transformation' in D and D['transformation'] == "None": + D['transformation'] = None + D['solver_to_sumk']=reconstruct_mapping(D['solver_to_sumk']) D['sumk_to_solver']=reconstruct_mapping(D['sumk_to_solver']) return cls(**D) @@ -679,6 +753,8 @@ class BlockStructure(object): else: for key in self.deg_shells[ish][l]: s+=' '+key+'\n' + s += "transformation\n" + s += str(self.transformation) return s from pytriqs.archive.hdf_archive_schemes import register_class diff --git a/python/sumk_dft.py b/python/sumk_dft.py index 08eedafc..1b7c3d18 100644 --- a/python/sumk_dft.py +++ b/python/sumk_dft.py @@ -36,6 +36,9 @@ from warnings import warn from scipy import compress from scipy.optimize import minimize +# TODO: check where the transformation in block_structure has to enter +# - DC + class SumkDFT(object): """This class provides a general SumK method for combining ab-initio code and pytriqs.""" From 5fd74f73b71477102d90f2c10eb438eb45c4f487 Mon Sep 17 00:00:00 2001 From: "Gernot J. Kraberger" <16017581+gkraberger@users.noreply.github.com> Date: Tue, 4 Sep 2018 19:02:10 +0200 Subject: [PATCH 09/57] start with Sr2RuO4 guide --- doc/documentation.rst | 1 + doc/guide/Sr2RuO4.rst | 40 ++++++++ doc/guide/Sr2RuO4/Sr2RuO4.indmftpr | 17 ++++ doc/guide/Sr2RuO4/Sr2RuO4.struct | 96 +++++++++++++++++++ .../Sr2RuO4/calculate_dos_wannier_basis.py | 15 +++ 5 files changed, 169 insertions(+) create mode 100644 doc/guide/Sr2RuO4.rst create mode 100644 doc/guide/Sr2RuO4/Sr2RuO4.indmftpr create mode 100644 doc/guide/Sr2RuO4/Sr2RuO4.struct create mode 100644 doc/guide/Sr2RuO4/calculate_dos_wannier_basis.py diff --git a/doc/documentation.rst b/doc/documentation.rst index b000a6c8..45f071d6 100644 --- a/doc/documentation.rst +++ b/doc/documentation.rst @@ -26,6 +26,7 @@ User guide guide/dftdmft_singleshot guide/SrVO3 guide/dftdmft_selfcons + guide/Sr2RuO4 guide/analysis guide/full_tutorial guide/transport diff --git a/doc/guide/Sr2RuO4.rst b/doc/guide/Sr2RuO4.rst new file mode 100644 index 00000000..a1e3c8b9 --- /dev/null +++ b/doc/guide/Sr2RuO4.rst @@ -0,0 +1,40 @@ +.. _Sr2RuO4: + +Spin-orbit coupled calculations (single-shot) +============================================= + +There are two main ways of including the spin-orbit coupling (SO) term into +DFT+DMFT calculations: + +- by performing a DFT calculation including SO and then doing a DMFT calculation on top, or +- by performing a DFT calculation without SO and then adding the SO term on the model level. + +Treatment of SO in DFT +---------------------- + +For now, TRIQS/DFTTools does only work with Wien2k when performing calculations with SO. +Of course, the general Hk framework is also possible. +But the way VASP treats SO is fundamentally different to the way Wien2k treats it and the interface does not handle that at the moment. + +Therefore, this guide assumes that Wien2k is being used. + +First, a Wien2k calculation including SO has to be performed. +For details, we refer the reader to the documentation of Wien2k. +The interface to Wien2k only works when the DFT calculation is done both spin-polarized and with SO (that means that you have to initialize the Wien2k calculation accordingly and then run with ``runsp -sp``). + +Performing the projection +~~~~~~~~~~~~~~~~~~~~~~~~~ + +Note that the final ``x lapw2 -almd -so -up`` and ``x lapw2 -almd -so -dn`` have to be run *on a single core*, which implies that, before, ``x lapw1 -up``, ``x lapw2 -dn``, and ``x lapwso -up`` have to be run in single-core mode (once). + +In the ``case.indmftpr`` file, the spin-orbit flag has to be set to ``1`` for the correlated atoms. +For example, for the compound Sr\ :sub:`2`\ RuO\ :sub:`4`, with the struct file :download:`Sr2RuO4.struct `, we would e.g. use the ``indmftpr`` file :download:`found here `. +Then, ``dmftproj -sp -so`` has to be called. +As usual, it is important to check for warnings (e.g., about eigenvalues of the overlap matrix) in the output of ``dmftproj`` and adapt the window until these warnings disappear. + +Note that in presence of SO, it is not possible to project only onto the :math:`t_{2g}` subshell because it is not an irreducible representation. +A redesign of the orthonormalization procedure might happen in the long term, which might allow that. + +We strongly suggest using the :py:meth:`.dos_wannier_basis` functionality of the :py:class:`.SumkDFTTools` class (see :download:`calculate_dos_wannier_basis.py `) and compare the Wannier-projected orbitals to the original DFT DOS (they should be more or less equal). +Note that, with SO, there are usually off-diagonal elements of the spectral function, which can also be imaginary. +The imaginary part can be found in the third column of the files ``DOS_wann_...``. diff --git a/doc/guide/Sr2RuO4/Sr2RuO4.indmftpr b/doc/guide/Sr2RuO4/Sr2RuO4.indmftpr new file mode 100644 index 00000000..fa8e6be5 --- /dev/null +++ b/doc/guide/Sr2RuO4/Sr2RuO4.indmftpr @@ -0,0 +1,17 @@ +4 ! Nsort +2 1 2 2 ! Multiplicities +3 ! lmax +complex ! Sr +0 0 0 0 +0 0 0 0 +cubic ! Ru +0 0 2 0 ! include d-shell as correlated +0 0 0 0 ! there are no irreps with SO +1 ! SO-flag +complex ! O1 +0 0 0 0 +0 0 0 0 +complex ! O2 +0 0 0 0 +0 0 0 0 +-0.7 1.4 ! energy window (Ry) diff --git a/doc/guide/Sr2RuO4/Sr2RuO4.struct b/doc/guide/Sr2RuO4/Sr2RuO4.struct new file mode 100644 index 00000000..5cfd9a0d --- /dev/null +++ b/doc/guide/Sr2RuO4/Sr2RuO4.struct @@ -0,0 +1,96 @@ +Sr2RuO4 s-o calc. M|| 0.00 0.00 1.00 +B 4 39_I + RELA + 7.300012 7.300012 24.044875 90.000000 90.000000 90.000000 +ATOM -1: X=0.00000000 Y=0.00000000 Z=0.35240000 + MULT= 2 ISPLIT=-2 + -1: X=0.00000000 Y=0.00000000 Z=0.64760000 +Sr2+ NPT= 781 R0=.000010000 RMT= 2.26000 Z: 38.00000 +LOCAL ROT MATRIX: 1.0000000 0.0000000 0.0000000 + 0.0000000 1.0000000 0.0000000 + 0.0000000 0.0000000 1.0000000 +ATOM -2: X=0.00000000 Y=0.00000000 Z=0.00000000 + MULT= 1 ISPLIT=-2 +Ru4+ NPT= 781 R0=.000010000 RMT= 1.95000 Z: 44.00000 +LOCAL ROT MATRIX: 1.0000000 0.0000000 0.0000000 + 0.0000000 1.0000000 0.0000000 + 0.0000000 0.0000000 1.0000000 +ATOM -3: X=0.50000000 Y=0.00000000 Z=0.00000000 + MULT= 2 ISPLIT= 8 + -3: X=0.00000000 Y=0.50000000 Z=0.00000000 +O 2- NPT= 781 R0=.000100000 RMT= 1.68000 Z: 8.00000 +LOCAL ROT MATRIX: 1.0000000 0.0000000 0.0000000 + 0.0000000 1.0000000 0.0000000 + 0.0000000 0.0000000 1.0000000 +ATOM -4: X=0.00000000 Y=0.00000000 Z=0.16350000 + MULT= 2 ISPLIT=-2 + -4: X=0.00000000 Y=0.00000000 Z=0.83650000 +O 2- NPT= 781 R0=.000100000 RMT= 1.68000 Z: 8.00000 +LOCAL ROT MATRIX: 1.0000000 0.0000000 0.0000000 + 0.0000000 1.0000000 0.0000000 + 0.0000000 0.0000000 1.0000000 + 16 NUMBER OF SYMMETRY OPERATIONS + 0-1 0 0.00000000 + 1 0 0 0.00000000 + 0 0-1 0.00000000 + 1 A 2 so. oper. type orig. index +-1 0 0 0.00000000 + 0-1 0 0.00000000 + 0 0-1 0.00000000 + 2 A 3 + 1 0 0 0.00000000 + 0 1 0 0.00000000 + 0 0-1 0.00000000 + 3 A 6 + 0-1 0 0.00000000 + 1 0 0 0.00000000 + 0 0 1 0.00000000 + 4 A 8 + 0 1 0 0.00000000 +-1 0 0 0.00000000 + 0 0-1 0.00000000 + 5 A 9 +-1 0 0 0.00000000 + 0-1 0 0.00000000 + 0 0 1 0.00000000 + 6 A 11 + 1 0 0 0.00000000 + 0 1 0 0.00000000 + 0 0 1 0.00000000 + 7 A 14 + 0 1 0 0.00000000 +-1 0 0 0.00000000 + 0 0 1 0.00000000 + 8 A 15 + 1 0 0 0.00000000 + 0-1 0 0.00000000 + 0 0-1 0.00000000 + 9 B 1 + 0 1 0 0.00000000 + 1 0 0 0.00000000 + 0 0-1 0.00000000 + 10 B 4 + 0-1 0 0.00000000 +-1 0 0 0.00000000 + 0 0-1 0.00000000 + 11 B 5 + 1 0 0 0.00000000 + 0-1 0 0.00000000 + 0 0 1 0.00000000 + 12 B 7 +-1 0 0 0.00000000 + 0 1 0 0.00000000 + 0 0-1 0.00000000 + 13 B 10 + 0 1 0 0.00000000 + 1 0 0 0.00000000 + 0 0 1 0.00000000 + 14 B 12 + 0-1 0 0.00000000 +-1 0 0 0.00000000 + 0 0 1 0.00000000 + 15 B 13 +-1 0 0 0.00000000 + 0 1 0 0.00000000 + 0 0 1 0.00000000 + 16 B 16 diff --git a/doc/guide/Sr2RuO4/calculate_dos_wannier_basis.py b/doc/guide/Sr2RuO4/calculate_dos_wannier_basis.py new file mode 100644 index 00000000..7cb8462a --- /dev/null +++ b/doc/guide/Sr2RuO4/calculate_dos_wannier_basis.py @@ -0,0 +1,15 @@ +from triqs_dft_tools.converters.wien2k_converter import Wien2kConverter +from triqs_dft_tools import SumkDFTTools + +filename = 'Sr2RuO4' + +conv = Wien2kConverter(filename = filename,hdf_filename=filename+'.h5') +conv.convert_dft_input() + +SK = SumkDFTTools(filename+'.h5') +mesh = (-10.0,10.0,500) +SK.dos_wannier_basis(broadening=(mesh[1]-mesh[0])/float(mesh[2]), + mesh=mesh, + save_to_file=True, + with_Sigma=False, + with_dc=False) From 2d481198766cf8ce30b40370080fceb29911dbea Mon Sep 17 00:00:00 2001 From: "Gernot J. Kraberger" <16017581+gkraberger@users.noreply.github.com> Date: Fri, 7 Sep 2018 11:27:07 +0200 Subject: [PATCH 10/57] block_structure: effective_transformation_sumk --- python/block_structure.py | 52 ++++++++++++++++++++++++++++++++---- test/blockstructure.py | 55 ++++++++++++++++++++++++++++++++++++++- 2 files changed, 101 insertions(+), 6 deletions(-) diff --git a/python/block_structure.py b/python/block_structure.py index 1d5bb3b2..42227c82 100644 --- a/python/block_structure.py +++ b/python/block_structure.py @@ -133,6 +133,8 @@ class BlockStructure(object): The list for each shell is sorted alphabetically by block name. """ + if self.gf_struct_solver is None: + return None # we sort by block name in order to get a reproducible result return [sorted([(k, v) for k, v in gfs.iteritems()], key=lambda x: x[0]) for gfs in self.gf_struct_solver] @@ -180,15 +182,55 @@ class BlockStructure(object): ``gf_struct_sumk_dict[ish][bname]`` is a list of the indices of block ``bname`` of shell ``ish``. """ + if self.gf_struct_sumk is None: + return None return [{block: indices for block, indices in gfs} for gfs in self.gf_struct_sumk] @property - def effective_transformation(self): - # TODO: if transformation is None, return np.eye - # TODO: zero out all the lines of the transformation that are - # not included in gf_struct_solver - return self.transformation + def effective_transformation_sumk(self): + trans = copy.deepcopy(self.transformation) + if self.gf_struct_sumk is None: + raise Exception('gf_struct_sumk not set.') + if self.gf_struct_solver is None: + raise Exception('gf_struct_solver not set.') + + if trans is None: + trans = [{block: np.eye(len(indices)) for block, indices in gfs} + for gfs in self.gf_struct_sumk] + + assert isinstance(trans, list),\ + "transformation has to be a list" + + assert len(trans) == len(self.gf_struct_sumk),\ + "give one transformation per correlated shell" + + for icrsh in range(len(trans)): + if trans[icrsh] is None: + trans[icrsh] = {block: np.eye(len(indices)) + for block, indices in self.gf_struct_sumk[icrsh]} + + if not isinstance(trans[icrsh], dict): + trans[icrsh] = {block: copy.deepcopy(trans[icrsh]) + for block, indices in self.gf_struct_sumk[icrsh]} + + assert trans[icrsh].keys() == self.gf_struct_sumk_dict[icrsh].keys(),\ + "wrong block names used in transformation (icrsh = {})".format(icrsh) + + for block in trans[icrsh]: + assert trans[icrsh][block].shape[0] == trans[icrsh][block].shape[1],\ + "Transformation has to be quadratic; throwing away orbitals can be achieved on the level of the mapping. (icrsh = {}, block = {})".format(icrsh, block) + + assert trans[icrsh][block].shape[0] == len(self.gf_struct_sumk_dict[icrsh][block]),\ + "Transformation block shape does not match gf_struct_sumk. (icrsh = {}, block = {})".format(icrsh, block) + + # zero out all the lines of the transformation that are + # not included in gf_struct_solver + for iorb, norb in enumerate(self.gf_struct_sumk_dict[icrsh][block]): + if self.sumk_to_solver[icrsh][(block, norb)][0] is None: + trans[icrsh][block][iorb, :] = 0.0 + return trans + @classmethod def full_structure(cls,gf_struct,corr_to_inequiv): diff --git a/test/blockstructure.py b/test/blockstructure.py index 7333620c..b0da8c5c 100644 --- a/test/blockstructure.py +++ b/test/blockstructure.py @@ -3,15 +3,38 @@ from pytriqs.utility.h5diff import h5diff from pytriqs.gf import * from pytriqs.utility.comparison_tests import assert_block_gfs_are_close from triqs_dft_tools.block_structure import BlockStructure +import numpy as np +from pytriqs.utility.h5diff import compare, failures + + +def cmp(a, b, precision=1.e-15): + compare('', a, b, 0, precision) + if failures: + raise AssertionError('\n'.join(failures)) SK = SumkDFT('blockstructure.in.h5', use_dft_blocks=True) original_bs = SK.block_structure +cmp(original_bs.effective_transformation_sumk, + [{'down': np.array([[1., 0., 0.], + [0., 1., 0.], + [0., 0., 1.]]), + 'up': np.array([[1., 0., 0.], + [0., 1., 0.], + [0., 0., 1.]])}]) # check pick_gf_struct_solver pick1 = original_bs.copy() pick1.pick_gf_struct_solver([{'up_0': [1], 'up_1': [0], 'down_1': [0]}]) +cmp(pick1.effective_transformation_sumk, + [{'down': np.array([[0., 0., 0.], + [0., 0., 0.], + [0., 0., 1.]]), + 'up': np.array([[0., 0., 0.], + [0., 1., 0.], + [0., 0., 1.]])}]) + # check loading a block_structure from file SK.block_structure = SK.load(['block_structure'], 'mod')[0] assert SK.block_structure == pick1, 'loading SK block structure from file failed' @@ -25,10 +48,36 @@ sk_pick1 = BlockStructure(gf_struct_sumk=SK.gf_struct_sumk, deg_shells=SK.deg_shells) assert sk_pick1 == pick1, 'constructing block structure from SumkDFT properties failed' +cmp(pick1.effective_transformation_sumk, + [{'down': np.array([[0., 0., 0.], + [0., 0., 0.], + [0., 0., 1.]]), + 'up': np.array([[0., 0., 0.], + [0., 1., 0.], + [0., 0., 1.]])}]) + # check pick_gf_struct_sumk pick2 = original_bs.copy() pick2.pick_gf_struct_sumk([{'up': [1, 2], 'down': [0, 1]}]) +cmp(pick2.effective_transformation_sumk, + [{'down': np.array([[1., 0., 0.], + [0., 1., 0.], + [0., 0., 0.]]), + 'up': np.array([[0., 0., 0.], + [0., 1., 0.], + [0., 0., 1.]])}]) + +pick3 = pick2.copy() +pick3.transformation = [np.reshape(range(9), (3, 3))] +cmp(pick3.effective_transformation_sumk, + [{'down': np.array([[0, 1, 2], + [3, 4, 5], + [0, 0, 0]]), + 'up': np.array([[0, 0, 0], + [3, 4, 5], + [6, 7, 8]])}]) + # check map_gf_struct_solver mapping = [{('down_0', 0): ('down', 0), ('down_0', 1): ('down', 2), @@ -61,7 +110,11 @@ G_sumk = BlockGf(mesh=G1.mesh, gf_struct=original_bs.gf_struct_sumk[0]) for i in range(3): G_sumk['up'][i, i] << SemiCircular(1 if i < 2 else 2) G_sumk['down'][i, i] << SemiCircular(4 if i < 2 else 3) -G3 = original_bs.convert_gf(G_sumk, None, space_from='sumk', beta=40, n_points=3) +G3 = original_bs.convert_gf(G_sumk, + None, + space_from='sumk', + beta=40, + n_points=3) assert_block_gfs_are_close(G1, G3) assert original_bs.gf_struct_sumk_list ==\ From bc78560ee1184f6da5652fe89c70d200545800ac Mon Sep 17 00:00:00 2001 From: "Gernot J. Kraberger" <16017581+gkraberger@users.noreply.github.com> Date: Fri, 7 Sep 2018 14:40:43 +0200 Subject: [PATCH 11/57] block_structure: add corr_to_inequiv --- python/block_structure.py | 37 ++++++++++++++++---- python/sumk_dft.py | 18 ++++++++-- test/analyse_block_structure_from_gf.ref.h5 | Bin 73312 -> 76008 bytes test/blockstructure.in.h5 | Bin 66104 -> 67352 bytes test/blockstructure.py | 3 +- test/blockstructure.ref.h5 | Bin 248384 -> 240784 bytes 6 files changed, 48 insertions(+), 10 deletions(-) diff --git a/python/block_structure.py b/python/block_structure.py index 42227c82..df0cc2e9 100644 --- a/python/block_structure.py +++ b/python/block_structure.py @@ -107,6 +107,7 @@ class BlockStructure(object): sumk_to_solver=None, solver_to_sumk_block=None, deg_shells=None, + corr_to_inequiv = None, transformation=None): self.gf_struct_sumk = gf_struct_sumk self.gf_struct_solver = gf_struct_solver @@ -114,6 +115,7 @@ class BlockStructure(object): self.sumk_to_solver = sumk_to_solver self.solver_to_sumk_block = solver_to_sumk_block self.deg_shells = deg_shells + self.corr_to_inequiv = corr_to_inequiv self.transformation = transformation @property @@ -187,6 +189,24 @@ class BlockStructure(object): return [{block: indices for block, indices in gfs} for gfs in self.gf_struct_sumk] + @property + def inequiv_to_corr(self): + if self.corr_to_inequiv is None: + return None + N_solver = len(np.unique(self.corr_to_inequiv)) + if self.gf_struct_solver is not None: + assert N_solver == len(self.gf_struct_solver) + assert sorted(np.unique(self.corr_to_inequiv)) == range(N_solver),\ + "an inequivalent shell is missing in corr_to_inequiv" + return [self.corr_to_inequiv.index(icrsh) + for icrsh in range(N_solver)] + + @inequiv_to_corr.setter + def inequiv_to_corr(self, value): + if value is None: + return + assert self.inequiv_to_corr == value, "Trying to set incompatible inequiv_to_corr" + @property def effective_transformation_sumk(self): trans = copy.deepcopy(self.transformation) @@ -285,7 +305,8 @@ class BlockStructure(object): solver_to_sumk = copy.deepcopy(solver_to_sumk), sumk_to_solver = solver_to_sumk, solver_to_sumk_block = s2sblock, - deg_shells = [[] for ish in range(len(gf_struct))]) + deg_shells = [[] for ish in range(len(gf_struct))], + corr_to_inequiv = corr_to_inequiv) def pick_gf_struct_solver(self,new_gf_struct): """ Pick selected orbitals within blocks. @@ -716,7 +737,7 @@ class BlockStructure(object): for prop in [ "gf_struct_sumk", "gf_struct_solver", "solver_to_sumk", "sumk_to_solver", "solver_to_sumk_block", - "deg_shells","transformation"]: + "deg_shells","transformation", "corr_to_inequiv"]: if not compare(getattr(self,prop),getattr(other,prop)): return False return True @@ -730,8 +751,10 @@ class BlockStructure(object): ret = {} for element in [ "gf_struct_sumk", "gf_struct_solver", "solver_to_sumk_block","deg_shells", - "transformation"]: + "transformation", "corr_to_inequiv"]: ret[element] = getattr(self,element) + if ret[element] is None: + ret[element] = 'None' if ret["transformation"] is None: ret["transformation"] = "None" @@ -761,8 +784,9 @@ class BlockStructure(object): d[ish][literal_eval(k)] = literal_eval(v) return d - if 'transformation' in D and D['transformation'] == "None": - D['transformation'] = None + for elem in D: + if D[elem]=="None": + D[elem] = None D['solver_to_sumk']=reconstruct_mapping(D['solver_to_sumk']) D['sumk_to_solver']=reconstruct_mapping(D['sumk_to_solver']) @@ -770,7 +794,8 @@ class BlockStructure(object): def __str__(self): s='' - s+= "gf_struct_sumk "+str( self.gf_struct_sumk)+'\n' + s+= "corr_to_inequiv "+str(self.corr_to_inequiv)+'\n' + s+= "gf_struct_sumk "+str(self.gf_struct_sumk)+'\n' s+= "gf_struct_solver "+str(self.gf_struct_solver)+'\n' s+= "solver_to_sumk_block "+str(self.solver_to_sumk_block)+'\n' for el in ['solver_to_sumk','sumk_to_solver']: diff --git a/python/sumk_dft.py b/python/sumk_dft.py index 1b7c3d18..854ee564 100644 --- a/python/sumk_dft.py +++ b/python/sumk_dft.py @@ -98,6 +98,8 @@ class SumkDFT(object): self.misc_data = misc_data self.h_field = h_field + self.block_structure = BlockStructure() + # Read input from HDF: things_to_read = ['energy_unit', 'n_k', 'k_dep_projection', 'SP', 'SO', 'charge_below', 'density_required', 'symm_op', 'n_shells', 'shells', 'n_corr_shells', 'corr_shells', 'use_rotations', 'rot_mat', @@ -123,8 +125,6 @@ class SumkDFT(object): self.spin_names_to_ind[iso][ self.spin_block_names[iso][isp]] = isp * self.SP - self.block_structure = BlockStructure() - # GF structure used for the local things in the k sums # Most general form allowing for all hybridisation, i.e. largest # blocks possible @@ -187,7 +187,7 @@ class SumkDFT(object): # initialise variables on all nodes to ensure mpi broadcast works at # the end for it in things_to_read: - setattr(self, it, 0) + setattr(self, it, None) subgroup_present = 0 if mpi.is_master_node(): @@ -2145,3 +2145,15 @@ class SumkDFT(object): @property def gf_struct_sumk_dict(self): return self.block_structure.gf_struct_sumk_dict + + def __get_corr_to_inequiv(self): + return self.block_structure.corr_to_inequiv + def __set_corr_to_inequiv(self, value): + self.block_structure.corr_to_inequiv = value + corr_to_inequiv = property(__get_corr_to_inequiv, __set_corr_to_inequiv) + + def __get_inequiv_to_corr(self): + return self.block_structure.inequiv_to_corr + def __set_inequiv_to_corr(self, value): + self.block_structure.inequiv_to_corr = value + inequiv_to_corr = property(__get_inequiv_to_corr, __set_inequiv_to_corr) diff --git a/test/analyse_block_structure_from_gf.ref.h5 b/test/analyse_block_structure_from_gf.ref.h5 index 7acea34d680aa13c55ebfa786da8eea4044c2812..e046860512cd1a04b2918461f2c7fecf8a0cf7ba 100644 GIT binary patch delta 6538 zcmai24RBP|6@K?FKksdR*d&H*Hoz_d62jjy#IhnfTgN(#MF?Oe1%*WfB4S*SpOs=+ zT7M!_=`N?546VBOQ&!Nrk8~s;mc^k?V6d}*LsJkNtksB&EVkkbj`rSj-rY^!IMbbh zbG~!WyZ5~FoqON8=|0e}=Xk$ZE$^u{>uz(fh-rS$AlzSfwrKRLtp|@|n9+C>!4NE7 z>*ek_aJ2tSPvB`XGRwECjg%n`#I5 zeYC;CVK>=pttnGO`}%cRIOipM(DF-+?&}wuL^w5>WP|0GS&GUMO~o8(rjfQV$q)%G z^)M;QuVEA6+#@6-mS1>7U%##=Ex)JY<^+fph2rgQSTTGC@3;w`AF@!2?}jYg)M4e* zA-oOoPvL$x+~0-=*ziCb)@@kM-Fto~;Z6Aki);?X0(0?C1yo`iFSX%8Hte$DG8-;O z{L{h$6*h-!Y`D^fWuf$bqpG-B4Id7J_@43Y&E6g+Gu${F6WuYqkZ6zXu^Jm5V#Bh| zdM`7~hGqTr9{1VsaKeQ|Uu$z1A#m?RkF?=Y0!wlf5!czUEco8za>w+>V-PPWOi*WY z7;D4hY}?^-zvyGPJkdkiCQf$c9Yk;S`UnHxDL3~` z#N)NAp2qNaHQYBSw4>Bp9gvkEe(GIA7LI~h=WS1atTSicG#YlDN^q@M5K_+*V^s1( zFng>QVt44Q3$@@Voi~h&n}0z*^kTUCx^>(|!Y#y-^^8DmG0eD6fj}`#TPnejIUn;* z@%S+C&DD8uywoyvI`2R&ENuP>I67A6Nz~H9=AINcn{mPE#qgUuZ{?XO^25M0li~JP z7RJ;1pd}BjUcG3|LyPWjUb<@S{p(=S1CKy%pAYFQ9Oy8AUNd)1BaR|dV8x{7TRLsW zf8ct`S>qIv@>G()^lXwUmre5tx7;niSeXfik$(`E3CzS0J8lGLrWtZhmos8<({`h& zDy?8@-!diX;tj>H@rkZXTA5b`OnF$pjZGH2W>Lq2`~ByQd@jO+7`!1=;YKWmGt3jWKqoNw3sL5)`{#;c< zlByxMh!{=YjXSfz3=-kH7l}wLl0h(q2$WpL*Z55VZB)65uvrF7!#-425C$PW9=`5_AHk+sX|O=&Kq}_W+^tGtVumW z{by>RkGJf!cHGP0e0;gFgF?!_gj*w%#J(}Rn|%B`;k-Dy>lia2Xw7qFyN z?|IWsoGb7;Y?(Zfr6lK$w%uCmjRt$rvIh~|h{*@G*8O7SBu8IBQr+nOJK zyrGt*iNKx%cmNhQ05X$2gc!aWC(n$Qfx$Xk#Z*Sm5az2{w8 z8Q56S>i>g5VxOCb55xX_&9~_9(3qOjZ{dc+WLG@7j`sBnSh(?+30Dn&cVVCbVaM;pWM6*rrB5q5&TXEzmHL@E`r`87$$d%5QWfF*58>cfvLYlW9bX|QvCA~zBcViW3I=S}O8#-vEohp?%dUw1c>{w^5R} zm%#^T6dSw9wui)i67P^WN^Atbk&{X`I#3gx81uubtHehVHJ`XQ_^x6Uf}O)T>8;nw1Y$r2Es02CU3<6tVWJkN4+}XbFQF$52Bn zQ<)IA2P0UikmxpRT5Ju7#%R>%V5T{gwRSt1;Vjr-L3k%WEl!cE^^RbF7B`1NVzI#o zq9)ECM+>RqJsr9(tZ!rAe!dL5%PSV#M`&5<-16s=urL_Jn`swFf>xw^gpqHpS}!@-PvH4^bq?QPX6~-!JWVN?raG^XX9*^DU#rD)&IbQ|7VKNsgMP*N|2_v=C}98-}{Q9QmE@#ZbkLaJYt} zDhZBR>RE$dD~!bNE+S_?iK8S=lQ>`AD)KyTudAAI#;=gkSwSUGfo#U)Ovt9gHA1Sy fW^g2$#ZAGHMpd%u2#!LlWK)-~No>|t&}HF&`*nIb delta 6278 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 bKwI2G<$xYSl>-`|#k>e;TOFg@JIMb4heS0i diff --git a/test/blockstructure.in.h5 b/test/blockstructure.in.h5 index 6e1bb46905cf3496c64e184258c9168afef997b8..7e03651c9fa5b68fa3be4e9480d8a2a236ed296c 100644 GIT binary patch delta 2473 zcmZ8iZD>*ITijrj3L0kHMTHn;lTO8E zP)62?CVfEz`;+}}i}fqlOEJ11%VZx>sf*KUs#t=>8e81dqIPa|J6|^+4cvR)=RNOv z&+|U#JvYhTis*rgumf8wwWYOHk(9i$LXsqBl)T6fk!LP>42+3gI&Uh>!@jC|?2N*9 ze7Iay-(xJQBtc3^5_uM;bEQem1k;U-_48)oDuU@_%+H^N7Z6N*?-T+S&I(Worb&$i z)wA#-U7LRl>t6NM6&1Sz{TuY)+EzQaG9B_9b&*6%;OfwM$ZoMiV4EGfdsW@J)rlZ! zvFqV&-4@iXY5yThf`v;`NQ~Bt)PNTkYUJO!%M02Ub&C6{fgZh9r-yoT2uok*A4@9Elg<> za#z9LO1nkh-oN3)_ugNN2oW|zvV{6HZ6$(4z>4LAu(Y!g_3Ia_Ef^;b!1Fh|%tei0 zX-k(90KT&qzO8P+;X``MbqhurSRd(xeZ6Lz?_fEzu)v9krqv=!&0KV`jM>Ab8Iy6A z5jzjT#Qu&}T;Q1z8ynJ03v4~am#ch`f&=9Q;sU3SN3^F9_A5$Zp>Bq_iabzrv>7>J z{m}+24QSc|1ok8C$P0UptVS+){a7QmpX8+S#|f#8qzFYRWQDEuA3-MHO0TJ8LIIi$ z$4*4FTJYEvbgGar$P&h3&B;cb9^@K(PBV>*{lyef&+rns#!ct60dgFHLFh~PZL(fo zUX#F{!GgX;7qr)TV0Vi}&m`R#XU{_WvW{h@f}{blk0EJP;N)4phYCjr8;})Nebo>- zlV)dE4AJ|3SXqhHUs)lL{rNm;HxG)zx--o<`is$1N}AnON#eDnhIrkn3t$`TTDW=p z&Yhb+-M(pyzjMcDTXsRu*yph3Ej!z(c$dIdO~z?rjYI6+58&po1Nw$NC=IuUS1ZzJY5Lr#5ahOKW7+I8O1jMo z$j|~v>qkZ#Y>r$xd5^$>I|ljuozm>7F-AUohmkKvGxD|^BahuQ zIQfT^JWl4pe6SHs@|N-D*;OfiIoVaQKPaIfOMh}in&?L@wF*IQiE4IopA?*g^W%P- z^*+Z&)4K%rPHM&ns_25<`8b}gg4U@OIQYOI?EZ^dvHL`KVvR$1q8-UFInhJz%H%`? zoXc6TJjK4HPdWL-WBx5Ie9kF(9C!v71C3~!>6Upy@AnelR5`t{zzMiAbuW@~vbHNY zpHPCx0qdrkapoCiMf)Q9x53o<+~DVA{M-gVrEP}q!y3=jEg}6<^r8A9|ErSNw` zd74rPLCy8$GUl4K(LZHy{G(#uT=>bfvA)9e;&eRJ4Mn9fks&$Rck+Pc|0#NJW* Q#_{>EcjS%3A%qhD1H0{*fdBvi delta 2443 zcmZ8iZ%kWN6o2=E?7a%Jn57~_cqR(Xrdf6C!akT_;)iZoVnMSsH6fTFc9=B%*vt=O z2_GuX*>WTh^h0r3RxyyibsG&VT8)1SLDE2+Ww_eFfGRS})QQ7o-hZ#JH>)kME)ztPsf<7%ZqT?uKn_mR#!otTma*h zjhIX~DjUz}$M=vOrRcc43)8(~dK1B%jV#D`l>CZuCBgKk^H=S{dkH4CLj{M&b~%^{ zrldMSbpgl5t1e?mZS0M8nJtIQhc6AdV?D2&Q28p=DL(?aQ!2=EC9^gWgO=ns-km6as(7m$)ODqIQatc33Z>e8!gX8EX zpFP4a{&%TgR$yscIPfX-#W85vCxfle4X2M=l;C-8?|_l&CL9gLYCp1IoIeLMAupKU zmmk;Ti}rEH)HzM7N0h^4m|*|$E@ivFm@0jNQ6U#hhu%7YCE87NLy{l zG5V6y5#gj%trdO7#mW&Pww)<5E`jdGlOT__ArGTWL@1^2MJ2WsIfam)u_Z-edG2yi z))3e?2KS%sG8xsU$w4+i(Sz7|RU0Mg4Mw5+s<+lUUMkTkurFFjv0(ytgOgQk=$fIS z3Hv7at=m_?eW3HTvO=DNmrKdx0;jKVyPoHGywoo%ur$T(HSp$SQ)nW|@?(&Y{De^e z4qUh6?Q5EL1VPkS6AMf@Fjl8n0t}*9-_(&k*p=iDO!}LznU3%@zkp{iG0Te~C0XaG z-x-~k_?A0nzb~Z4FtN^)=ZdLvbDYXEOQ<@FT2GqcZhA{u1$NAGyPgv1#x6gB9cj^e zCgUWy7a}MOQyDw<%!#(EwWUf4Tmt*&DFI28lAq@uTzqnYwZ+gp^euOp3~!d?D15wP z$Ib;oj?F*PRmY-?17x)Z;bU#EoNk1k)i(I_rWNk5T9ib(m_EEH5|S=7y0svQ2}m*l z>Y}*g$=uCS0p=x+ZO}UZ4-*i%ReVEFh6+GV7`fE|`JWt$aiBVL2tH}_qBNC(WZ23y z;p8v6gqEx>VR(g0aIZ26*m@g=M-QTP-rnj8Oip)!ZN?ArY+Ho?c#}@pJtQ0Fh zDwzTOzTQ9jx=g#L3`tdRJ@X7nx(um5+OV0!#1krZZ1Ip&n=sS*wo-UqvrY}(<#fF6 zzCT&r^Lh3<2;AX&dV59%PUQ1!E)AQ$^WuLA0jL>T?-hk?D-F4Y z!~)XR$Y(u zFZWe<3VIBat_L{>-^Iv|TOJ4%Sbj)WCcO*+iU!p(BqMoX1T`oQPAUZ`8uXD3EYlFY YMy)zZh5JfjPbmzR!Z3q_o(dHGABpst-~a#s diff --git a/test/blockstructure.py b/test/blockstructure.py index b0da8c5c..92f5f3b6 100644 --- a/test/blockstructure.py +++ b/test/blockstructure.py @@ -45,7 +45,8 @@ sk_pick1 = BlockStructure(gf_struct_sumk=SK.gf_struct_sumk, solver_to_sumk=SK.solver_to_sumk, sumk_to_solver=SK.sumk_to_solver, solver_to_sumk_block=SK.solver_to_sumk_block, - deg_shells=SK.deg_shells) + deg_shells=SK.deg_shells, + corr_to_inequiv=SK.corr_to_inequiv) assert sk_pick1 == pick1, 'constructing block structure from SumkDFT properties failed' cmp(pick1.effective_transformation_sumk, diff --git a/test/blockstructure.ref.h5 b/test/blockstructure.ref.h5 index c9eb42303698a3aad0d5067b8d916f9d52d8ea7b..d85903cf04181b46dd7763275e790d8b7ab2196d 100644 GIT binary patch literal 240784 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 H39tVT&h`6x literal 248384 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 h`X1N6xySWy?Q#9q>%}tYS&8Q9^9$ Date: Fri, 7 Sep 2018 15:31:41 +0200 Subject: [PATCH 12/57] block_structure: effective_transformation_solver --- python/block_structure.py | 22 ++++++++++++++++++++++ test/blockstructure.py | 26 ++++++++++++++++++++++++++ 2 files changed, 48 insertions(+) diff --git a/python/block_structure.py b/python/block_structure.py index df0cc2e9..c9cb03dd 100644 --- a/python/block_structure.py +++ b/python/block_structure.py @@ -251,6 +251,28 @@ class BlockStructure(object): trans[icrsh][block][iorb, :] = 0.0 return trans + @property + def effective_transformation_solver(self): + eff_trans_sumk = self.effective_transformation_sumk + + ets = [] + for ish in range(len(self.gf_struct_solver)): + icrsh = self.inequiv_to_corr[ish] + ets.append(dict()) + for block in self.gf_struct_solver[ish]: + block_sumk = self.solver_to_sumk_block[ish][block] + T = eff_trans_sumk[icrsh][block_sumk] + ets[ish][block] = np.zeros((len(self.gf_struct_solver[ish][block]), + len(T)), + dtype=T.dtype) + for i in self.gf_struct_solver[ish][block]: + i_sumk = self.solver_to_sumk[ish][block, i] + assert i_sumk[0] == block_sumk,\ + "Wrong block in solver_to_sumk" + i_sumk = i_sumk[1] + ets[ish][block][i, :] = T[i_sumk, :] + return ets + @classmethod def full_structure(cls,gf_struct,corr_to_inequiv): diff --git a/test/blockstructure.py b/test/blockstructure.py index 92f5f3b6..482bd570 100644 --- a/test/blockstructure.py +++ b/test/blockstructure.py @@ -22,6 +22,14 @@ cmp(original_bs.effective_transformation_sumk, 'up': np.array([[1., 0., 0.], [0., 1., 0.], [0., 0., 1.]])}]) +cmp(original_bs.effective_transformation_solver, + [{'up_0': np.array([[1., 0., 0.], + [0., 1., 0.]]), + 'up_1': np.array([[0., 0., 1.]]), + 'down_1': np.array([[0., 0., 1.]]), + 'down_0': np.array([[1., 0., 0.], + [0., 1., 0.]])}]) + # check pick_gf_struct_solver pick1 = original_bs.copy() @@ -34,6 +42,10 @@ cmp(pick1.effective_transformation_sumk, 'up': np.array([[0., 0., 0.], [0., 1., 0.], [0., 0., 1.]])}]) +cmp(pick1.effective_transformation_solver, + [{'up_0': np.array([[0., 1., 0.]]), + 'up_1': np.array([[0., 0., 1.]]), + 'down_1': np.array([[0., 0., 1.]])}]) # check loading a block_structure from file SK.block_structure = SK.load(['block_structure'], 'mod')[0] @@ -56,6 +68,10 @@ cmp(pick1.effective_transformation_sumk, 'up': np.array([[0., 0., 0.], [0., 1., 0.], [0., 0., 1.]])}]) +cmp(pick1.effective_transformation_solver, + [{'up_0': np.array([[0., 1., 0.]]), + 'up_1': np.array([[0., 0., 1.]]), + 'down_1': np.array([[0., 0., 1.]])}]) # check pick_gf_struct_sumk pick2 = original_bs.copy() @@ -68,6 +84,11 @@ cmp(pick2.effective_transformation_sumk, 'up': np.array([[0., 0., 0.], [0., 1., 0.], [0., 0., 1.]])}]) +cmp(pick2.effective_transformation_solver, + [{'up_0': np.array([[0., 1., 0.]]), + 'up_1': np.array([[0., 0., 1.]]), + 'down_0': np.array([[1., 0., 0.], + [0., 1., 0.]])}]) pick3 = pick2.copy() pick3.transformation = [np.reshape(range(9), (3, 3))] @@ -78,6 +99,11 @@ cmp(pick3.effective_transformation_sumk, 'up': np.array([[0, 0, 0], [3, 4, 5], [6, 7, 8]])}]) +cmp(pick3.effective_transformation_solver, + [{'up_0': np.array([[3, 4, 5]]), + 'up_1': np.array([[6, 7, 8]]), + 'down_0': np.array([[0, 1, 2], + [3, 4, 5]])}]) # check map_gf_struct_solver mapping = [{('down_0', 0): ('down', 0), From ff40e8e0f02055c29887f3391975596cdc3ff830 Mon Sep 17 00:00:00 2001 From: "Gernot J. Kraberger" <16017581+gkraberger@users.noreply.github.com> Date: Tue, 11 Sep 2018 14:30:17 +0200 Subject: [PATCH 13/57] [doc] block_structure: small fixes --- doc/reference/block_structure.rst | 5 ++-- python/block_structure.py | 49 +++++++++++++++++++++++++++---- 2 files changed, 45 insertions(+), 9 deletions(-) diff --git a/doc/reference/block_structure.rst b/doc/reference/block_structure.rst index ad4004c8..1fe1bebb 100644 --- a/doc/reference/block_structure.rst +++ b/doc/reference/block_structure.rst @@ -9,8 +9,8 @@ The block structure can also be written to and read from HDF files. .. warning:: Do not write the individual elements of this class to a HDF file, - as they belong together and changing one without the other can - result in unexpected results. Always write the BlockStructure + as they belong together and changing one without the other can + result in unexpected results. Always write the BlockStructure object as a whole. Writing the sumk_to_solver and solver_to_sumk elements @@ -19,4 +19,3 @@ The block structure can also be written to and read from HDF files. .. autoclass:: triqs_dft_tools.block_structure.BlockStructure :members: :show-inheritance: - diff --git a/python/block_structure.py b/python/block_structure.py index c9cb03dd..b0ce1228 100644 --- a/python/block_structure.py +++ b/python/block_structure.py @@ -84,6 +84,9 @@ class BlockStructure(object): where the :math:`G_i` are the Green's functions of the block, and the functions :math:`C_i` conjugate their argument if the bool ``conj_i`` is ``True``. + corr_to_inequiv : list + a list where, for each correlated shell, the index of the corresponding + inequivalent correlated shell is given transformation : list of numpy.array or list of dict a list with entries for each ``ish`` giving transformation matrices that are used on the Green's function in ``sumk`` space when before @@ -123,7 +126,7 @@ class BlockStructure(object): """ The structure of the solver Green's function This is returned as a - list (for each shell) + list (for each shell) of lists (for each block) of tuples (block_name, block_indices). @@ -146,7 +149,7 @@ class BlockStructure(object): """ The structure of the sumk Green's function This is returned as a - list (for each shell) + list (for each shell) of lists (for each block) of tuples (block_name, block_indices) @@ -163,7 +166,7 @@ class BlockStructure(object): """ The structure of the solver Green's function This is returned as a - list (for each shell) + list (for each shell) of dictionaries. That is, @@ -177,7 +180,7 @@ class BlockStructure(object): """ The structure of the sumk Green's function This is returned as a - list (for each shell) + list (for each shell) of dictionaries. That is, @@ -191,6 +194,9 @@ class BlockStructure(object): @property def inequiv_to_corr(self): + """ A list mapping an inequivalent correlated shell to a correlated shell + """ + if self.corr_to_inequiv is None: return None N_solver = len(np.unique(self.corr_to_inequiv)) @@ -209,6 +215,12 @@ class BlockStructure(object): @property def effective_transformation_sumk(self): + """ Return the effective transformation matrix + + A list of dicts, one for every correlated shell. In the dict, + there is a transformation matrix (as numpy array) for each + block in sumk space, that is used to transform the block. + """ trans = copy.deepcopy(self.transformation) if self.gf_struct_sumk is None: raise Exception('gf_struct_sumk not set.') @@ -253,6 +265,31 @@ class BlockStructure(object): @property def effective_transformation_solver(self): + """ Return the effective transformation matrix + + A list of dicts, one for every inequivalent correlated shell. + In the dict, there is a transformation matrix (as numpy array) + for each block in solver space, that is used to transform from + the sumk block (see :py:meth:`.solver_to_sumk_block`) to the + solver block. + + + For a solver block ``b`` for inequivalent correlated shell ``ish``, + the corresponding block of the solver Green's function is:: + + # the effective transformation matrix for the block + T = block_structure.effective_transformation_solver[ish][b] + # the index of the correlated shell + icrsh = block_structure.inequiv_to_corr[ish] + # the name of the corresponding sumk block + block_sumk = block_structure.solver_to_sumk_block[icrsh][b] + # transform the Green's function + G_solver[ish][b].from_L_G_R(T, G_sumk[icrsh][block_sumk], T.conjugate().transpose()) + + The functionality of that code block is implemented in + :py:meth:`.convert_gf` (i.e., you don't need to use this directly). + """ + eff_trans_sumk = self.effective_transformation_sumk ets = [] @@ -512,8 +549,8 @@ class BlockStructure(object): ---------- 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 + If ``space='solver'``, the index of the of the inequivalent correlated shell, + if ``space='sumk'``, the index of the correlated shell gf_function : constructor function used to construct the Gf objects constituting the individual blocks; default: GfImFreq From 6a889fab8c237abb11a3e11475c67639ce4b5d32 Mon Sep 17 00:00:00 2001 From: "Gernot J. Kraberger" <16017581+gkraberger@users.noreply.github.com> Date: Thu, 13 Sep 2018 13:57:54 +0200 Subject: [PATCH 14/57] block_structure: convert_gf with transformation --- python/block_structure.py | 96 +++++++++++++++++++++++---------------- test/blockstructure.py | 24 +++++++++- 2 files changed, 80 insertions(+), 40 deletions(-) diff --git a/python/block_structure.py b/python/block_structure.py index b0ce1228..6d700d83 100644 --- a/python/block_structure.py +++ b/python/block_structure.py @@ -29,6 +29,7 @@ from pytriqs.gf import GfImFreq, BlockGf from ast import literal_eval import pytriqs.utility.mpi as mpi from warnings import warn +from collections import defaultdict class BlockStructure(object): @@ -209,10 +210,23 @@ class BlockStructure(object): @inequiv_to_corr.setter def inequiv_to_corr(self, value): + # a check for backward compatibility if value is None: return assert self.inequiv_to_corr == value, "Trying to set incompatible inequiv_to_corr" + @property + def sumk_to_solver_block(self): + if self.corr_to_inequiv is None: + return None + ret = [] + for icrsh, ish in enumerate(self.corr_to_inequiv): + d = defaultdict(list) + for block_solver, block_sumk in self.solver_to_sumk_block[ish].iteritems(): + d[block_sumk].append(block_solver) + ret.append(d) + return ret + @property def effective_transformation_sumk(self): """ Return the effective transformation matrix @@ -671,8 +685,6 @@ class BlockStructure(object): options passed to the constructor for the new Gf """ - # TODO: use effective_transformation here - if ish is not None: warn( 'The parameter ish in convert_gf is deprecated. Use ish_from and ish_to instead.') @@ -691,55 +703,61 @@ class BlockStructure(object): G_struct = self if space_from == 'solver': - gf_struct_in = G_struct.gf_struct_solver[ish_from] + gf_struct_from = G_struct.gf_struct_solver[ish_from] + eff_trans_from = G_struct.effective_transformation_solver[ish_from] + block_mapping_from = G_struct.sumk_to_solver_block[ish_from] elif space_from == 'sumk': - gf_struct_in = G_struct.gf_struct_sumk_dict[ish_from] + gf_struct_from = G_struct.gf_struct_sumk_dict[ish_from] + eff_trans_from = {block: np.eye(len(indices)) + for block, indices in G_struct.gf_struct_sumk[ish_from]} + block_mapping_from = {b: [b] for b in gf_struct_from} else: raise Exception( "Argument space_from has to be either 'solver' or 'sumk'.") + if space_to == 'solver': + gf_struct_to = self.gf_struct_solver[ish_to] + eff_trans_to = self.effective_transformation_solver[ish_to] + block_mapping_to = self.solver_to_sumk_block[ish_to] + elif space_to == 'sumk': + gf_struct_to = self.gf_struct_sumk_dict[ish_to] + eff_trans_to = {block: np.eye(len(indices)) + for block, indices in self.gf_struct_sumk_list[ish_to]} + block_mapping_to = {b: b for b in gf_struct_to} + else: + raise Exception( + "Argument space_to has to be either 'solver' or 'sumk'.") + # create a Green's function to hold the result if G_out is None: G_out = self.create_gf(ish=ish_to, space=space_to, **kwargs) else: self.check_gf(G_out, ish=ish_to, space=space_to) - for block in gf_struct_in.keys(): - for i1 in gf_struct_in[block]: - for i2 in gf_struct_in[block]: - if space_from == 'sumk': - i1_sumk = (block, i1) - i2_sumk = (block, i2) - elif space_from == 'solver': - i1_sumk = G_struct.solver_to_sumk[ish_from][(block, i1)] - i2_sumk = G_struct.solver_to_sumk[ish_from][(block, i2)] + for block_to in gf_struct_to.keys(): + block_intermediate = block_mapping_to[block_to] + block_from = block_mapping_from[block_intermediate] + T_to = eff_trans_to[block_to] + g_help = G_out[block_to].copy() + for block in block_from: + T_from = eff_trans_from[block] + g_help.from_L_G_R(np.dot(T_to, np.conjugate(np.transpose(T_from))), + G[block], + np.dot(T_from, np.conjugate(np.transpose(T_to)))) + G_out[block_to] << G_out[block_to] + g_help - if space_to == 'sumk': - i1_sol = i1_sumk - i2_sol = i2_sumk - elif space_to == 'solver': - i1_sol = self.sumk_to_solver[ish_to][i1_sumk] - i2_sol = self.sumk_to_solver[ish_to][i2_sumk] - else: - raise Exception( - "Argument space_to has to be either 'solver' or 'sumk'.") - - if i1_sol[0] is None or i2_sol[0] is None: - if show_warnings: - if mpi.is_master_node(): - warn(('Element {},{} of block {} of G is not present ' + - 'in the new structure').format(i1, i2, block)) - continue - if i1_sol[0] != i2_sol[0]: - if (show_warnings and - np.max(np.abs(G[block][i1, i2].data)) > warning_threshold): - if mpi.is_master_node(): - warn(('Element {},{} of block {} of G is approximated ' + - 'to zero to match the new structure. Max abs value: {}').format( - i1, i2, block, np.max(np.abs(G[block][i1, i2].data)))) - continue - G_out[i1_sol[0]][i1_sol[1], i2_sol[1]] = \ - G[block][i1, i2] + if show_warnings: + # we back-transform it + G_back = G_struct.convert_gf(G_out, self, ish_from=ish_to, + ish_to=ish_from, + show_warnings=False, # else we get an endless loop + space_from=space_to, space_to=space_from, **kwargs) + for name, gf in G_back: + maxdiff = np.max(np.abs(G_back[name].data - G[name].data), + axis=0) + if np.any(maxdiff > warning_threshold): + warn('Block {} maximum difference:\n'.format(name) + + str(maxdiff)) return G_out def approximate_as_diagonal(self): diff --git a/test/blockstructure.py b/test/blockstructure.py index 482bd570..27ff65ab 100644 --- a/test/blockstructure.py +++ b/test/blockstructure.py @@ -2,6 +2,7 @@ from triqs_dft_tools.sumk_dft import * from pytriqs.utility.h5diff import h5diff from pytriqs.gf import * from pytriqs.utility.comparison_tests import assert_block_gfs_are_close +from scipy.linalg import expm from triqs_dft_tools.block_structure import BlockStructure import numpy as np from pytriqs.utility.h5diff import compare, failures @@ -127,7 +128,14 @@ offd = original_bs.copy() offd.approximate_as_diagonal() # check map_gf_struct_solver -G2 = map1.convert_gf(G1, original_bs, beta=40, n_points=3, show_warnings=False) +import warnings +with warnings.catch_warnings(record=True) as w: + G2 = map1.convert_gf(G1, original_bs, beta=40, n_points=3, + show_warnings=True) + assert len(w) == 1 + assert issubclass(w[-1].category, UserWarning) + assert "Block up_1 maximum difference" in str(w[-1].message) + # check full_structure full = BlockStructure.full_structure( @@ -144,6 +152,20 @@ G3 = original_bs.convert_gf(G_sumk, n_points=3) assert_block_gfs_are_close(G1, G3) +# check convert_gf with transformation +# np.random.seed(894892309) +H = np.random.rand(3, 3) + 1.0j * np.random.rand(3, 3) +H = H + H.conjugate().transpose() +T = expm(1.0j * H) +G_T = G_sumk.copy() +for block, gf in G_T: + gf.from_L_G_R(T.conjugate().transpose(), gf, T) +transformed_bs = original_bs.copy() +transformed_bs.transformation = [T] +G_bT = transformed_bs.convert_gf(G_T, None, space_from='sumk', + beta=40, n_points=3) +assert_block_gfs_are_close(G1, G_bT) + assert original_bs.gf_struct_sumk_list ==\ [[('up', [0, 1, 2]), ('down', [0, 1, 2])]] assert original_bs.gf_struct_solver_dict ==\ From 8130d6b9fc907f9d94108ef89158ca69cc5502b6 Mon Sep 17 00:00:00 2001 From: "Gernot J. Kraberger" <16017581+gkraberger@users.noreply.github.com> Date: Thu, 13 Sep 2018 16:27:12 +0200 Subject: [PATCH 15/57] block_structure: pick_gf_struct_sumk with transformation plus little bug fixes --- python/block_structure.py | 77 ++++++++++++++++++++++++++------------- python/sumk_dft.py | 2 +- test/blockstructure.py | 16 ++++++++ 3 files changed, 68 insertions(+), 27 deletions(-) diff --git a/python/block_structure.py b/python/block_structure.py index 6d700d83..79812cb0 100644 --- a/python/block_structure.py +++ b/python/block_structure.py @@ -217,10 +217,10 @@ class BlockStructure(object): @property def sumk_to_solver_block(self): - if self.corr_to_inequiv is None: + if self.inequiv_to_corr is None: return None ret = [] - for icrsh, ish in enumerate(self.corr_to_inequiv): + for ish, icrsh in enumerate(self.inequiv_to_corr): d = defaultdict(list) for block_solver, block_sumk in self.solver_to_sumk_block[ish].iteritems(): d[block_sumk].append(block_solver) @@ -252,6 +252,7 @@ class BlockStructure(object): "give one transformation per correlated shell" for icrsh in range(len(trans)): + ish = self.corr_to_inequiv[icrsh] if trans[icrsh] is None: trans[icrsh] = {block: np.eye(len(indices)) for block, indices in self.gf_struct_sumk[icrsh]} @@ -273,7 +274,7 @@ class BlockStructure(object): # zero out all the lines of the transformation that are # not included in gf_struct_solver for iorb, norb in enumerate(self.gf_struct_sumk_dict[icrsh][block]): - if self.sumk_to_solver[icrsh][(block, norb)][0] is None: + if self.sumk_to_solver[ish][(block, norb)][0] is None: trans[icrsh][block][iorb, :] = 0.0 return trans @@ -381,7 +382,7 @@ class BlockStructure(object): deg_shells = [[] for ish in range(len(gf_struct))], corr_to_inequiv = corr_to_inequiv) - def pick_gf_struct_solver(self,new_gf_struct): + def pick_gf_struct_solver(self, new_gf_struct): """ Pick selected orbitals within blocks. This throws away parts of the Green's function that (for some @@ -419,28 +420,28 @@ class BlockStructure(object): gf_struct = new_gf_struct[ish] # create new solver_to_sumk - so2su={} + so2su = {} so2su_block = {} - for blk,idxs in gf_struct.items(): + for blk, idxs in gf_struct.items(): for i in range(len(idxs)): - so2su[(blk,i)]=self.solver_to_sumk[ish][(blk,idxs[i])] - so2su_block[blk]=so2su[(blk,i)][0] + so2su[(blk, i)] = self.solver_to_sumk[ish][(blk, idxs[i])] + so2su_block[blk] = so2su[(blk, i)][0] self.solver_to_sumk[ish] = so2su self.solver_to_sumk_block[ish] = so2su_block # create new sumk_to_solver - for k,v in self.sumk_to_solver[ish].items(): - blk,ind=v + for k, v in self.sumk_to_solver[ish].items(): + blk, ind = v if blk in gf_struct and ind in gf_struct[blk]: new_ind = gf_struct[blk].index(ind) - self.sumk_to_solver[ish][k]=(blk,new_ind) + self.sumk_to_solver[ish][k] = (blk, new_ind) else: - self.sumk_to_solver[ish][k]=(None,None) + self.sumk_to_solver[ish][k] = (None, None) # reindexing gf_struct so that it starts with 0 for k in gf_struct: - gf_struct[k]=range(len(gf_struct[k])) - self.gf_struct_solver[ish]=gf_struct + gf_struct[k] = range(len(gf_struct[k])) + self.gf_struct_solver[ish] = gf_struct - def pick_gf_struct_sumk(self,new_gf_struct): + def pick_gf_struct_sumk(self, new_gf_struct): """ Pick selected orbitals within blocks. This throws away parts of the Green's function that (for some @@ -475,24 +476,46 @@ class BlockStructure(object): However, the indices are not according to the solver Gf but the sumk Gf. """ + eff_trans_sumk = self.effective_transformation_sumk - # TODO: when there is a transformation matrix, this should - # first zero out the corresponding rows of (a copy of) T and then - # pick_gf_struct_solver all lines of (the copy of) T that have at least - # one non-zero entry + assert len(eff_trans_sumk) == len(new_gf_struct),\ + "new_gf_struct has the wrong length" + + new_gf_struct_transformed = copy.deepcopy(new_gf_struct) + + # when there is a transformation matrix, this first zeroes out + # the corresponding rows of (a copy of) T and then applies + # pick_gf_struct_solver for all lines of T that have at least + # one non-zero entry + + for icrsh in range(len(new_gf_struct)): + for block, indices in self.gf_struct_sumk[icrsh]: + if not block in new_gf_struct[icrsh]: + del new_gf_struct_transformed[block] + continue + T = eff_trans_sumk[icrsh][block] + for index in indices: + if not index in new_gf_struct[icrsh][block]: + T[:, index] = 0.0 + new_indices = [] + for index in indices: + if np.any(np.abs(T[index, :]) > 1.e-15): + new_indices.append(index) + new_gf_struct_transformed[icrsh][block] = new_indices gfs = [] # construct gfs, which is the equivalent of new_gf_struct # but according to the solver Gf, by using the sumk_to_solver # mapping - for ish in range(len(new_gf_struct)): + for icrsh in range(len(new_gf_struct_transformed)): + ish = self.corr_to_inequiv[icrsh] gfs.append({}) - for block in new_gf_struct[ish].keys(): - for ind in new_gf_struct[ish][block]: - ind_sol = self.sumk_to_solver[ish][(block,ind)] - if not ind_sol[0] in gfs[ish]: - gfs[ish][ind_sol[0]]=[] - gfs[ish][ind_sol[0]].append(ind_sol[1]) + for block in new_gf_struct_transformed[icrsh].keys(): + for ind in new_gf_struct_transformed[icrsh][block]: + ind_sol = self.sumk_to_solver[ish][(block, ind)] + if not ind_sol[0] in gfs[icrsh]: + gfs[icrsh][ind_sol[0]] = [] + gfs[icrsh][ind_sol[0]].append(ind_sol[1]) self.pick_gf_struct_solver(gfs) def map_gf_struct_solver(self, mapping): @@ -730,6 +753,8 @@ class BlockStructure(object): # create a Green's function to hold the result if G_out is None: + if not 'mesh' in kwargs and not 'beta' in 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) diff --git a/python/sumk_dft.py b/python/sumk_dft.py index 854ee564..1ae7febb 100644 --- a/python/sumk_dft.py +++ b/python/sumk_dft.py @@ -1080,7 +1080,7 @@ class SumkDFT(object): full_structure = BlockStructure.full_structure( [{sp:range(self.corr_shells[self.inequiv_to_corr[ish]]['dim']) for sp in self.spin_block_names[self.corr_shells[self.inequiv_to_corr[ish]]['SO']]} - for ish in range(self.n_inequiv_shells)],None) + for ish in range(self.n_inequiv_shells)],self.corr_to_inequiv) G_transformed = [ self.block_structure.convert_gf(G[ish], full_structure, ish, mesh=G[ish].mesh.copy(), show_warnings=threshold, diff --git a/test/blockstructure.py b/test/blockstructure.py index 27ff65ab..f7a581be 100644 --- a/test/blockstructure.py +++ b/test/blockstructure.py @@ -106,6 +106,22 @@ cmp(pick3.effective_transformation_solver, 'down_0': np.array([[0, 1, 2], [3, 4, 5]])}]) +pick4 = original_bs.copy() +pick4.transformation = [np.array([[0, 1, 0], [1, 0, 0], [0, 0, 1]])] +pick4.pick_gf_struct_sumk([{'up': [1, 2], 'down': [0, 1]}]) +cmp(pick2.gf_struct_sumk, pick4.gf_struct_sumk) +cmp(pick2.gf_struct_solver, pick4.gf_struct_solver) +assert pick4.sumk_to_solver == [{('up', 0): ('up_0', 0), + ('up', 1): (None, None), + ('up', 2): ('up_1', 0), + ('down', 2): (None, None), + ('down', 1): ('down_0', 1), + ('down', 0): ('down_0', 0)}] +assert pick4.solver_to_sumk == [{('up_1', 0): ('up', 2), + ('up_0', 0): ('up', 0), + ('down_0', 0): ('down', 0), + ('down_0', 1): ('down', 1)}] + # check map_gf_struct_solver mapping = [{('down_0', 0): ('down', 0), ('down_0', 1): ('down', 2), From f0b1599379847d5778aeaa18ffafb2ebc86d7c00 Mon Sep 17 00:00:00 2001 From: "Gernot J. Kraberger" <16017581+gkraberger@users.noreply.github.com> Date: Thu, 13 Sep 2018 17:11:30 +0200 Subject: [PATCH 16/57] SumkDFT: transform in calc_dc --- python/sumk_dft.py | 35 ++++++++++++++++++++--------------- 1 file changed, 20 insertions(+), 15 deletions(-) diff --git a/python/sumk_dft.py b/python/sumk_dft.py index 1ae7febb..03e4cbbb 100644 --- a/python/sumk_dft.py +++ b/python/sumk_dft.py @@ -36,9 +36,6 @@ from warnings import warn from scipy import compress from scipy.optimize import minimize -# TODO: check where the transformation in block_structure has to enter -# - DC - class SumkDFT(object): """This class provides a general SumK method for combining ab-initio code and pytriqs.""" @@ -1526,21 +1523,22 @@ class SumkDFT(object): dc_imp : gf_struct_sumk like Double-counting self-energy term. dc_energ : list of floats - Double-counting energy corrections for each correlated shell. + Double-counting energy corrections for each correlated shell. """ self.dc_imp = dc_imp self.dc_energ = dc_energ - def calc_dc(self, dens_mat, orb=0, U_interact=None, J_hund=None, use_dc_formula=0, use_dc_value=None): + def calc_dc(self, dens_mat, orb=0, U_interact=None, J_hund=None, + use_dc_formula=0, use_dc_value=None, transform=True): r""" - Calculates and sets the double counting corrections. + Calculate and set the double counting corrections. If 'use_dc_value' is provided the double-counting term is uniformly initialized with this constant and 'U_interact' and 'J_hund' are ignored. - If 'use_dc_value' is None the correction is evaluated according to + If 'use_dc_value' is None the correction is evaluated according to one of the following formulae: * use_dc_formula = 0: fully-localised limit (FLL) @@ -1558,19 +1556,21 @@ class SumkDFT(object): Parameters ---------- dens_mat : gf_struct_solver like - Density matrix for the specified correlated shell. + Density matrix for the specified correlated shell. orb : int, optional - Index of an inequivalent shell. + Index of an inequivalent shell. U_interact : float, optional - Value of interaction parameter `U`. + Value of interaction parameter `U`. J_hund : float, optional - Value of interaction parameter `J`. + Value of interaction parameter `J`. use_dc_formula : int, optional - Type of double-counting correction (see description). + Type of double-counting correction (see description). use_dc_value : float, optional - Value of the double-counting correction. If specified - `U_interact`, `J_hund` and `use_dc_formula` are ignored. - + Value of the double-counting correction. If specified + `U_interact`, `J_hund` and `use_dc_formula` are ignored. + transform : bool + whether or not to use the transformation in block_structure + to transform the dc """ for icrsh in range(self.n_corr_shells): @@ -1651,6 +1651,11 @@ class SumkDFT(object): mpi.report( "DC for shell %(icrsh)i = %(use_dc_value)f" % locals()) mpi.report("DC energy = %s" % self.dc_energ[icrsh]) + if transform: + for sp in spn: + T = self.block_structure.effective_transformation_sumk[icrsh][sp] + self.dc_imp[icrsh][sp] = numpy.dot(T.conjugate().transpose(), + numpy.dot(self.dc_imp[icrsh][sp], T)) def add_dc(self, iw_or_w="iw"): r""" From 8e4c923d21a50f6598ffd2bf3a7dfbb0dafd3002 Mon Sep 17 00:00:00 2001 From: "Gernot J. Kraberger" <16017581+gkraberger@users.noreply.github.com> Date: Mon, 17 Sep 2018 13:32:50 +0200 Subject: [PATCH 17/57] [block_structure] create_matrix etc. --- python/block_structure.py | 195 ++++++++++++++++++++++++++++++++------ python/sumk_dft.py | 5 + test/blockstructure.py | 16 ++++ 3 files changed, 189 insertions(+), 27 deletions(-) diff --git a/python/block_structure.py b/python/block_structure.py index 79812cb0..f7f3317c 100644 --- a/python/block_structure.py +++ b/python/block_structure.py @@ -598,6 +598,36 @@ class BlockStructure(object): 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': gf_struct = self.gf_struct_solver elif space == 'sumk': @@ -611,7 +641,7 @@ class BlockStructure(object): for n in names: G = gf_function(indices=gf_struct[ish][n], **kwargs) blocks.append(G) - G = BlockGf(name_list=names, block_list=blocks) + G = block_function(name_list=names, block_list=blocks) return G def check_gf(self, G, ish=None, space='solver'): @@ -636,6 +666,34 @@ class BlockStructure(object): 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': gf_struct = self.gf_struct_solver elif space == 'sumk': @@ -658,16 +716,28 @@ class BlockStructure(object): if ish is None: ish = 0 - for block in gf_struct[ish]: - assert block in G.indices,\ - "block " + block + " not in G (shell {})".format(ish) - for block, gf in G: - assert block in gf_struct[ish],\ - "block " + block + " not in struct (shell {})".format(ish) - assert list(gf.indices) == 2 * [map(str, gf_struct[ish][block])],\ - "block " + block + " has wrong indices (shell {})".format(ish) + if isinstance(G, BlockGf): + for block in gf_struct[ish]: + assert block in G.indices,\ + "block " + block + " not in G (shell {})".format(ish) + for block, gf in G: + assert block in gf_struct[ish],\ + "block " + block + " not in struct (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): """ Convert BlockGf from its structure to this structure. @@ -714,6 +784,56 @@ class BlockStructure(object): ish_from = 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: ish_to = ish_from @@ -751,35 +871,56 @@ class BlockStructure(object): raise Exception( "Argument space_to has to be either 'solver' or 'sumk'.") - # create a Green's function to hold the result - if G_out is None: - if not 'mesh' in kwargs and not 'beta' in kwargs: - kwargs['mesh'] = G.mesh - G_out = self.create_gf(ish=ish_to, space=space_to, **kwargs) + if isinstance(G, BlockGf): + # create a Green's function to hold the result + if G_out is None: + if not 'mesh' in kwargs and not 'beta' in 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: - 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(): + if isinstance(G, BlockGf): + G_out[block_to].zero() + else: + G_out[block_to][:] = 0.0 block_intermediate = block_mapping_to[block_to] block_from = block_mapping_from[block_intermediate] T_to = eff_trans_to[block_to] g_help = G_out[block_to].copy() for block in block_from: T_from = eff_trans_from[block] - g_help.from_L_G_R(np.dot(T_to, np.conjugate(np.transpose(T_from))), - G[block], - np.dot(T_from, np.conjugate(np.transpose(T_to)))) - G_out[block_to] << G_out[block_to] + g_help + if isinstance(G, BlockGf): + g_help.from_L_G_R(np.dot(T_to, np.conjugate(np.transpose(T_from))), + G[block], + 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: # we back-transform it - G_back = G_struct.convert_gf(G_out, self, ish_from=ish_to, - ish_to=ish_from, - show_warnings=False, # else we get an endless loop - space_from=space_to, space_to=space_from, **kwargs) - for name, gf in G_back: - maxdiff = np.max(np.abs(G_back[name].data - G[name].data), - axis=0) + G_back = G_struct._convert_gf_or_matrix(G_out, self, ish_from=ish_to, + ish_to=ish_from, + show_warnings=False, # else we get an endless loop + space_from=space_to, space_to=space_from, **kwargs) + for name, gf in (G_back if isinstance(G, BlockGf) else G_back.iteritems()): + if isinstance(G, BlockGf): + 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): warn('Block {} maximum difference:\n'.format(name) + str(maxdiff)) diff --git a/python/sumk_dft.py b/python/sumk_dft.py index 03e4cbbb..4fb912a8 100644 --- a/python/sumk_dft.py +++ b/python/sumk_dft.py @@ -776,6 +776,9 @@ class SumkDFT(object): ------- G_out """ + + assert isinstance(G_loc, list), "G_loc must be a list (with elements for each correlated shell)" + if G_out is None: 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)] @@ -1009,6 +1012,8 @@ class SumkDFT(object): 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) # initialize the variables diff --git a/test/blockstructure.py b/test/blockstructure.py index f7a581be..30aec6f6 100644 --- a/test/blockstructure.py +++ b/test/blockstructure.py @@ -31,6 +31,15 @@ cmp(original_bs.effective_transformation_solver, 'down_0': np.array([[1., 0., 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 pick1 = original_bs.copy() @@ -152,6 +161,13 @@ with warnings.catch_warnings(record=True) as w: assert issubclass(w[-1].category, UserWarning) 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 full = BlockStructure.full_structure( From 1705e5268f2915592cdf15a32ed09ec4abec6d38 Mon Sep 17 00:00:00 2001 From: "Gernot J. Kraberger" <16017581+gkraberger@users.noreply.github.com> Date: Thu, 7 Feb 2019 14:09:18 +0100 Subject: [PATCH 18/57] blockstructure: adapt deg_shells in pick --- python/block_structure.py | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/python/block_structure.py b/python/block_structure.py index f7f3317c..fd34c48a 100644 --- a/python/block_structure.py +++ b/python/block_structure.py @@ -436,6 +436,24 @@ class BlockStructure(object): self.sumk_to_solver[ish][k] = (blk, new_ind) else: self.sumk_to_solver[ish][k] = (None, None) + # adapt deg_shells + if self.deg_shells is not None: + for degsh in self.deg_shells[ish]: + for key in degsh.keys(): + if isinstance(degsh, dict): + if not key in gf_struct: + del degsh[key] + continue + if gf_struct[key] != self.gf_struct_solver[ish][key]: + v, C = degsh[key] + degsh[key][0] = \ + v[gf_struct[key], :][:, gf_struct[key]] + warn( + 'Removing shells from degenerate shell {}. Cannot guarantee that they continue to be equivalent.') + else: + if not key in gf_struct: + degsh.remove(key) + continue # reindexing gf_struct so that it starts with 0 for k in gf_struct: gf_struct[k] = range(len(gf_struct[k])) From 51275c772d5411324e47ae963802d569a5fbfafa Mon Sep 17 00:00:00 2001 From: Hermann Ulrich Schnait Date: Tue, 4 Jun 2019 16:48:23 +0200 Subject: [PATCH 19/57] Bugfix in Blockstructure Test --- python/block_structure.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/python/block_structure.py b/python/block_structure.py index fd34c48a..7563c224 100644 --- a/python/block_structure.py +++ b/python/block_structure.py @@ -439,8 +439,8 @@ class BlockStructure(object): # adapt deg_shells if self.deg_shells is not None: for degsh in self.deg_shells[ish]: - for key in degsh.keys(): - if isinstance(degsh, dict): + if isinstance(degsh, dict): + for key in degsh.keys(): if not key in gf_struct: del degsh[key] continue @@ -450,7 +450,8 @@ class BlockStructure(object): v[gf_struct[key], :][:, gf_struct[key]] warn( 'Removing shells from degenerate shell {}. Cannot guarantee that they continue to be equivalent.') - else: + else: # degshell is list + for key in degsh: if not key in gf_struct: degsh.remove(key) continue From 743ff09cac3cc19b2dd59f22447fb21c81c8ad71 Mon Sep 17 00:00:00 2001 From: Hermann Schnait Date: Wed, 5 Jun 2019 09:24:53 +0200 Subject: [PATCH 20/57] Changed 'orb' parameter to 'ish' for consistency --- python/sumk_dft.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/python/sumk_dft.py b/python/sumk_dft.py index 4fb912a8..d3f5ebea 100644 --- a/python/sumk_dft.py +++ b/python/sumk_dft.py @@ -1692,7 +1692,7 @@ class SumkDFT(object): return sigma_minus_dc - def symm_deg_gf(self, gf_to_symm, orb): + def symm_deg_gf(self, gf_to_symm, ish=0): r""" Averages a GF over degenerate shells. @@ -1704,8 +1704,8 @@ class SumkDFT(object): ---------- gf_to_symm : gf_struct_solver like Input and output GF (i.e., it gets overwritten) - orb : int - Index of an inequivalent shell. + ish : int + Index of an inequivalent shell. (default value 0) """ @@ -1713,7 +1713,7 @@ class SumkDFT(object): # an h5 file, self.deg_shells might be None if self.deg_shells is None: return - for degsh in self.deg_shells[orb]: + for degsh in self.deg_shells[ish]: # ss will hold the averaged orbitals in the basis where the # blocks are all equal # i.e. maybe_conjugate(v^dagger gf v) From 3d0adafad27bb09203907deb7c65943d40de0eb3 Mon Sep 17 00:00:00 2001 From: Hermann Schnait Date: Wed, 5 Jun 2019 11:43:00 +0200 Subject: [PATCH 21/57] Modified test-reference files to changed degshells when picking gf-struct --- test/blockstructure.in.h5 | Bin 67352 -> 67352 bytes test/blockstructure.ref.h5 | Bin 240784 -> 240784 bytes 2 files changed, 0 insertions(+), 0 deletions(-) diff --git a/test/blockstructure.in.h5 b/test/blockstructure.in.h5 index 7e03651c9fa5b68fa3be4e9480d8a2a236ed296c..f4d2cada3e2ec1a058b2848f6dc39fe9cfd6e882 100644 GIT binary patch delta 47 zcmV+~0MP%Kjs%#F1h62Kv%t3y0+TS77?Thh5VKg8W)cAblfS4bvtTDc0h3^;GP7E$ FzFfCz5{du- delta 53 zcmV-50LuTEjs%#F1h62K0T8jV2Lh8&fe4c@mKc-ZkxsLgmM9Vd0+YX}DU*;82m%1A Lv9S&TvZ@$e9gY*s diff --git a/test/blockstructure.ref.h5 b/test/blockstructure.ref.h5 index d85903cf04181b46dd7763275e790d8b7ab2196d..74857307853722ac906bdc6a2acc24abf214744f 100644 GIT binary patch delta 107 zcmbPmlW)RJzJ?aYEld@cw>Lau6kwX(ag|A8vcf5W={rIgJ+}Y2$|T1$S?@L1bcGvC z3L6hdFiw7OG-~^%n@n=0Pz?_Pn86yha|ANWF@n_^1TllvPJgh1IePoyVCJ(C0BeUU AV*mgE delta 117 zcmbPmlW)RJzJ?aYEld@cw;Mz<3NTIYxXL6k{lO{5i0wbFGRZMbu9M=Lu5g1%VY-7j zBPY{Mri~kU87DtD8nu1XO(wZgsHO)2%o39~JPDZY5y*TGti>RRSz&U3B_~rbGf2nu P2P>GPw;v8>J{ti5g~Tkk From ba79a7f7086c07a63de5ed1afba5e3445ef42c7a Mon Sep 17 00:00:00 2001 From: Hermann Schnait Date: Wed, 5 Jun 2019 12:10:12 +0200 Subject: [PATCH 22/57] Modified map_gf_struct to remove degshells + update test case --- python/block_structure.py | 1 + test/blockstructure.ref.h5 | Bin 240784 -> 240784 bytes 2 files changed, 1 insertion(+) diff --git a/python/block_structure.py b/python/block_structure.py index 7563c224..b7ea824f 100644 --- a/python/block_structure.py +++ b/python/block_structure.py @@ -591,6 +591,7 @@ class BlockStructure(object): self.solver_to_sumk[ish] = so2su self.sumk_to_solver[ish] = su2so self.solver_to_sumk_block[ish] = so2su_block + self.deg_shells[ish] = [] def create_gf(self, ish=0, gf_function=GfImFreq, space='solver', **kwargs): """ Create a zero BlockGf having the correct structure. diff --git a/test/blockstructure.ref.h5 b/test/blockstructure.ref.h5 index 74857307853722ac906bdc6a2acc24abf214744f..4b2ab4040bfde95433a1fbdb888e0b7d8734ae82 100644 GIT binary patch delta 49 zcmbPmlW)RJzJ@J~-+U*3J0-RK$0BA9rpXN#1*U5RFiK2caFxlgy)S?fh?%zc1u!$k F001_66m0+i delta 47 zcmbPmlW)RJzJ@J~-+U+gF-tLh2-&U`$tcD&T_b=|V(JE_i1rx)j6lq^eMSKDk7xk1 CHxZiv From 187499b00f72157b6501e90cf738b2209ebac70a Mon Sep 17 00:00:00 2001 From: Hermann Schnait Date: Wed, 5 Jun 2019 16:24:38 +0200 Subject: [PATCH 23/57] Bugfixes in block_structure --- python/block_structure.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/python/block_structure.py b/python/block_structure.py index b7ea824f..e5659b49 100644 --- a/python/block_structure.py +++ b/python/block_structure.py @@ -451,10 +451,11 @@ class BlockStructure(object): warn( 'Removing shells from degenerate shell {}. Cannot guarantee that they continue to be equivalent.') else: # degshell is list - for key in degsh: + degsh1 = copy.deepcopy(degsh) # in order to not remove a key while iterating + for key in degsh1: if not key in gf_struct: + warn('Removing shells from degenerate shell {}.') degsh.remove(key) - continue # reindexing gf_struct so that it starts with 0 for k in gf_struct: gf_struct[k] = range(len(gf_struct[k])) @@ -510,7 +511,7 @@ class BlockStructure(object): for icrsh in range(len(new_gf_struct)): for block, indices in self.gf_struct_sumk[icrsh]: if not block in new_gf_struct[icrsh]: - del new_gf_struct_transformed[block] + #del new_gf_struct_transformed[block] # this MUST be wrong, as new_gf_struct_transformed needs to have a integer index for icrsh... # error when index is not kept at all continue T = eff_trans_sumk[icrsh][block] for index in indices: From 159ee1166eaeba8be14a87ff86d8b98cd595a9a7 Mon Sep 17 00:00:00 2001 From: Hermann Schnait Date: Tue, 18 Jun 2019 09:59:45 +0200 Subject: [PATCH 24/57] Thread show_warnings through to extract_gloc in SK --- python/sumk_dft.py | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/python/sumk_dft.py b/python/sumk_dft.py index d3f5ebea..db914cd9 100644 --- a/python/sumk_dft.py +++ b/python/sumk_dft.py @@ -667,7 +667,7 @@ class SumkDFT(object): return Sigma_out def extract_G_loc(self, mu=None, iw_or_w='iw', with_Sigma=True, with_dc=True, broadening=None, - transform_to_solver_blocks=True): + transform_to_solver_blocks=True, show_warnings=True): r""" Extracts the local downfolded Green function by the Brillouin-zone integration of the lattice Green's function. @@ -686,6 +686,9 @@ class SumkDFT(object): transform_to_solver_blocks : bool, optional If True (default), the returned G_loc will be transformed to the block structure ``gf_struct_solver``, else it will be in ``gf_struct_sumk``. + show_warnings : bool, optional + Displays warning messages during transformation + (Only effective if transform_to_solver_blocks = True Returns ------- @@ -753,11 +756,11 @@ class SumkDFT(object): icrsh, gf, direction='toLocal') if transform_to_solver_blocks: - return self.transform_to_solver_blocks(G_loc) + return self.transform_to_solver_blocks(G_loc, show_warnings=show_warnings) return G_loc - def transform_to_solver_blocks(self, G_loc, G_out=None): + def transform_to_solver_blocks(self, G_loc, G_out=None, show_warnings = True): """ transform G_loc from sumk to solver space Parameters @@ -794,7 +797,8 @@ class SumkDFT(object): ish_from=self.inequiv_to_corr[ish], ish_to=ish, space_from='sumk', - G_out=G_out[ish]) + G_out=G_out[ish], + show_warnings = show_warnings) # return only the inequivalent shells: return G_out From 32356a06baf4c01d7ca9465cdb68e709b39c0b13 Mon Sep 17 00:00:00 2001 From: Hermann Schnait Date: Tue, 18 Jun 2019 14:57:19 +0200 Subject: [PATCH 25/57] Calculate diagonalization in solver blocks --- python/block_structure.py | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/python/block_structure.py b/python/block_structure.py index e5659b49..3062956f 100644 --- a/python/block_structure.py +++ b/python/block_structure.py @@ -942,9 +942,23 @@ class BlockStructure(object): axis=0) else: maxdiff = G_back[name] - G[name] - if np.any(maxdiff > warning_threshold): + + if space_to == 'solver': # do comparison in solver (ignore diff. in ignored orbitals) + maxdiff = G_struct._convert_gf_or_matrix({'ud':maxdiff}, self, ish_from=ish_from, + ish_to=ish_to, + show_warnings=False, + space_from=space_from, space_to=space_to, **kwargs) + + for block in maxdiff: + maxdiff_b = maxdiff[block] + if np.any(maxdiff_b > warning_threshold): + warn('Block {} maximum difference:\n'.format(name) + str(maxdiff)) + + + elif np.any(maxdiff > warning_threshold): warn('Block {} maximum difference:\n'.format(name) + str(maxdiff)) + return G_out def approximate_as_diagonal(self): From 6623a397392f87175c51a32e1529567151afade3 Mon Sep 17 00:00:00 2001 From: Hermann Schnait Date: Tue, 18 Jun 2019 14:57:46 +0200 Subject: [PATCH 26/57] Display transformation warnings only for relevant (solver) blocks --- python/trans_basis.py | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/python/trans_basis.py b/python/trans_basis.py index 91a014a5..ef573efc 100644 --- a/python/trans_basis.py +++ b/python/trans_basis.py @@ -48,7 +48,7 @@ class TransBasis: self.T = copy.deepcopy(self.SK.T[0]) self.w = numpy.identity(SK.corr_shells[0]['dim']) - def calculate_diagonalisation_matrix(self, prop_to_be_diagonal='eal'): + def calculate_diagonalisation_matrix(self, prop_to_be_diagonal='eal', calc_in_solver_blocks = False): """ Calculates the diagonalisation matrix w, and stores it as member of the class. @@ -76,6 +76,13 @@ class TransBasis: "trans_basis: not a valid quantitiy to be diagonal. Choices are 'eal' or 'dm'.") return 0 + if calc_in_solver_blocks: + trafo = self.SK.block_structure.transformation + self.SK.block_structre.transform = None + prop_solver = self.SK.block_structre.convert_matrix(prop, space_from='sumk', space_to='solver') + prop = self.SK.block_structre.convert_matrix(prop_solver, space_from='solver', space_to='sumk') + self.SK.block_structre.transform = trafo + if self.SK.SO == 0: self.eig, self.w = numpy.linalg.eigh(prop['up']) # calculate new Transformation matrix From a44f3d36f4f089254cb6a154e5287afd12ef6cc4 Mon Sep 17 00:00:00 2001 From: Hermann Schnait Date: Tue, 18 Jun 2019 16:35:25 +0200 Subject: [PATCH 27/57] Reworked Diagonalization function to ignore 'picked out' obitals (e.g. egs) --- python/trans_basis.py | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/python/trans_basis.py b/python/trans_basis.py index ef573efc..f00140d6 100644 --- a/python/trans_basis.py +++ b/python/trans_basis.py @@ -78,10 +78,15 @@ class TransBasis: if calc_in_solver_blocks: trafo = self.SK.block_structure.transformation - self.SK.block_structre.transform = None - prop_solver = self.SK.block_structre.convert_matrix(prop, space_from='sumk', space_to='solver') - prop = self.SK.block_structre.convert_matrix(prop_solver, space_from='solver', space_to='sumk') - self.SK.block_structre.transform = trafo + self.SK.block_structure.transform = None + prop_solver = self.SK.block_structure.convert_matrix(prop, space_from='sumk', space_to='solver') + v= [] + for name in prop_solver: + v[name] = numpy.linalg.eigh(prop_solver[name])[1] + self.w = self.SK.block_structure.convert_matrix(v, space_from='solver', space_to='sumk')['ud' if self.SK.SO else 'up'] + self.T = numpy.dot(self.T.transpose().conjugate(), + self.w).conjugate().transpose() + self.SK.block_structure.transform = trafo if self.SK.SO == 0: self.eig, self.w = numpy.linalg.eigh(prop['up']) From d66950a043fad7507fe8f1a81edf8c4c9d6829b7 Mon Sep 17 00:00:00 2001 From: Hermann Schnait Date: Tue, 18 Jun 2019 16:53:23 +0200 Subject: [PATCH 28/57] Remove show_warning again as it is not necessary anymore --- python/sumk_dft.py | 52 +++++++++++++++++++++------------------------- 1 file changed, 24 insertions(+), 28 deletions(-) diff --git a/python/sumk_dft.py b/python/sumk_dft.py index db914cd9..8da2751e 100644 --- a/python/sumk_dft.py +++ b/python/sumk_dft.py @@ -52,11 +52,11 @@ class SumkDFT(object): hdf_file : string Name of hdf5 containing the data. h_field : scalar, optional - The value of magnetic field to add to the DFT Hamiltonian. + The value of magnetic field to add to the DFT Hamiltonian. The contribution -h_field*sigma is added to diagonal elements of the Hamiltonian. It cannot be used with the spin-orbit coupling on; namely h_field is set to 0 if self.SO=True. use_dft_blocks : boolean, optional - If True, the local Green's function matrix for each spin is divided into smaller blocks + If True, the local Green's function matrix for each spin is divided into smaller blocks with the block structure determined from the DFT density matrix of the corresponding correlated shell. Alternatively and additionally, the block structure can be analysed using :meth:`analyse_block_structure ` @@ -64,7 +64,7 @@ class SumkDFT(object): dft_data : string, optional Name of hdf5 subgroup in which DFT data for projector and lattice Green's function construction are stored. symmcorr_data : string, optional - Name of hdf5 subgroup in which DFT data on symmetries of correlated shells + Name of hdf5 subgroup in which DFT data on symmetries of correlated shells (symmetry operations, permutaion matrices etc.) are stored. parproj_data : string, optional Name of hdf5 subgroup in which DFT data on non-normalized projectors for non-correlated @@ -291,10 +291,10 @@ class SumkDFT(object): bname : string Block name of the target block of the lattice Green's function. - gf_to_downfold : Gf + gf_to_downfold : Gf Block of the Green's function that is to be downfolded. - gf_inp : Gf - FIXME + gf_inp : Gf + FIXME shells : string, optional - if shells='corr': orthonormalized projectors for correlated shells are used for the downfolding. @@ -343,10 +343,10 @@ class SumkDFT(object): bname : string Block name of the target block of the lattice Green's function. - gf_to_upfold : Gf + gf_to_upfold : Gf Block of the Green's function that is to be upfolded. - gf_inp : Gf - FIXME + gf_inp : Gf + FIXME shells : string, optional - if shells='corr': orthonormalized projectors for correlated shells are used for the upfolding. @@ -391,10 +391,10 @@ class SumkDFT(object): - if shells='corr': ish labels all correlated shells (equivalent or not) - if shells='all': ish labels only representative (inequivalent) non-correlated shells - gf_to_rotate : Gf + gf_to_rotate : Gf Block of the Green's function that is to be rotated. direction : string - The direction of rotation can be either + The direction of rotation can be either - 'toLocal' : global -> local transformation, - 'toGlobal' : local -> global transformation. @@ -444,7 +444,7 @@ class SumkDFT(object): def lattice_gf(self, ik, mu=None, iw_or_w="iw", beta=40, broadening=None, mesh=None, with_Sigma=True, with_dc=True): r""" - Calculates the lattice Green function for a given k-point from the DFT Hamiltonian and the self energy. + Calculates the lattice Green function for a given k-point from the DFT Hamiltonian and the self energy. Parameters ---------- @@ -467,7 +467,7 @@ class SumkDFT(object): Data defining mesh on which the real-axis GF will be calculated, given in the form (om_min,om_max,n_points), where om_min is the minimum omega, om_max is the maximum omega and n_points is the number of points. with_Sigma : boolean, optional - If True the GF will be calculated with the self-energy stored in self.Sigmaimp_(w/iw), for real/Matsubara GF, respectively. + If True the GF will be calculated with the self-energy stored in self.Sigmaimp_(w/iw), for real/Matsubara GF, respectively. In this case the mesh is taken from the self.Sigma_imp object. If with_Sigma=True but self.Sigmaimp_(w/iw) is not present, with_Sigma is reset to False. with_dc : boolean, optional @@ -667,7 +667,7 @@ class SumkDFT(object): return Sigma_out def extract_G_loc(self, mu=None, iw_or_w='iw', with_Sigma=True, with_dc=True, broadening=None, - transform_to_solver_blocks=True, show_warnings=True): + transform_to_solver_blocks=True): r""" Extracts the local downfolded Green function by the Brillouin-zone integration of the lattice Green's function. @@ -686,9 +686,6 @@ class SumkDFT(object): transform_to_solver_blocks : bool, optional If True (default), the returned G_loc will be transformed to the block structure ``gf_struct_solver``, else it will be in ``gf_struct_sumk``. - show_warnings : bool, optional - Displays warning messages during transformation - (Only effective if transform_to_solver_blocks = True Returns ------- @@ -756,11 +753,11 @@ class SumkDFT(object): icrsh, gf, direction='toLocal') if transform_to_solver_blocks: - return self.transform_to_solver_blocks(G_loc, show_warnings=show_warnings) + return self.transform_to_solver_blocks(G_loc) return G_loc - def transform_to_solver_blocks(self, G_loc, G_out=None, show_warnings = True): + def transform_to_solver_blocks(self, G_loc, G_out=None): """ transform G_loc from sumk to solver space Parameters @@ -797,16 +794,15 @@ class SumkDFT(object): ish_from=self.inequiv_to_corr[ish], ish_to=ish, space_from='sumk', - G_out=G_out[ish], - show_warnings = show_warnings) + G_out=G_out[ish]) # return only the inequivalent shells: return G_out def analyse_block_structure(self, threshold=0.00001, include_shells=None, dm=None, hloc=None): r""" - Determines the block structure of local Green's functions by analysing the structure of - the corresponding density matrices and the local Hamiltonian. The resulting block structures + Determines the block structure of local Green's functions by analysing the structure of + the corresponding density matrices and the local Hamiltonian. The resulting block structures for correlated shells are stored in the :class:`SumkDFT.block_structure ` attribute. Parameters @@ -969,7 +965,7 @@ class SumkDFT(object): else: return w-w0 gf = [BlockGf(name_block_generator = [(name, GfReFreq( - window=(-numpy.pi*(len(block.mesh)-1) / (len(block.mesh)*get_delta_from_mesh(block.mesh)), + window=(-numpy.pi*(len(block.mesh)-1) / (len(block.mesh)*get_delta_from_mesh(block.mesh)), numpy.pi*(len(block.mesh)-1) / (len(block.mesh)*get_delta_from_mesh(block.mesh))), n_points=len(block.mesh), indices=block.indices)) for name, block in g_sh], make_copies=False) for g_sh in G] @@ -1348,7 +1344,7 @@ class SumkDFT(object): - if 'using_point_integration': Only works for diagonal hopping matrix (true in wien2k). beta : float, optional - Inverse temperature. + Inverse temperature. Returns ------- @@ -1756,7 +1752,7 @@ class SumkDFT(object): def total_density(self, mu=None, iw_or_w="iw", with_Sigma=True, with_dc=True, broadening=None): r""" - Calculates the total charge within the energy window for a given chemical potential. + Calculates the total charge within the energy window for a given chemical potential. The chemical potential is either given by parameter `mu` or, if it is not specified, taken from `self.chemical_potential`. @@ -1773,7 +1769,7 @@ class SumkDFT(object): with - .. math:: n(k) = Tr G_{\nu\nu'}(k, i\omega_{n}). + .. math:: n(k) = Tr G_{\nu\nu'}(k, i\omega_{n}). The calculation is done in the global coordinate system, if distinction is made between local/global. @@ -2064,7 +2060,7 @@ class SumkDFT(object): return dc def check_projectors(self): - """Calculated the density matrix from projectors (DM = P Pdagger) to check that it is correct and + """Calculated the density matrix from projectors (DM = P Pdagger) to check that it is correct and specifically that it matches DFT.""" dens_mat = [numpy.zeros([self.corr_shells[icrsh]['dim'], self.corr_shells[icrsh]['dim']], numpy.complex_) for icrsh in range(self.n_corr_shells)] From 810b315c92e44a735b893ef0a3a7b4148a023a4a Mon Sep 17 00:00:00 2001 From: Hermann Schnait Date: Tue, 18 Jun 2019 16:53:44 +0200 Subject: [PATCH 29/57] Fixing TransBasis --- python/trans_basis.py | 31 ++++++++++++++++++------------- 1 file changed, 18 insertions(+), 13 deletions(-) diff --git a/python/trans_basis.py b/python/trans_basis.py index f00140d6..7bd2ee4e 100644 --- a/python/trans_basis.py +++ b/python/trans_basis.py @@ -60,6 +60,10 @@ class TransBasis: - 'eal' : local hamiltonian (i.e. crystal field) - 'dm' : local density matrix + calc_in_solver_blocks : bool, optional + Whether the property shall be diagonalized in the + full sumk structure, or just in the solver structure. + Returns ------- wsqr : double @@ -78,26 +82,27 @@ class TransBasis: if calc_in_solver_blocks: trafo = self.SK.block_structure.transformation - self.SK.block_structure.transform = None + self.SK.block_structure.transformation = None + prop_solver = self.SK.block_structure.convert_matrix(prop, space_from='sumk', space_to='solver') - v= [] + v= {} for name in prop_solver: v[name] = numpy.linalg.eigh(prop_solver[name])[1] self.w = self.SK.block_structure.convert_matrix(v, space_from='solver', space_to='sumk')['ud' if self.SK.SO else 'up'] self.T = numpy.dot(self.T.transpose().conjugate(), self.w).conjugate().transpose() - self.SK.block_structure.transform = trafo - - if self.SK.SO == 0: - self.eig, self.w = numpy.linalg.eigh(prop['up']) - # calculate new Transformation matrix - self.T = numpy.dot(self.T.transpose().conjugate(), - self.w).conjugate().transpose() + self.SK.block_structure.transformation = trafo else: - self.eig, self.w = numpy.linalg.eigh(prop['ud']) - # calculate new Transformation matrix - self.T = numpy.dot(self.T.transpose().conjugate(), - self.w).conjugate().transpose() + if self.SK.SO == 0: + self.eig, self.w = numpy.linalg.eigh(prop['up']) + # calculate new Transformation matrix + self.T = numpy.dot(self.T.transpose().conjugate(), + self.w).conjugate().transpose() + else: + self.eig, self.w = numpy.linalg.eigh(prop['ud']) + # calculate new Transformation matrix + self.T = numpy.dot(self.T.transpose().conjugate(), + self.w).conjugate().transpose() # measure for the 'unity' of the transformation: wsqr = sum(abs(self.w.diagonal())**2) / self.w.diagonal().size From f695ccac7a384ababd1c2f16dc30d515f1431175 Mon Sep 17 00:00:00 2001 From: Hermann Schnait Date: Mon, 24 Jun 2019 10:03:43 +0200 Subject: [PATCH 30/57] Ignore imaginary part of the density when calculating mu --- python/sumk_dft.py | 58 +++++++++++++++++++++++++--------------------- 1 file changed, 32 insertions(+), 26 deletions(-) diff --git a/python/sumk_dft.py b/python/sumk_dft.py index 8da2751e..38b8195c 100644 --- a/python/sumk_dft.py +++ b/python/sumk_dft.py @@ -52,11 +52,11 @@ class SumkDFT(object): hdf_file : string Name of hdf5 containing the data. h_field : scalar, optional - The value of magnetic field to add to the DFT Hamiltonian. + The value of magnetic field to add to the DFT Hamiltonian. The contribution -h_field*sigma is added to diagonal elements of the Hamiltonian. It cannot be used with the spin-orbit coupling on; namely h_field is set to 0 if self.SO=True. use_dft_blocks : boolean, optional - If True, the local Green's function matrix for each spin is divided into smaller blocks + If True, the local Green's function matrix for each spin is divided into smaller blocks with the block structure determined from the DFT density matrix of the corresponding correlated shell. Alternatively and additionally, the block structure can be analysed using :meth:`analyse_block_structure ` @@ -64,7 +64,7 @@ class SumkDFT(object): dft_data : string, optional Name of hdf5 subgroup in which DFT data for projector and lattice Green's function construction are stored. symmcorr_data : string, optional - Name of hdf5 subgroup in which DFT data on symmetries of correlated shells + Name of hdf5 subgroup in which DFT data on symmetries of correlated shells (symmetry operations, permutaion matrices etc.) are stored. parproj_data : string, optional Name of hdf5 subgroup in which DFT data on non-normalized projectors for non-correlated @@ -291,10 +291,10 @@ class SumkDFT(object): bname : string Block name of the target block of the lattice Green's function. - gf_to_downfold : Gf + gf_to_downfold : Gf Block of the Green's function that is to be downfolded. - gf_inp : Gf - FIXME + gf_inp : Gf + FIXME shells : string, optional - if shells='corr': orthonormalized projectors for correlated shells are used for the downfolding. @@ -343,10 +343,10 @@ class SumkDFT(object): bname : string Block name of the target block of the lattice Green's function. - gf_to_upfold : Gf + gf_to_upfold : Gf Block of the Green's function that is to be upfolded. - gf_inp : Gf - FIXME + gf_inp : Gf + FIXME shells : string, optional - if shells='corr': orthonormalized projectors for correlated shells are used for the upfolding. @@ -391,10 +391,10 @@ class SumkDFT(object): - if shells='corr': ish labels all correlated shells (equivalent or not) - if shells='all': ish labels only representative (inequivalent) non-correlated shells - gf_to_rotate : Gf + gf_to_rotate : Gf Block of the Green's function that is to be rotated. direction : string - The direction of rotation can be either + The direction of rotation can be either - 'toLocal' : global -> local transformation, - 'toGlobal' : local -> global transformation. @@ -444,7 +444,7 @@ class SumkDFT(object): def lattice_gf(self, ik, mu=None, iw_or_w="iw", beta=40, broadening=None, mesh=None, with_Sigma=True, with_dc=True): r""" - Calculates the lattice Green function for a given k-point from the DFT Hamiltonian and the self energy. + Calculates the lattice Green function for a given k-point from the DFT Hamiltonian and the self energy. Parameters ---------- @@ -467,7 +467,7 @@ class SumkDFT(object): Data defining mesh on which the real-axis GF will be calculated, given in the form (om_min,om_max,n_points), where om_min is the minimum omega, om_max is the maximum omega and n_points is the number of points. with_Sigma : boolean, optional - If True the GF will be calculated with the self-energy stored in self.Sigmaimp_(w/iw), for real/Matsubara GF, respectively. + If True the GF will be calculated with the self-energy stored in self.Sigmaimp_(w/iw), for real/Matsubara GF, respectively. In this case the mesh is taken from the self.Sigma_imp object. If with_Sigma=True but self.Sigmaimp_(w/iw) is not present, with_Sigma is reset to False. with_dc : boolean, optional @@ -667,7 +667,7 @@ class SumkDFT(object): return Sigma_out def extract_G_loc(self, mu=None, iw_or_w='iw', with_Sigma=True, with_dc=True, broadening=None, - transform_to_solver_blocks=True): + transform_to_solver_blocks=True, show_warnings=True): r""" Extracts the local downfolded Green function by the Brillouin-zone integration of the lattice Green's function. @@ -686,6 +686,9 @@ class SumkDFT(object): transform_to_solver_blocks : bool, optional If True (default), the returned G_loc will be transformed to the block structure ``gf_struct_solver``, else it will be in ``gf_struct_sumk``. + show_warnings : bool, optional + Displays warning messages during transformation + (Only effective if transform_to_solver_blocks = True Returns ------- @@ -753,11 +756,11 @@ class SumkDFT(object): icrsh, gf, direction='toLocal') if transform_to_solver_blocks: - return self.transform_to_solver_blocks(G_loc) + return self.transform_to_solver_blocks(G_loc, show_warnings=show_warnings) return G_loc - def transform_to_solver_blocks(self, G_loc, G_out=None): + def transform_to_solver_blocks(self, G_loc, G_out=None, show_warnings = True): """ transform G_loc from sumk to solver space Parameters @@ -794,15 +797,16 @@ class SumkDFT(object): ish_from=self.inequiv_to_corr[ish], ish_to=ish, space_from='sumk', - G_out=G_out[ish]) + G_out=G_out[ish], + show_warnings = show_warnings) # return only the inequivalent shells: return G_out def analyse_block_structure(self, threshold=0.00001, include_shells=None, dm=None, hloc=None): r""" - Determines the block structure of local Green's functions by analysing the structure of - the corresponding density matrices and the local Hamiltonian. The resulting block structures + Determines the block structure of local Green's functions by analysing the structure of + the corresponding density matrices and the local Hamiltonian. The resulting block structures for correlated shells are stored in the :class:`SumkDFT.block_structure ` attribute. Parameters @@ -965,7 +969,7 @@ class SumkDFT(object): else: return w-w0 gf = [BlockGf(name_block_generator = [(name, GfReFreq( - window=(-numpy.pi*(len(block.mesh)-1) / (len(block.mesh)*get_delta_from_mesh(block.mesh)), + window=(-numpy.pi*(len(block.mesh)-1) / (len(block.mesh)*get_delta_from_mesh(block.mesh)), numpy.pi*(len(block.mesh)-1) / (len(block.mesh)*get_delta_from_mesh(block.mesh))), n_points=len(block.mesh), indices=block.indices)) for name, block in g_sh], make_copies=False) for g_sh in G] @@ -1344,7 +1348,7 @@ class SumkDFT(object): - if 'using_point_integration': Only works for diagonal hopping matrix (true in wien2k). beta : float, optional - Inverse temperature. + Inverse temperature. Returns ------- @@ -1752,7 +1756,7 @@ class SumkDFT(object): def total_density(self, mu=None, iw_or_w="iw", with_Sigma=True, with_dc=True, broadening=None): r""" - Calculates the total charge within the energy window for a given chemical potential. + Calculates the total charge within the energy window for a given chemical potential. The chemical potential is either given by parameter `mu` or, if it is not specified, taken from `self.chemical_potential`. @@ -1769,7 +1773,7 @@ class SumkDFT(object): with - .. math:: n(k) = Tr G_{\nu\nu'}(k, i\omega_{n}). + .. math:: n(k) = Tr G_{\nu\nu'}(k, i\omega_{n}). The calculation is done in the global coordinate system, if distinction is made between local/global. @@ -1808,8 +1812,10 @@ class SumkDFT(object): # collect data from mpi: dens = mpi.all_reduce(mpi.world, dens, lambda x, y: x + y) mpi.barrier() - - return dens + import numpy as np + if np.abs(np.imag(dens)) > 1e-20: + mpi.report("Warning: Imaginary part in density will be ignored ({})".format(str(np.abs(np.imag(dens))))) + return np.real(dens) def set_mu(self, mu): r""" @@ -2060,7 +2066,7 @@ class SumkDFT(object): return dc def check_projectors(self): - """Calculated the density matrix from projectors (DM = P Pdagger) to check that it is correct and + """Calculated the density matrix from projectors (DM = P Pdagger) to check that it is correct and specifically that it matches DFT.""" dens_mat = [numpy.zeros([self.corr_shells[icrsh]['dim'], self.corr_shells[icrsh]['dim']], numpy.complex_) for icrsh in range(self.n_corr_shells)] From bd228de7689ff1f3f321f57d3576946d001c13af Mon Sep 17 00:00:00 2001 From: Hermann Schnait Date: Mon, 24 Jun 2019 10:15:09 +0200 Subject: [PATCH 31/57] Add adapt_deg_shells method and call it in map_gf_struct --- python/block_structure.py | 50 ++++++++++++++++++++++++--------------- 1 file changed, 31 insertions(+), 19 deletions(-) diff --git a/python/block_structure.py b/python/block_structure.py index 3062956f..79394657 100644 --- a/python/block_structure.py +++ b/python/block_structure.py @@ -437,30 +437,39 @@ class BlockStructure(object): else: self.sumk_to_solver[ish][k] = (None, None) # adapt deg_shells - if self.deg_shells is not None: - for degsh in self.deg_shells[ish]: - if isinstance(degsh, dict): - for key in degsh.keys(): - if not key in gf_struct: - del degsh[key] - continue - if gf_struct[key] != self.gf_struct_solver[ish][key]: - v, C = degsh[key] - degsh[key][0] = \ - v[gf_struct[key], :][:, gf_struct[key]] - warn( - 'Removing shells from degenerate shell {}. Cannot guarantee that they continue to be equivalent.') - else: # degshell is list - degsh1 = copy.deepcopy(degsh) # in order to not remove a key while iterating - for key in degsh1: - if not key in gf_struct: - warn('Removing shells from degenerate shell {}.') - degsh.remove(key) + + self.adapt_deg_shells(gf_struct, ish) + + # reindexing gf_struct so that it starts with 0 for k in gf_struct: gf_struct[k] = range(len(gf_struct[k])) self.gf_struct_solver[ish] = gf_struct + def adapt_deg_shells(gf_struct, ish=0): + """ Adapts the deg_shells to a new gf_struct + Internally called when using pick_gf_struct and map_gf_struct + """ + if self.deg_shells is not None: + for degsh in self.deg_shells[ish]: + if isinstance(degsh, dict): + for key in degsh.keys(): + if not key in gf_struct: + del degsh[key] + continue + if gf_struct[key] != self.gf_struct_solver[ish][key]: + v, C = degsh[key] + degsh[key][0] = \ + v[gf_struct[key], :][:, gf_struct[key]] + warn( + 'Removing shells from degenerate shell {}. Cannot guarantee that they continue to be equivalent.') + else: # degshell is list + degsh1 = copy.deepcopy(degsh) # in order to not remove a key while iterating + for key in degsh1: + if not key in gf_struct: + warn('Removing shells from degenerate shell {}.') + degsh.remove(key) + def pick_gf_struct_sumk(self, new_gf_struct): """ Pick selected orbitals within blocks. @@ -588,6 +597,9 @@ class BlockStructure(object): for k in self.sumk_to_solver[ish].keys(): if not k in su2so: su2so[k] = (None, None) + + adapt_deg_shells(gf_struct, ish) + self.gf_struct_solver[ish] = gf_struct self.solver_to_sumk[ish] = so2su self.sumk_to_solver[ish] = su2so From 9bc4643fdf9fc5e2fe99dc7784eeef3119ac5e7f Mon Sep 17 00:00:00 2001 From: Hermann Schnait Date: Mon, 24 Jun 2019 12:33:22 +0200 Subject: [PATCH 32/57] Update unit tests and bugfixes in BlockStructure --- python/block_structure.py | 12 ++++++------ python/sumk_dft.py | 4 ++-- test/analyse_block_structure_from_gf.py | 7 +++---- 3 files changed, 11 insertions(+), 12 deletions(-) diff --git a/python/block_structure.py b/python/block_structure.py index 79394657..fca33d5d 100644 --- a/python/block_structure.py +++ b/python/block_structure.py @@ -446,7 +446,7 @@ class BlockStructure(object): gf_struct[k] = range(len(gf_struct[k])) self.gf_struct_solver[ish] = gf_struct - def adapt_deg_shells(gf_struct, ish=0): + def adapt_deg_shells(self, gf_struct, ish=0): """ Adapts the deg_shells to a new gf_struct Internally called when using pick_gf_struct and map_gf_struct """ @@ -598,7 +598,7 @@ class BlockStructure(object): if not k in su2so: su2so[k] = (None, None) - adapt_deg_shells(gf_struct, ish) + self.adapt_deg_shells(gf_struct, ish) self.gf_struct_solver[ish] = gf_struct self.solver_to_sumk[ish] = so2su @@ -816,7 +816,6 @@ class BlockStructure(object): 'The parameter ish in convert_gf is deprecated. Use ish_from and ish_to instead.') ish_from = 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) @@ -866,7 +865,6 @@ class BlockStructure(object): 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: ish_to = ish_from @@ -955,8 +953,10 @@ class BlockStructure(object): else: maxdiff = G_back[name] - G[name] - if space_to == 'solver': # do comparison in solver (ignore diff. in ignored orbitals) - maxdiff = G_struct._convert_gf_or_matrix({'ud':maxdiff}, self, ish_from=ish_from, + if space_to == 'solver' and self == G_struct: # do comparison in solver (ignore diff. in ignored orbitals) + tmp = self.create_matrix(space='sumk') + tmp[name] = maxdiff + maxdiff = G_struct._convert_gf_or_matrix(tmp, self, ish_from=ish_from, ish_to=ish_to, show_warnings=False, space_from=space_from, space_to=space_to, **kwargs) diff --git a/python/sumk_dft.py b/python/sumk_dft.py index 38b8195c..40c3e1b5 100644 --- a/python/sumk_dft.py +++ b/python/sumk_dft.py @@ -1090,9 +1090,9 @@ class SumkDFT(object): G_transformed = [ self.block_structure.convert_gf(G[ish], full_structure, ish, mesh=G[ish].mesh.copy(), show_warnings=threshold, - gf_function=type(G[ish]._first())) + gf_function=type(G[ish]._first()), space_from='sumk', space_to='solver') for ish in range(self.n_inequiv_shells)] - + #print 'c' if analyse_deg_shells: self.analyse_deg_shells(G_transformed, threshold, include_shells) return G_transformed diff --git a/test/analyse_block_structure_from_gf.py b/test/analyse_block_structure_from_gf.py index 5a831444..442a7fff 100644 --- a/test/analyse_block_structure_from_gf.py +++ b/test/analyse_block_structure_from_gf.py @@ -26,7 +26,6 @@ G = SK.extract_G_loc() # the original block structure block_structure1 = SK.block_structure.copy() - G_new = SK.analyse_block_structure_from_gf(G) # the new block structure @@ -163,9 +162,9 @@ for conjugate in conjugate_values: G_new = SK.analyse_block_structure_from_gf(G, 1.e-7) # transform G_noisy etc. to the new block structure - G_noisy = SK.block_structure.convert_gf(G_noisy, block_structure1, beta = G_noisy.mesh.beta) - G_pre_transform = SK.block_structure.convert_gf(G_pre_transform, block_structure1, beta = G_noisy.mesh.beta) - G_noisy_pre_transform = SK.block_structure.convert_gf(G_noisy_pre_transform, block_structure1, beta = G_noisy.mesh.beta) + G_noisy = SK.block_structure.convert_gf(G_noisy, block_structure1, beta = G_noisy.mesh.beta, space_from='sumk') + G_pre_transform = SK.block_structure.convert_gf(G_pre_transform, block_structure1, beta = G_noisy.mesh.beta, space_from='sumk') + G_noisy_pre_transform = SK.block_structure.convert_gf(G_noisy_pre_transform, block_structure1, beta = G_noisy.mesh.beta, space_from='sumk') assert len(SK.deg_shells[0]) == 2, "wrong number of equivalent groups found" assert sorted([len(d) for d in SK.deg_shells[0]]) == [2,3], "wrong number of members in the equivalent groups found" From 8016152c5eca658d789904ac79a363a35cdfeb13 Mon Sep 17 00:00:00 2001 From: Hermann Schnait Date: Thu, 27 Jun 2019 12:12:33 +0200 Subject: [PATCH 33/57] Documentation for basis rotations --- doc/documentation.rst | 8 ++++ doc/guide/BasisRotation.rst | 76 +++++++++++++++++++++++++++++++++++++ 2 files changed, 84 insertions(+) create mode 100644 doc/guide/BasisRotation.rst diff --git a/doc/documentation.rst b/doc/documentation.rst index 45f071d6..d40b1dd6 100644 --- a/doc/documentation.rst +++ b/doc/documentation.rst @@ -27,6 +27,14 @@ User guide guide/SrVO3 guide/dftdmft_selfcons guide/Sr2RuO4 + guide/BasisRotation + +Postprocessing +-------------- + +.. toctree:: + :maxdepth: 2 + guide/analysis guide/full_tutorial guide/transport diff --git a/doc/guide/BasisRotation.rst b/doc/guide/BasisRotation.rst new file mode 100644 index 00000000..dda0a573 --- /dev/null +++ b/doc/guide/BasisRotation.rst @@ -0,0 +1,76 @@ +.. _plovasp: + +Numerical Treatment of the Sign-Problem: Basis Rotations +======= + +When performing calculations with off-diagonal complex hybridisation or local Hamiltonian, one is +often limited by the fermionic sign-problem. However, as the sign is no +physical observable, one can try to improve the calculation by rotating +to another basis. + +While the choice of basis to perform the calculation in can be chosen +arbitrarily, two choices which have shown good results are the basis +which diagonalizes the local Hamiltonian or the density matrix of then +system. + +The transformation matrix can be stored in the :class:`BlockStructure` and the +transformation is automatically performed when using :class:`SumkDFT`'s :meth:`extract_G_loc` +and :meth:`put_Sigma` (see below). + + +Finding the Transformation Matrix +----------------- + +The :class:`TransBasis` class offers a simple mehod to calculate the transformation +matrices to a basis where either the local Hamiltonian or the density matrix +is diagonal:: + + from triqs_dft_tools.trans_basis import TransBasis + TB = TransBasis(SK) + TB.calculate_diagonalisation_matrix(prop_to_be_diagonal='eal', calc_in_solver_blocks = True) + + SK.block_structure.transformation = [{'ud':TB.w}] + + + +Transforming Green's functions manually +----------------- + +One can transform Green's functions manually using the :meth:`convert_gf` method:: + + # Rotate a Green's function from solver-space to sumk-space + new_gf = block_structure.convert_gf(old_gf, space_from='solver', space_to='sumk') + + + +Automatic transformation during the DMFT loop +----------------- + +During a DMFT loop one is switching back and forth between Sumk-Space and Solver-Space +in each iteration. Once the block_structure.transformation property is set, this can be +done automatically:: + + for it in range(iteration_offset, iteration_offset + n_iterations): + # every GF is in solver space here + S.G0_iw << inverse(S.Sigma_iw + inverse(S.G_iw)) + + # solve the impurity in solver space -> hopefully better sign + S.solve(h_int = H, **p) + + # calc_dc(..., transform = True) by default + SK.calc_dc(S.G_iw.density(), U_interact=U, J_hund=J, orb=0, use_dc_formula=DC_type) + + # put_Sigma(..., transform_to_sumk_blocks = True) by default + SK.put_Sigma([S.Sigma_iw]) + + SK.calc_mu() + + # extract_G_loc(..., transform_to_solver_blocks = True) by default + S.G_iw << SK.extract_G_loc()[0] + +.. warning:: + One must not forget to also transform the interaction Hamiltonian to the diagonal basis! + This can be done with the :meth:`transform_U_matrix` method. However, due to different + conventions in this method, one must pass the conjugated version of the transformation matrix:: + + U_trans = transform_U_matrix(U, SK.block_structure.transformation[0]['ud'].conjugate()) From e40f3159896e2b5fedfb4e18e4e16ed751dd297b Mon Sep 17 00:00:00 2001 From: Hermann Schnait Date: Wed, 10 Jul 2019 17:15:48 +0200 Subject: [PATCH 34/57] Implement calculate_diagonalization_matrix method into SK --- python/sumk_dft.py | 74 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 74 insertions(+) diff --git a/python/sumk_dft.py b/python/sumk_dft.py index 40c3e1b5..69d95640 100644 --- a/python/sumk_dft.py +++ b/python/sumk_dft.py @@ -1333,7 +1333,81 @@ class SumkDFT(object): # a block was found, break out of the loop break + + def calculate_diagonalization_matrix(self, prop_to_be_diagonal='eal', calc_in_solver_blocks=False, write_to_blockstructure = True, ish=0): + """ + Calculates the diagonalisation matrix, and (optionally) stores it in the BlockStructure. + Parameters + ---------- + prop_to_be_diagonal : string, optional + Defines the property to be diagonalized. + + - 'eal' : local hamiltonian (i.e. crystal field) + - 'dm' : local density matrix + + calc_in_solver_blocks : bool, optional + Whether the property shall be diagonalized in the + full sumk structure, or just in the solver structure. + + write_to_blockstructure : bool, optional + Whether the diagonalization matrix shall be written to + the BlockStructure directly. + ish : int, optional + Number of the correlated shell to be diagonalized. + + Returns + ------- + trafo : dict + The transformation matrix for each spin-block in the correlated shell + + """ + trafo = {} + + + if prop_to_be_diagonal == 'eal': + prop = self.eff_atomic_levels()[ish] + elif prop_to_be_diagonal == 'dm': + prop = self.density_matrix(method='using_point_integration')[ish] + else: + mpi.report( + "calculate_diagonalization_matrix: not a valid quantitiy to be diagonal. Choices are 'eal' or 'dm'.") + return 0 + + if calc_in_solver_blocks: + trafo_tmp = self.block_structure.transformation + self.block_structure.transformation = None + + prop_solver = self.block_structure.convert_matrix(prop, space_from='sumk', space_to='solver') + t= {} + for name in prop_solver: + t[name] = numpy.linalg.eigh(prop_solver[name])[1].conjugate().transpose() + trafo = self.block_structure.convert_matrix(t, space_from='solver', space_to='sumk') + #self.T = numpy.dot(self.T.transpose().conjugate(), + # self.w).conjugate().transpose() + self.block_structure.transformation = trafo_tmp + else: + for name in prop: + t = numpy.linalg.eigh(prop[name])[1].conjugate().transpose() + trafo[name] = t + # calculate new Transformation matrix + #self.T = numpy.dot(self.T.transpose().conjugate(), + # self.w).conjugate().transpose() + + # measure for the 'unity' of the transformation: + #wsqr = sum(abs(self.w.diagonal())**2) / self.w.diagonal().size + #return wsqr + + if write_to_blockstructure: + if self.block_structure.transformation == None: + self.block_structure.transformation = [{} for icrsh in range(self.n_corr_shells)] + for sp in self.spin_block_names[self.corr_shells[icrsh]['SO']]: + self.block_structure.transformation[icrsh][sp] = numpy.eye(self.corr_shells[icrsh]['dim'], self.corr_shells[icrsh]['dim'], numpy.complex_) + + self.block_structure.transformation[ish] = trafo + + return trafo + def density_matrix(self, method='using_gf', beta=40.0): """Calculate density matrices in one of two ways. From e7cddf3e7e320ab855c2c1d946ab7393ed289391 Mon Sep 17 00:00:00 2001 From: Hermann Schnait Date: Thu, 18 Jul 2019 11:59:50 +0200 Subject: [PATCH 35/57] Bugfix in calculate_diagonalization_matrix for more than one deg shell --- python/block_structure.py | 1 - python/sumk_dft.py | 6 ++++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/python/block_structure.py b/python/block_structure.py index fca33d5d..5739482c 100644 --- a/python/block_structure.py +++ b/python/block_structure.py @@ -726,7 +726,6 @@ class BlockStructure(object): return self._check_gf_or_matrix(G, ish, space) def _check_gf_or_matrix(self, G, ish=None, space='solver'): - if space == 'solver': gf_struct = self.gf_struct_solver elif space == 'sumk': diff --git a/python/sumk_dft.py b/python/sumk_dft.py index 69d95640..7408cce2 100644 --- a/python/sumk_dft.py +++ b/python/sumk_dft.py @@ -1401,8 +1401,10 @@ class SumkDFT(object): if write_to_blockstructure: if self.block_structure.transformation == None: self.block_structure.transformation = [{} for icrsh in range(self.n_corr_shells)] - for sp in self.spin_block_names[self.corr_shells[icrsh]['SO']]: - self.block_structure.transformation[icrsh][sp] = numpy.eye(self.corr_shells[icrsh]['dim'], self.corr_shells[icrsh]['dim'], numpy.complex_) + for icrsh in range(self. n_corr_shells): + for sp in self.spin_block_names[self.corr_shells[icrsh]['SO']]: + self.block_structure.transformation[icrsh][sp] = numpy.eye(self.corr_shells[icrsh]['dim'], dtype=numpy.complex_) + self.block_structure.transformation[ish] = trafo From 46d9229722907e0ce08a293cdb7b846235a566c4 Mon Sep 17 00:00:00 2001 From: Manuel Date: Mon, 12 Aug 2019 16:28:49 -0400 Subject: [PATCH 36/57] Beautify check density imag part --- python/sumk_dft.py | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/python/sumk_dft.py b/python/sumk_dft.py index 64ee0af9..ef7f7dd8 100644 --- a/python/sumk_dft.py +++ b/python/sumk_dft.py @@ -1345,7 +1345,7 @@ class SumkDFT(object): calc_in_solver_blocks : bool, optional Whether the property shall be diagonalized in the full sumk structure, or just in the solver structure. - + write_to_blockstructure : bool, optional Whether the diagonalization matrix shall be written to the BlockStructure directly. @@ -1359,8 +1359,8 @@ class SumkDFT(object): """ trafo = {} - - + + if prop_to_be_diagonal == 'eal': prop = self.eff_atomic_levels()[ish] elif prop_to_be_diagonal == 'dm': @@ -1393,7 +1393,7 @@ class SumkDFT(object): # measure for the 'unity' of the transformation: #wsqr = sum(abs(self.w.diagonal())**2) / self.w.diagonal().size #return wsqr - + if write_to_blockstructure: if self.block_structure.transformation == None: self.block_structure.transformation = [{} for icrsh in range(self.n_corr_shells)] @@ -1401,11 +1401,11 @@ class SumkDFT(object): for sp in self.spin_block_names[self.corr_shells[icrsh]['SO']]: self.block_structure.transformation[icrsh][sp] = numpy.eye(self.corr_shells[icrsh]['dim'], dtype=numpy.complex_) - + self.block_structure.transformation[ish] = trafo - + return trafo - + def density_matrix(self, method='using_gf', beta=40.0): """Calculate density matrices in one of two ways. @@ -1884,10 +1884,10 @@ class SumkDFT(object): # collect data from mpi: dens = mpi.all_reduce(mpi.world, dens, lambda x, y: x + y) mpi.barrier() - import numpy as np - if np.abs(np.imag(dens)) > 1e-20: - mpi.report("Warning: Imaginary part in density will be ignored ({})".format(str(np.abs(np.imag(dens))))) - return np.real(dens) + + if abs(dens.imag) > 1e-20: + mpi.report("Warning: Imaginary part in density will be ignored ({})".format(str(abs(dens.imag)))) + return dens.real def set_mu(self, mu): r""" From 796e05ea646b392955ec14e0c61c93b344dde1ab Mon Sep 17 00:00:00 2001 From: Manuel Date: Mon, 12 Aug 2019 19:23:27 -0400 Subject: [PATCH 37/57] Rewrite calculate_diagonalization_matrix --- python/block_structure.py | 2 +- python/sumk_dft.py | 81 ++++++++++++++++++--------------------- 2 files changed, 39 insertions(+), 44 deletions(-) diff --git a/python/block_structure.py b/python/block_structure.py index 5739482c..4b40a69a 100644 --- a/python/block_structure.py +++ b/python/block_structure.py @@ -90,7 +90,7 @@ class BlockStructure(object): inequivalent correlated shell is given transformation : list of numpy.array or list of dict a list with entries for each ``ish`` giving transformation matrices - that are used on the Green's function in ``sumk`` space when before + that are used on the Green's function in ``sumk`` space before converting to the ``solver`` space Up to the change in block structure, diff --git a/python/sumk_dft.py b/python/sumk_dft.py index ef7f7dd8..bdbccddd 100644 --- a/python/sumk_dft.py +++ b/python/sumk_dft.py @@ -1330,7 +1330,7 @@ class SumkDFT(object): # a block was found, break out of the loop break - def calculate_diagonalization_matrix(self, prop_to_be_diagonal='eal', calc_in_solver_blocks=False, write_to_blockstructure = True, ish=0): + def calculate_diagonalization_matrix(self, prop_to_be_diagonal='eal', calc_in_solver_blocks=False, write_to_blockstructure = True, shells=None): """ Calculates the diagonalisation matrix, and (optionally) stores it in the BlockStructure. @@ -1349,62 +1349,57 @@ class SumkDFT(object): write_to_blockstructure : bool, optional Whether the diagonalization matrix shall be written to the BlockStructure directly. - ish : int, optional - Number of the correlated shell to be diagonalized. + shells : list of int, optional + Indices of correlated shells to be diagonalized. + None: all shells Returns ------- trafo : dict The transformation matrix for each spin-block in the correlated shell - """ - trafo = {} - - if prop_to_be_diagonal == 'eal': - prop = self.eff_atomic_levels()[ish] - elif prop_to_be_diagonal == 'dm': - prop = self.density_matrix(method='using_point_integration')[ish] - else: - mpi.report( - "calculate_diagonalization_matrix: not a valid quantitiy to be diagonal. Choices are 'eal' or 'dm'.") + # Use all shells + if shells is None: + shells = range(self.n_corr_shells) + elif max(shells) >= self.n_corr_shells: # Check if the shell indices are present + mpi.report("calculate_diagonalization_matrix: shells not correct.") return 0 - if calc_in_solver_blocks: - trafo_tmp = self.block_structure.transformation - self.block_structure.transformation = None - - prop_solver = self.block_structure.convert_matrix(prop, space_from='sumk', space_to='solver') - t= {} - for name in prop_solver: - t[name] = numpy.linalg.eigh(prop_solver[name])[1].conjugate().transpose() - trafo = self.block_structure.convert_matrix(t, space_from='solver', space_to='sumk') - #self.T = numpy.dot(self.T.transpose().conjugate(), - # self.w).conjugate().transpose() - self.block_structure.transformation = trafo_tmp + if prop_to_be_diagonal == 'eal': + prop = [self.eff_atomic_levels()[self.corr_to_inequiv[ish]] + for ish in range(self.n_corr_shells)] + elif prop_to_be_diagonal == 'dm': + prop = self.density_matrix(method='using_point_integration') else: - for name in prop: - t = numpy.linalg.eigh(prop[name])[1].conjugate().transpose() - trafo[name] = t - # calculate new Transformation matrix - #self.T = numpy.dot(self.T.transpose().conjugate(), - # self.w).conjugate().transpose() + mpi.report( + "calculate_diagonalization_matrix: Choices for prop_to_be_diagonal are 'eal' or 'dm'.") + return 0 - # measure for the 'unity' of the transformation: - #wsqr = sum(abs(self.w.diagonal())**2) / self.w.diagonal().size - #return wsqr + trans = [{block: numpy.eye(len(indices)) for block, indices in gfs} for gfs in self.gf_struct_sumk] + + for ish in shells: + trafo = {} + # Transform to solver basis if desired, blocks of prop change in this step! + if calc_in_solver_blocks: + prop[ish] = self.block_structure.convert_matrix(prop[ish], space_from='sumk', space_to='solver') + # Get diagonalisation matrix, if not already diagonal + for name in prop[ish]: + if abs(numpy.sum(prop[ish][name]-numpy.diag(numpy.diagonal(prop[ish][name])))) > 1e-13: + trafo[name] = numpy.linalg.eigh(prop[ish][name])[1].conj().T + else: + trafo[name] = numpy.identity(numpy.shape(prop[ish][name])[0]) + # Transform back to sumk if necessay, blocks change in this step! + if calc_in_solver_blocks: + trafo = self.block_structure.convert_matrix(trafo, space_from='solver', space_to='sumk') + trans[ish] = trafo + + # Write to block_structure object if write_to_blockstructure: - if self.block_structure.transformation == None: - self.block_structure.transformation = [{} for icrsh in range(self.n_corr_shells)] - for icrsh in range(self. n_corr_shells): - for sp in self.spin_block_names[self.corr_shells[icrsh]['SO']]: - self.block_structure.transformation[icrsh][sp] = numpy.eye(self.corr_shells[icrsh]['dim'], dtype=numpy.complex_) + self.block_structure.transformation = trans - - self.block_structure.transformation[ish] = trafo - - return trafo + return trans def density_matrix(self, method='using_gf', beta=40.0): From 35584a841c141f0a05b6ea8e34459b7912453ab3 Mon Sep 17 00:00:00 2001 From: Manuel Date: Thu, 15 Aug 2019 20:18:40 -0400 Subject: [PATCH 38/57] Add test for calculate_diagonalization_matrix --- python/sumk_dft.py | 7 +++- test/CMakeLists.txt | 2 +- test/basis_transformation.py | 70 ++++++++++++++++++++++++++++++++++++ 3 files changed, 77 insertions(+), 2 deletions(-) create mode 100644 test/basis_transformation.py diff --git a/python/sumk_dft.py b/python/sumk_dft.py index bdbccddd..fa78e00e 100644 --- a/python/sumk_dft.py +++ b/python/sumk_dft.py @@ -1088,7 +1088,7 @@ class SumkDFT(object): full_structure, ish, mesh=G[ish].mesh.copy(), show_warnings=threshold, gf_function=type(G[ish]._first()), space_from='sumk', space_to='solver') for ish in range(self.n_inequiv_shells)] - #print 'c' + if analyse_deg_shells: self.analyse_deg_shells(G_transformed, threshold, include_shells) return G_transformed @@ -1359,6 +1359,11 @@ class SumkDFT(object): The transformation matrix for each spin-block in the correlated shell """ + if self.block_structure.transformation: + mpi.report( + "calculate_diagonalization_matrix: requires block_structure.transformation = None.") + return 0 + # Use all shells if shells is None: shells = range(self.n_corr_shells) diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 758ea139..fd3de192 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -5,7 +5,7 @@ file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/${all_h5_files} DESTINATION ${CMAKE_CURREN FILE(COPY SrVO3.pmat SrVO3.struct SrVO3.outputs SrVO3.oubwin SrVO3.ctqmcout SrVO3.symqmc SrVO3.sympar SrVO3.parproj SrIrO3_rot.h5 hk_convert_hamiltonian.hk LaVO3-Pnma_hr.dat LaVO3-Pnma.inp DESTINATION ${CMAKE_CURRENT_BINARY_DIR}) # List all tests -set(all_tests wien2k_convert hk_convert w90_convert sumkdft_basic srvo3_Gloc srvo3_transp sigma_from_file blockstructure analyse_block_structure_from_gf analyse_block_structure_from_gf2) +set(all_tests wien2k_convert hk_convert w90_convert sumkdft_basic srvo3_Gloc srvo3_transp sigma_from_file blockstructure analyse_block_structure_from_gf analyse_block_structure_from_gf2 basis_transformation) set(python_executable python) diff --git a/test/basis_transformation.py b/test/basis_transformation.py new file mode 100644 index 00000000..dd0ddd46 --- /dev/null +++ b/test/basis_transformation.py @@ -0,0 +1,70 @@ +from pytriqs.utility.comparison_tests import * +from triqs_dft_tools.sumk_dft import * +import numpy as np + +def is_diagonal_matrix(M): + return abs(np.sum(M-np.diag(np.diagonal(M)))) < 1e-10 + +def call_diagonalize(SK): + SK.block_structure.transformation = None + t_sumk_eal = SK.calculate_diagonalization_matrix(prop_to_be_diagonal='eal', calc_in_solver_blocks=False, write_to_blockstructure = True) + SK.block_structure.transformation = None + t_solver_eal = SK.calculate_diagonalization_matrix(prop_to_be_diagonal='eal', calc_in_solver_blocks=True, write_to_blockstructure = True) + SK.block_structure.transformation = None + t_solver_dm = SK.calculate_diagonalization_matrix(prop_to_be_diagonal='dm', calc_in_solver_blocks=False, write_to_blockstructure = True) + SK.block_structure.transformation = None + t_sumk_dm = SK.calculate_diagonalization_matrix(prop_to_be_diagonal='dm', calc_in_solver_blocks=True, write_to_blockstructure = True) + SK.block_structure.transformation = None + return t_sumk_eal, t_solver_eal, t_sumk_dm, t_solver_dm + +SK = SumkDFT(hdf_file = 'SrVO3.h5', use_dft_blocks=True) + +# only eal and dm are allowed +SK.block_structure.transformation = None +assert not SK.calculate_diagonalization_matrix(prop_to_be_diagonal='test') + +# check for shell index +assert not SK.calculate_diagonalization_matrix(shells = [15]) + +# calling the function twice leads to block_structure.transformation already being set +SK.calculate_diagonalization_matrix() +assert not SK.calculate_diagonalization_matrix() +SK.block_structure.transformation = None + +# Check writing to block_structure +SK.calculate_diagonalization_matrix(write_to_blockstructure=False) +assert SK.block_structure.transformation is None +SK.block_structure.transformation = None +SK.calculate_diagonalization_matrix(write_to_blockstructure=True) +assert SK.block_structure.transformation is not None +SK.block_structure.transformation = None + +t_sumk_eal, t_solver_eal, t_sumk_dm, t_solver_dm = call_diagonalize(SK) + +# All matrices should be identities +for orb in range(SK.n_corr_shells): + for block in t_solver_eal[orb]: + assert_arrays_are_close(t_sumk_eal[orb][block],np.identity(3), precision=1e-6) + assert_arrays_are_close(t_sumk_dm[orb][block],np.identity(3), precision=1e-6) + assert_arrays_are_close(t_solver_eal[orb][block],np.identity(3), precision=1e-6) + assert_arrays_are_close(t_solver_dm[orb][block],np.identity(3), precision=1e-6) + +SK = SumkDFT(hdf_file = 'w90_convert.ref.h5', use_dft_blocks=True) + +t_sumk_eal, t_solver_eal, t_sumk_dm, t_solver_dm = call_diagonalize(SK) + +# In this example solver and sumk should be the same +for orb in range(SK.n_corr_shells): + for block in t_solver_eal[orb]: + assert_arrays_are_close(t_sumk_eal[orb][block],t_solver_eal[orb][block], precision=1e-6) + assert_arrays_are_close(t_sumk_dm[orb][block],t_solver_dm[orb][block], precision=1e-6) + +# Check if transformations make eal and dm really diagonal +eal = SK.eff_atomic_levels()[0] +for e in eal: + assert is_diagonal_matrix(np.dot(np.dot(t_solver_eal[0][e], eal[e].conj().T),t_solver_eal[0][e].conj().T)) + +dm = SK.density_matrix(method='using_point_integration') +for dmi in dm: + for e in dmi: + assert is_diagonal_matrix(np.dot(np.dot(t_solver_dm[0][e], dmi[e].conj().T),t_solver_dm[0][e].conj().T)) From ad0f2b54b99ca5395e1dbcebb6f7410dfa54e4a6 Mon Sep 17 00:00:00 2001 From: aichhorn Date: Mon, 24 Feb 2020 15:42:28 +0100 Subject: [PATCH 39/57] Reshuffled doc on SOC and Basisrotations --- doc/documentation.rst | 12 +++- doc/guide/BasisRotation.rst | 24 ++++---- doc/guide/Sr2MgOsO6/Sr2MgOsO6.indmftpr | 21 +++++++ doc/guide/Sr2MgOsO6/Sr2MgOsO6.struct | 72 ++++++++++++++++++++++ doc/guide/Sr2MgOsO6/Sr2MgOsO6_SOC.indmftpr | 21 +++++++ doc/guide/Sr2RuO4.rst | 40 ------------ doc/guide/removeorbitals.rst | 6 ++ doc/guide/soc.rst | 41 ++++++++++++ 8 files changed, 183 insertions(+), 54 deletions(-) create mode 100644 doc/guide/Sr2MgOsO6/Sr2MgOsO6.indmftpr create mode 100644 doc/guide/Sr2MgOsO6/Sr2MgOsO6.struct create mode 100644 doc/guide/Sr2MgOsO6/Sr2MgOsO6_SOC.indmftpr delete mode 100644 doc/guide/Sr2RuO4.rst create mode 100644 doc/guide/removeorbitals.rst create mode 100644 doc/guide/soc.rst diff --git a/doc/documentation.rst b/doc/documentation.rst index 93119a5e..86e22f76 100644 --- a/doc/documentation.rst +++ b/doc/documentation.rst @@ -33,8 +33,16 @@ DFT+DMFT guide/dftdmft_singleshot guide/dftdmft_selfcons - guide/Sr2RuO4 - guide/BasisRotation + +Advanced Topics +--------------- + +.. toctree:: + :maxdepth: 2 + + guide/basisrotation + guide/soc + guide/removeorbitals Postprocessing -------------- diff --git a/doc/guide/BasisRotation.rst b/doc/guide/BasisRotation.rst index dda0a573..55826f5d 100644 --- a/doc/guide/BasisRotation.rst +++ b/doc/guide/BasisRotation.rst @@ -1,16 +1,15 @@ -.. _plovasp: +.. _basisrotation: Numerical Treatment of the Sign-Problem: Basis Rotations ======= -When performing calculations with off-diagonal complex hybridisation or local Hamiltonian, one is -often limited by the fermionic sign-problem. However, as the sign is no -physical observable, one can try to improve the calculation by rotating -to another basis. +When performing calculations with off-diagonal terms in the hybridisation function or in the local Hamiltonian, one is +often limited by the fermionic sign-problem slowing down the QMC calculations significantly. This can occur for instance if the crystal shows locally rotated or distorted cages, or when spin-orbit coupling is included. The examples for this are included in the :ref:`tutorials` of this documentation. -While the choice of basis to perform the calculation in can be chosen -arbitrarily, two choices which have shown good results are the basis -which diagonalizes the local Hamiltonian or the density matrix of then +However, as the fermonic sign in the QMC calculation is no +physical observable, one can try to improve the calculation by rotating +to another basis. While this basis can in principle be chosen arbitrarily, +two choices which have shown good results; name the basis sets that diagonalize the local Hamiltonian or the local density matrix of the system. The transformation matrix can be stored in the :class:`BlockStructure` and the @@ -21,7 +20,7 @@ and :meth:`put_Sigma` (see below). Finding the Transformation Matrix ----------------- -The :class:`TransBasis` class offers a simple mehod to calculate the transformation +The :class:`TransBasis` class offers a simple method to calculate the transformation matrices to a basis where either the local Hamiltonian or the density matrix is diagonal:: @@ -46,9 +45,10 @@ One can transform Green's functions manually using the :meth:`convert_gf` method Automatic transformation during the DMFT loop ----------------- -During a DMFT loop one is switching back and forth between Sumk-Space and Solver-Space -in each iteration. Once the block_structure.transformation property is set, this can be -done automatically:: +During a DMFT loop one is often switching back and forth between the unrotated basis (Sumk-Space) and the rotated basis that is used by the QMC Solver. However, this need not be done manually each time. Instead, +once the block_structure.transformation property is set as shown above, this is +done automatically, meaning that :class:`SumkDFT`'s :meth:`extract_G_loc` +and :meth:`put_Sigma` are doing the transformations by default:: for it in range(iteration_offset, iteration_offset + n_iterations): # every GF is in solver space here diff --git a/doc/guide/Sr2MgOsO6/Sr2MgOsO6.indmftpr b/doc/guide/Sr2MgOsO6/Sr2MgOsO6.indmftpr new file mode 100644 index 00000000..ed0a6b56 --- /dev/null +++ b/doc/guide/Sr2MgOsO6/Sr2MgOsO6.indmftpr @@ -0,0 +1,21 @@ +5 ! Nsort +2 1 1 4 2 ! Mult(Nsort) +3 ! lmax +complex ! choice of angular harmonics +0 0 0 0 ! l included for each sort +0 0 0 0 ! If split into ireps, gives number of ireps. for a given orbital (otherwise 0) +cubic ! choice of angular harmonics +0 0 2 0 ! l included for each sort +0 0 0 0 ! If split into ireps, gives number of ireps. for a given orbital (otherwise 0) +0 ! SO flag +complex ! choice of angular harmonics +0 0 0 0 ! l included for each sort +0 0 0 0 ! If split into ireps, gives number of ireps. for a given orbital (otherwise 0) +complex ! choice of angular harmonics +0 0 0 0 ! l included for each sort +0 0 0 0 ! If split into ireps, gives number of ireps. for a given orbital (otherwise 0) +complex +0 0 0 0 +0 0 0 0 +-0.088 0.43 ! 0.40 gives warnings, 0.043 gives occ 1.996 +0.04301 diff --git a/doc/guide/Sr2MgOsO6/Sr2MgOsO6.struct b/doc/guide/Sr2MgOsO6/Sr2MgOsO6.struct new file mode 100644 index 00000000..2078143b --- /dev/null +++ b/doc/guide/Sr2MgOsO6/Sr2MgOsO6.struct @@ -0,0 +1,72 @@ +Sr2MgOsO6 s-o calc. M|| 0.00 0.00 1.00 +B 5 87 + RELA + 10.507954 10.507954 14.968880 90.000000 90.000000 90.000000 +ATOM -1: X=0.00000000 Y=0.50000000 Z=0.75000000 + MULT= 2 ISPLIT=-2 + -1: X=0.50000000 Y=0.00000000 Z=0.75000000 +Sr 2+ NPT= 781 R0=.000010000 RMT= 2.50000 Z: 38.00000 +LOCAL ROT MATRIX: 1.0000000 0.0000000 0.0000000 + 0.0000000 1.0000000 0.0000000 + 0.0000000 0.0000000 1.0000000 +ATOM -2: X=0.00000000 Y=0.00000000 Z=0.00000000 + MULT= 1 ISPLIT=-2 +Os 6+ NPT= 781 R0=.000005000 RMT= 1.94 Z: 76.00000 +LOCAL ROT MATRIX: 1.0000000 0.0000000 0.0000000 + 0.0000000 1.0000000 0.0000000 + 0.0000000 0.0000000 1.0000000 +ATOM -3: X=0.00000000 Y=0.00000000 Z=0.50000000 + MULT= 1 ISPLIT=-2 +Mg 2+ NPT= 781 R0=.000100000 RMT= 1.89 Z: 12.00000 +LOCAL ROT MATRIX: 1.0000000 0.0000000 0.0000000 + 0.0000000 1.0000000 0.0000000 + 0.0000000 0.0000000 1.0000000 +ATOM -4: X=0.74270000 Y=0.21790000 Z=0.00000000 + MULT= 4 ISPLIT= 8 + -4: X=0.25730000 Y=0.78210000 Z=0.00000000 + -4: X=0.21790000 Y=0.25730000 Z=0.00000000 + -4: X=0.78210000 Y=0.74270000 Z=0.00000000 +O 2- NPT= 781 R0=.000100000 RMT= 1.58 Z: 8.00000 +LOCAL ROT MATRIX: 1.0000000 0.0000000 0.0000000 + 0.0000000 1.0000000 0.0000000 + 0.0000000 0.0000000 1.0000000 +ATOM -5: X=0.00000000 Y=0.00000000 Z=0.75390000 + MULT= 2 ISPLIT=-2 + -5: X=0.00000000 Y=0.00000000 Z=0.24610000 +O 2- NPT= 781 R0=.000100000 RMT= 1.58 Z: 8.00000 +LOCAL ROT MATRIX: 1.0000000 0.0000000 0.0000000 + 0.0000000 1.0000000 0.0000000 + 0.0000000 0.0000000 1.0000000 + 8 NUMBER OF SYMMETRY OPERATIONS + 0-1 0 0.00000000 + 1 0 0 0.00000000 + 0 0-1 0.00000000 + 1 +-1 0 0 0.00000000 + 0-1 0 0.00000000 + 0 0-1 0.00000000 + 2 + 1 0 0 0.00000000 + 0 1 0 0.00000000 + 0 0-1 0.00000000 + 3 + 0-1 0 0.00000000 + 1 0 0 0.00000000 + 0 0 1 0.00000000 + 4 + 0 1 0 0.00000000 +-1 0 0 0.00000000 + 0 0-1 0.00000000 + 5 +-1 0 0 0.00000000 + 0-1 0 0.00000000 + 0 0 1 0.00000000 + 6 + 1 0 0 0.00000000 + 0 1 0 0.00000000 + 0 0 1 0.00000000 + 7 + 0 1 0 0.00000000 +-1 0 0 0.00000000 + 0 0 1 0.00000000 + 8 diff --git a/doc/guide/Sr2MgOsO6/Sr2MgOsO6_SOC.indmftpr b/doc/guide/Sr2MgOsO6/Sr2MgOsO6_SOC.indmftpr new file mode 100644 index 00000000..253cda1a --- /dev/null +++ b/doc/guide/Sr2MgOsO6/Sr2MgOsO6_SOC.indmftpr @@ -0,0 +1,21 @@ +5 ! Nsort +2 1 1 4 2 ! Mult(Nsort) +3 ! lmax +complex ! choice of angular harmonics +0 0 0 0 ! l included for each sort +0 0 0 0 ! If split into ireps, gives number of ireps. for a given orbital (otherwise 0) +cubic ! choice of angular harmonics +0 0 2 0 ! l included for each sort +0 0 0 0 ! If split into ireps, gives number of ireps. for a given orbital (otherwise 0) +1 ! SO flag +complex ! choice of angular harmonics +0 0 0 0 ! l included for each sort +0 0 0 0 ! If split into ireps, gives number of ireps. for a given orbital (otherwise 0) +complex ! choice of angular harmonics +0 0 0 0 ! l included for each sort +0 0 0 0 ! If split into ireps, gives number of ireps. for a given orbital (otherwise 0) +complex +0 0 0 0 +0 0 0 0 +-0.088 0.43 ! 0.40 gives warnings, 0.043 gives occ 1.996 +0.04301 diff --git a/doc/guide/Sr2RuO4.rst b/doc/guide/Sr2RuO4.rst deleted file mode 100644 index a1e3c8b9..00000000 --- a/doc/guide/Sr2RuO4.rst +++ /dev/null @@ -1,40 +0,0 @@ -.. _Sr2RuO4: - -Spin-orbit coupled calculations (single-shot) -============================================= - -There are two main ways of including the spin-orbit coupling (SO) term into -DFT+DMFT calculations: - -- by performing a DFT calculation including SO and then doing a DMFT calculation on top, or -- by performing a DFT calculation without SO and then adding the SO term on the model level. - -Treatment of SO in DFT ----------------------- - -For now, TRIQS/DFTTools does only work with Wien2k when performing calculations with SO. -Of course, the general Hk framework is also possible. -But the way VASP treats SO is fundamentally different to the way Wien2k treats it and the interface does not handle that at the moment. - -Therefore, this guide assumes that Wien2k is being used. - -First, a Wien2k calculation including SO has to be performed. -For details, we refer the reader to the documentation of Wien2k. -The interface to Wien2k only works when the DFT calculation is done both spin-polarized and with SO (that means that you have to initialize the Wien2k calculation accordingly and then run with ``runsp -sp``). - -Performing the projection -~~~~~~~~~~~~~~~~~~~~~~~~~ - -Note that the final ``x lapw2 -almd -so -up`` and ``x lapw2 -almd -so -dn`` have to be run *on a single core*, which implies that, before, ``x lapw1 -up``, ``x lapw2 -dn``, and ``x lapwso -up`` have to be run in single-core mode (once). - -In the ``case.indmftpr`` file, the spin-orbit flag has to be set to ``1`` for the correlated atoms. -For example, for the compound Sr\ :sub:`2`\ RuO\ :sub:`4`, with the struct file :download:`Sr2RuO4.struct `, we would e.g. use the ``indmftpr`` file :download:`found here `. -Then, ``dmftproj -sp -so`` has to be called. -As usual, it is important to check for warnings (e.g., about eigenvalues of the overlap matrix) in the output of ``dmftproj`` and adapt the window until these warnings disappear. - -Note that in presence of SO, it is not possible to project only onto the :math:`t_{2g}` subshell because it is not an irreducible representation. -A redesign of the orthonormalization procedure might happen in the long term, which might allow that. - -We strongly suggest using the :py:meth:`.dos_wannier_basis` functionality of the :py:class:`.SumkDFTTools` class (see :download:`calculate_dos_wannier_basis.py `) and compare the Wannier-projected orbitals to the original DFT DOS (they should be more or less equal). -Note that, with SO, there are usually off-diagonal elements of the spectral function, which can also be imaginary. -The imaginary part can be found in the third column of the files ``DOS_wann_...``. diff --git a/doc/guide/removeorbitals.rst b/doc/guide/removeorbitals.rst new file mode 100644 index 00000000..b9ddd384 --- /dev/null +++ b/doc/guide/removeorbitals.rst @@ -0,0 +1,6 @@ +.. _removeorbitals: + +Reducing the number of orbitals for the Solver +============================================== + +To be done... \ No newline at end of file diff --git a/doc/guide/soc.rst b/doc/guide/soc.rst new file mode 100644 index 00000000..bedaf13d --- /dev/null +++ b/doc/guide/soc.rst @@ -0,0 +1,41 @@ +.. _soc: + +Spin-orbit coupled calculations (single-shot) +============================================= + +There are two main ways of including the spin-orbit coupling (SOC) term into +DFT+DMFT calculations: + +- by performing a DFT calculation including SOC and then doing a DMFT calculation on top, or +- by performing a DFT calculation without SOC and then adding the SOC term on the model level. + +Treatment of SOC in DFT +----------------------- + +For now, TRIQS/DFTTools does only work with Wien2k when performing calculations with SO. +The treatment of SOC in the VASP package is fundamentally different to the way Wien2k treats it, and the interface does not handle that at the moment. +Therefore, this guide describes how to do an AOC calculation using the Wien2k DFT package. + +First, a Wien2k calculation including SOC has to be performed. +For details, we refer the reader to the documentation of Wien2k. As a matter of fact, we need the output for the DFT band structure for both spin directions explicitly. That means that one needs to do a spin-polarised DFT calculation with SOC, but, however, with magnetic moment set to zero. In the Wien2k initialisation procedure, one can choose for the option -nom when ``lstart`` is called. This means that the charge densities are initialised without magnetic splitting. The SOC calculation is then performed in a standard way as described in the Wien2k manual. + +Performing the projection +~~~~~~~~~~~~~~~~~~~~~~~~~ + +Note that the final ``x lapw2 -almd -so -up`` and ``x lapw2 -almd -so -dn`` have to be run *on a single core*, which implies that, before, ``x lapw2 -up``, ``x lapw2 -dn``, and ``x lapwso -up`` have to be run in single-core mode (at least once). + +In the ``case.indmftpr`` file, the spin-orbit flag has to be set to ``1`` for the correlated atoms. +For example, for the compound Sr\ :sub:`2`\ MgOsO\ :sub:`6`, with the struct file :download:`Sr2MgOsO6.struct `, we would, e.g., use the ``indmftpr`` file :download:`found here `. +Then, ``dmftproj -sp -so`` has to be called. +As usual, it is important to check for warnings (e.g., about eigenvalues of the overlap matrix) in the output of ``dmftproj`` and adapt the window until these warnings disappear. + +Note that in presence of SOC, it is not possible to project only onto the :math:`t_{2g}` subshell because it is not an irreducible representation. + + +We strongly suggest using the :py:meth:`.dos_wannier_basis` functionality of the :py:class:`.SumkDFTTools` class (see :download:`calculate_dos_wannier_basis.py `) and compare the Wannier-projected orbitals to the original DFT DOS (they should be more or less equal). +Note that, with SOC, there are usually off-diagonal elements of the spectral function, which can also be imaginary. +The imaginary part can be found in the third column of the files ``DOS_wann_...``. + +After the projection, one can proceed with the DMFT calculation. However, two things need to be noted here. First, since the spin is not a good quantum number any more, there are off-diagonal elements in the hybridisation function and the local Hamiltonian coupling the two spin directions. This will eventually lead to a fermonic sign problem when QMC is used as a impurity solver. Second, although the :math:`e_{g}` subshell needs to be included in the projection, it can in many cases be neglected in the solution of the Anderson impurity model, after a transformation to a rotated local basis is done. This basis diagonalising the local Hamiltonian in the presence of SOC, is often called the numerical j-Basis. How rotations are performed is described in :ref:`basisrotation`, and the cutting of the orbitals in :ref:`removeorbitals`. + +A DMFT calculation including SOC for Sr2MgOsO6 is included in the :ref:`tutorials`. From 8e28518a31e281e78e45f2e2cde49f8c9ec9426c Mon Sep 17 00:00:00 2001 From: aichhorn Date: Mon, 24 Feb 2020 15:59:28 +0100 Subject: [PATCH 40/57] small bugfix with capital letters in BasisRotation --- doc/documentation.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/documentation.rst b/doc/documentation.rst index 86e22f76..8a19818d 100644 --- a/doc/documentation.rst +++ b/doc/documentation.rst @@ -40,7 +40,7 @@ Advanced Topics .. toctree:: :maxdepth: 2 - guide/basisrotation + guide/BasisRotation guide/soc guide/removeorbitals From 3c998adb71a74185e93ef9942e01c2efc5f94ab7 Mon Sep 17 00:00:00 2001 From: aichhorn Date: Wed, 26 Feb 2020 14:06:01 +0100 Subject: [PATCH 41/57] [doc] First draft of the blockstructure documentation --- doc/documentation.rst | 2 +- doc/guide/BasisRotation.rst | 13 +++++++------ doc/guide/blockstructure.rst | 35 +++++++++++++++++++++++++++++++++++ doc/guide/removeorbitals.rst | 6 ------ doc/guide/soc.rst | 2 +- 5 files changed, 44 insertions(+), 14 deletions(-) create mode 100644 doc/guide/blockstructure.rst delete mode 100644 doc/guide/removeorbitals.rst diff --git a/doc/documentation.rst b/doc/documentation.rst index 8a19818d..371ff512 100644 --- a/doc/documentation.rst +++ b/doc/documentation.rst @@ -40,9 +40,9 @@ Advanced Topics .. toctree:: :maxdepth: 2 + guide/blockstructure guide/BasisRotation guide/soc - guide/removeorbitals Postprocessing -------------- diff --git a/doc/guide/BasisRotation.rst b/doc/guide/BasisRotation.rst index 55826f5d..60fe23a4 100644 --- a/doc/guide/BasisRotation.rst +++ b/doc/guide/BasisRotation.rst @@ -1,7 +1,7 @@ .. _basisrotation: -Numerical Treatment of the Sign-Problem: Basis Rotations -======= +Automatic basis rotations in DFT+DMFT +===================================== When performing calculations with off-diagonal terms in the hybridisation function or in the local Hamiltonian, one is often limited by the fermionic sign-problem slowing down the QMC calculations significantly. This can occur for instance if the crystal shows locally rotated or distorted cages, or when spin-orbit coupling is included. The examples for this are included in the :ref:`tutorials` of this documentation. @@ -16,9 +16,10 @@ The transformation matrix can be stored in the :class:`BlockStructure` and the transformation is automatically performed when using :class:`SumkDFT`'s :meth:`extract_G_loc` and :meth:`put_Sigma` (see below). +[UPDATE EVERYTHING FROM HERE ON:] -Finding the Transformation Matrix ------------------ +Finding the transformation matrix +--------------------------------- The :class:`TransBasis` class offers a simple method to calculate the transformation matrices to a basis where either the local Hamiltonian or the density matrix @@ -33,7 +34,7 @@ is diagonal:: Transforming Green's functions manually ------------------ +--------------------------------------- One can transform Green's functions manually using the :meth:`convert_gf` method:: @@ -43,7 +44,7 @@ One can transform Green's functions manually using the :meth:`convert_gf` method Automatic transformation during the DMFT loop ------------------ +--------------------------------------------- During a DMFT loop one is often switching back and forth between the unrotated basis (Sumk-Space) and the rotated basis that is used by the QMC Solver. However, this need not be done manually each time. Instead, once the block_structure.transformation property is set as shown above, this is diff --git a/doc/guide/blockstructure.rst b/doc/guide/blockstructure.rst new file mode 100644 index 00000000..72c7da3f --- /dev/null +++ b/doc/guide/blockstructure.rst @@ -0,0 +1,35 @@ +.. _blockstructure: + +Manipulating the Greens functions block structure +================================================= + +The DFTTools package includes the general :class:`BlockStructure ` class for manipulating the blocks of Greens functions. In the following, we will introduce its basic and most commonly used functionalities that might show up in an actual DFT+DMFT calculation, and will illustrate them on a very basic fictitious problem. + +SumK and Solver structure +------------------------- + +The main idea is to have two structures for the Greens functions available. The first one is used in the procedures of the :class:`SumkDFT ` to calculate Dysons equations, lattice Greens functions, and so on. The second structure is the one which is used for the solution of the Anderson impurity problem. As a matter of fact, these two structure need not necessarily be the same. + +[TODO] Describe the mapping. Discuss why small blocks are important for the QMC solver. Do the example. + +Picking orbitals +---------------- + +In some cases it might happen that for the projection to localised orbitals a full d or f-shells has to be used. However, for the Anderson impurity problem, just a subset of the orbitals are needed. This is the case, e.g., when the projection leads to completely empty or full orbitals that you don't want to include in the AIM. + +For the example we are dealing with it means that .... [CONTINUE] + +Basis rotations +--------------- + +In cases where the Greens function or the local Hamiltonian shows off diagonal entries in the chosen basis, it is often beneficial to rotate to a different basis. This is of particular interest when using a QMC solver, since off-diagonal contributions lead to a famous fermionic sign problem. The :class:`BlockStructure ` class includes methods to perform such basis rotations. + +[TODO] Show it on the example + +Dismissing off-diagonals +------------------------ + +As said above, off diagonal contributions lead to some troubles. However, +When you are exactly sure that you know what you are doing, there is functionality to take only the diagonal parts into account in the block structure. Be careful, there is no automatic check whether this approximation is justified or not! + +[TODO] Show the example \ No newline at end of file diff --git a/doc/guide/removeorbitals.rst b/doc/guide/removeorbitals.rst deleted file mode 100644 index b9ddd384..00000000 --- a/doc/guide/removeorbitals.rst +++ /dev/null @@ -1,6 +0,0 @@ -.. _removeorbitals: - -Reducing the number of orbitals for the Solver -============================================== - -To be done... \ No newline at end of file diff --git a/doc/guide/soc.rst b/doc/guide/soc.rst index bedaf13d..f4b7ffd6 100644 --- a/doc/guide/soc.rst +++ b/doc/guide/soc.rst @@ -36,6 +36,6 @@ We strongly suggest using the :py:meth:`.dos_wannier_basis` functionality of the Note that, with SOC, there are usually off-diagonal elements of the spectral function, which can also be imaginary. The imaginary part can be found in the third column of the files ``DOS_wann_...``. -After the projection, one can proceed with the DMFT calculation. However, two things need to be noted here. First, since the spin is not a good quantum number any more, there are off-diagonal elements in the hybridisation function and the local Hamiltonian coupling the two spin directions. This will eventually lead to a fermonic sign problem when QMC is used as a impurity solver. Second, although the :math:`e_{g}` subshell needs to be included in the projection, it can in many cases be neglected in the solution of the Anderson impurity model, after a transformation to a rotated local basis is done. This basis diagonalising the local Hamiltonian in the presence of SOC, is often called the numerical j-Basis. How rotations are performed is described in :ref:`basisrotation`, and the cutting of the orbitals in :ref:`removeorbitals`. +After the projection, one can proceed with the DMFT calculation. However, two things need to be noted here. First, since the spin is not a good quantum number any more, there are off-diagonal elements in the hybridisation function and the local Hamiltonian coupling the two spin directions. This will eventually lead to a fermonic sign problem when QMC is used as a impurity solver. Second, although the :math:`e_{g}` subshell needs to be included in the projection, it can in many cases be neglected in the solution of the Anderson impurity model, after a transformation to a rotated local basis is done. This basis, diagonalising the local Hamiltonian in the presence of SOC, is often called the numerical j-basis. How rotations are performed is described in :ref:`basisrotation`, and the cutting of the orbitals in :ref:`blockstructure`. A DMFT calculation including SOC for Sr2MgOsO6 is included in the :ref:`tutorials`. From 00194a46171787da4e1ae1f8342fd99f08f7022f Mon Sep 17 00:00:00 2001 From: aichhorn Date: Wed, 26 Feb 2020 14:38:32 +0100 Subject: [PATCH 42/57] Bugfix in calculate_density_matrix for purely imaginary off-diagonals --- python/sumk_dft.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/sumk_dft.py b/python/sumk_dft.py index fa78e00e..392f068c 100644 --- a/python/sumk_dft.py +++ b/python/sumk_dft.py @@ -1390,7 +1390,7 @@ class SumkDFT(object): prop[ish] = self.block_structure.convert_matrix(prop[ish], space_from='sumk', space_to='solver') # Get diagonalisation matrix, if not already diagonal for name in prop[ish]: - if abs(numpy.sum(prop[ish][name]-numpy.diag(numpy.diagonal(prop[ish][name])))) > 1e-13: + if numpy.sum(abs(prop[ish][name]-numpy.diag(numpy.diagonal(prop[ish][name])))) > 1e-13: trafo[name] = numpy.linalg.eigh(prop[ish][name])[1].conj().T else: trafo[name] = numpy.identity(numpy.shape(prop[ish][name])[0]) From ae5720f75b9f46202e6b81d482e40b4e4a2a48b9 Mon Sep 17 00:00:00 2001 From: aichhorn Date: Fri, 27 Mar 2020 11:58:25 +0100 Subject: [PATCH 43/57] added the basic BlockStructure documentation --- doc/guide/blockstructure.rst | 124 ++++++++++++++++-- doc/guide/images_scripts/BS_GF_up_0.png | Bin 0 -> 10674 bytes doc/guide/images_scripts/BS_GF_up_1.png | Bin 0 -> 29092 bytes .../images_scripts/BS_GF_up_1_rotated.png | Bin 0 -> 33118 bytes .../BS_GF_up_1_rotated_diag.png | Bin 0 -> 8451 bytes .../BS_GF_up_2_rotated_diag.png | Bin 0 -> 9702 bytes doc/guide/images_scripts/BS_GFsumk.png | Bin 0 -> 45208 bytes 7 files changed, 110 insertions(+), 14 deletions(-) create mode 100644 doc/guide/images_scripts/BS_GF_up_0.png create mode 100644 doc/guide/images_scripts/BS_GF_up_1.png create mode 100644 doc/guide/images_scripts/BS_GF_up_1_rotated.png create mode 100644 doc/guide/images_scripts/BS_GF_up_1_rotated_diag.png create mode 100644 doc/guide/images_scripts/BS_GF_up_2_rotated_diag.png create mode 100644 doc/guide/images_scripts/BS_GFsumk.png diff --git a/doc/guide/blockstructure.rst b/doc/guide/blockstructure.rst index 72c7da3f..178be061 100644 --- a/doc/guide/blockstructure.rst +++ b/doc/guide/blockstructure.rst @@ -1,35 +1,131 @@ .. _blockstructure: -Manipulating the Greens functions block structure -================================================= +Manipulating the Green's functions block structure +================================================== -The DFTTools package includes the general :class:`BlockStructure ` class for manipulating the blocks of Greens functions. In the following, we will introduce its basic and most commonly used functionalities that might show up in an actual DFT+DMFT calculation, and will illustrate them on a very basic fictitious problem. +The DFTTools package includes the general :class:`BlockStructure ` class for manipulating the blocks of Green's functions (see also the TRIQS documentation on BlockGF). In the following, we will introduce its basic and most commonly used functionalities that might show up in an actual DFT+DMFT calculation, and will illustrate them on a very basic fictitious problem. -SumK and Solver structure -------------------------- +The main idea is to have two structures for the Greens functions available. The first one is used in the procedures of the :class:`SumkDFT ` to calculate Dysons equations, lattice Greens functions, and so on, and is normally a full matrix. For instance, in a calculation using :math:`t_{2g}` orbitals without spin-orbit-coupling, you have an spin-up block of size 3x3 and a spin-down block of the same size. In the following, wee will refer to this structure as *sumk* structure. -The main idea is to have two structures for the Greens functions available. The first one is used in the procedures of the :class:`SumkDFT ` to calculate Dysons equations, lattice Greens functions, and so on. The second structure is the one which is used for the solution of the Anderson impurity problem. As a matter of fact, these two structure need not necessarily be the same. +The second structure, called *solver* structure, is the one which is used for the solution of the Anderson impurity problem. As a matter of fact, in particular in combination with quantum Monte Carlo techniques, it is advisable to use as small blocks as possible in order to run into numerical problems. In particular, it should contain information about the symmetry of the local problem. -[TODO] Describe the mapping. Discuss why small blocks are important for the QMC solver. Do the example. +Creating a block structure and Green's function +----------------------------------------------- + +For the purpose of this documentation, we focus on an example of a 3x3 Green's function, consisting of a 1x1 block and a 2x2 block (with off-diagonal coupling). This is reminiscent of a :math:`t_{2g}` manifold. Note that this initialisation is normally done automatically by DFTTools, we do it here manually for demonstration purposes only. + +We can create a simple :class:`BlockStructure ` object as follows:: + + from triqs_dft_tools import BlockStructure + BS = BlockStructure.full_structure([{'up':[0,1,2]}], None) + +This creates a block structure with one 3x3 block named *up*. Note that we have not created any Green's function yet; this is just the structure of those objects. If you want to create a Green's function with this structure, you can do (we will if with some content also):: + + from pytriqs.gf import * + GF_sumk = BS.create_gf(space='sumk', beta = 40, n_points = 1000) + GF_sumk['up'][0,0] << iOmega_n - 2.0 + GF_sumk['up'][1,1] << iOmega_n + 0.5 + GF_sumk['up'][2,2] << iOmega_n + 0.5 + GF_sumk['up'][1,2] << 0.1 + GF_sumk['up'][2,1] << 0.1 + GF_sumk['up'] << inverse(GF_sumk['up']) + +Technically, we use the *sumk* block structure for this Green's function. However, at this point, sumk and solver structure are still the same. + +A plot of this structure looks like this. Note that there are off-diagonal elements which are exactly zero by construction. + +.. image:: images_scripts/BS_GFsumk.png + :width: 600 + :align: center + +The *solver* structure +---------------------- + +The method:`BlockStructure.full_structure()` method, as we used it above to create our BlockStructure object, yields - as the name suggests - a full structure, where *sumk* and *asolver* structure are identical. Now we want to take advantage of the symmetries of the problem to reduce the *solver* block structure to the relevant matrix elements only. In our case the [0,0] matrix element of the Green's function is completely decoupled from the 2x2 matrix of [1:2,1:2] elements. We simplify the *solver* structure by setting the mapping of each orbital to its target block and orbital:: + + BS.map_gf_struct_solver([{('up',0):('up_0',0), ('up',1):('up_1',0), ('up',2):('up_1',1)}]) + +This creates a *solver* structure different from the *sumk* structure. To see the result, let us look at the Green's function in the *solver* structure now:: + + GF_solver = BS.convert_gf(GF_sumk, space_from='sumk', space_to='solver') + +This converts the GF_sumk into GF_solver, which looks like this. + +.. image:: images_scripts/BS_GF_up_0.png + :width: 200 + :align: center + +.. image:: images_scripts/BS_GF_up_1.png + :width: 400 + :align: center + +As you can see, the Green's function in the *solver* structure now consists of two blocks: one 1x1 block (called *up_0*) and one 2x2 block (called *up_1*). This is no approximation, as the off-diagonal elements between these blocks are exactly zero anyway. Picking orbitals ---------------- -In some cases it might happen that for the projection to localised orbitals a full d or f-shells has to be used. However, for the Anderson impurity problem, just a subset of the orbitals are needed. This is the case, e.g., when the projection leads to completely empty or full orbitals that you don't want to include in the AIM. +In some cases it might happen that for the projection to localised orbitals a full *d* or *f*-shell has to be used. However, for the Anderson impurity problem, just a subset of the orbitals are needed. This is the case, e.g., when the projection leads to completely empty or full orbitals that you don't want to include in the AIM. -For the example we are dealing with it means that .... [CONTINUE] +For the example here, the local energy of the *up_0* block (2 eV) is higher than that of the *up_1* block (0.4 and 0.6 eV). Assuming that the chemical potential lies somewhere in the range of the *up_1* block, we might restrict our calculation to only this *up_1* block. The :class:`BlockStructure ` class includes methods to pick a subset or orbitals:: + + BS.pick_gf_struct_solver([{'up_1':[0,1]}]) + GF2 = BS.convert_gf(GF_sumk, space_from='sumk', space_to='solver') + +Now the Green's function GF2 consists of only one 2x2 block, called *up_1*, as we have left out the *up_0* block. Basis rotations --------------- In cases where the Greens function or the local Hamiltonian shows off diagonal entries in the chosen basis, it is often beneficial to rotate to a different basis. This is of particular interest when using a QMC solver, since off-diagonal contributions lead to a famous fermionic sign problem. The :class:`BlockStructure ` class includes methods to perform such basis rotations. -[TODO] Show it on the example +In our example, the local Hamiltonian is given by -Dismissing off-diagonals ------------------------- +.. math:: + + \varepsilon_{mm'} = \begin{pmatrix} 2.0 & 0.0 & 0.0 \\0.0 & -0.5 & -0.1\\0.0 & -0.1 & -0.5 \end{pmatrix} + +It is easy to check that the following matrix diagonalises this local Hamiltonian: + +.. math:: + + T_{mm'} = \begin{pmatrix} 1.0 & 0.0 & 0.0 \\0.0 & 1/\sqrt{2} & -1/\sqrt{2}\\0.0 & 1/\sqrt{2} & 1/\sqrt{2} \end{pmatrix} + +With this unitary matrix, we can do a basis rotation to reduce the size of the off-diagonal matrix elements. Note that the transformation matrix has to be given in the *solver* basis form (a 3x3 matrix in this case):: + + import numpy as np + # Unitary transformation matrix + T = np.array([[1,0,0],[0,1./np.sqrt(2),-1./np.sqrt(2)],[0,1./np.sqrt(2),1./np.sqrt(2)]]) + + BS.transformation = [T] + GF3 = BS.convert_gf(GF_sumk, space_from='sumk', space_to='solver') + +.. image:: images_scripts/BS_GF_up_1_rotated.png + :width: 400 + :align: center + +As you can see, the offdiagonal elements are reduced to 1e-16 in this basis. Please note that our example is not the most generic case. Normally, due to non-local hybridisation, the off-diagonals can be made smaller, but not exactly zero. + +Diagonal approximation +---------------------- As said above, off diagonal contributions lead to some troubles. However, -When you are exactly sure that you know what you are doing, there is functionality to take only the diagonal parts into account in the block structure. Be careful, there is no automatic check whether this approximation is justified or not! +when you are exactly sure that you know what you are doing, there is functionality to take only the diagonal parts into account in the block structure. Be careful, there is no automatic check whether this approximation is justified or not! -[TODO] Show the example \ No newline at end of file +Starting from the rotated basis as done above, we can get rid of the off-diagonals as follows:: + + BS.approximate_as_diagonal() + GF4 = BS.convert_gf(GF_sumk, space_from='sumk', space_to='solver') + +The Green's function GF4 consists now only of two 1x1 blocks, where *up_1* was the [0,0] element of the former 2x2 block, and *up_2* was the [1,1] element: + +.. image:: images_scripts/BS_GF_up_1_rotated_diag.png + :width: 200 + :align: center + +.. image:: images_scripts/BS_GF_up_2_rotated_diag.png + :width: 200 + :align: center + +In summary, we started with a full 3x3 matrix in the very beginning, and ended with two 1x1 blocks containing the relevant matrix elements for the calculation. + + \ No newline at end of file diff --git a/doc/guide/images_scripts/BS_GF_up_0.png b/doc/guide/images_scripts/BS_GF_up_0.png new file mode 100644 index 0000000000000000000000000000000000000000..b1c329b4769b0be5d9201e5eba08272593cb630c GIT binary patch literal 10674 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 literal 0 HcmV?d00001 diff --git a/doc/guide/images_scripts/BS_GF_up_1.png b/doc/guide/images_scripts/BS_GF_up_1.png new file mode 100644 index 0000000000000000000000000000000000000000..db6a77e5b9f82ad306706c4c7c7f355d3abe6832 GIT binary patch literal 29092 zcmc$`by!tzyDdyfNG?F7kp}7RZfQ`Il#-V2lXzN~1p~cn$*tgDxv0p$Y>7>kE!dWJK^ve!5;Y z_<~?BCi@N<{P93G3I;!;*vM$u!@!_oKOL}Ri(Yr&MP3KVj}B_q#tzQywIX&szGE_RSDCi@A}!`gNQ&$#xUE*2fewsHKs;M5@C}w?!WMAIZaMtH`&xq zTHu{t_}yR~kxlzt44EvD@k>2CmKZWbHwM`s%OEjU;a5u`7Xt z>hb!+#=XAbVN8t$G5=(t1z2PV9R@LDL%FD^=gkCotwHlspkBYy{z*+^ZLL;Q2qPp8)_HN&C zsPwvb6S`jU6M`<-4-3v%atYmTQ!KgdF_zV@h2pg4|K8{@sL-pMSHXQ2*6llFj5=BV zT0-XOT0MqQf;}nLt+M9kZ(!vH-d;6z^&aPCPiYSi0o0ca$Q$Kk5+i0t`UGSXt2xuU?u<1xHLDns!DKX?|2bT? z*Z~0nl+@IhH~4+eOvEJM%?Pl?g7p>6|8wx3e!%v@5<|29|2^LSS3d%#z`03RFyxO3T--?<7_9%}#}9qpvbZmhw-0d^|7!bx zG#8e}7aj?N#d=8~Pd-UZU!N>W@bY7ZC$8k`<-B!%X6DzmHG^8KMS^Yp04y;C*`B7jLTY*PCx>U?BWh}D;tC4rDcshZQ(D%a&o+mANHptf zw1_7-oxgoIAg5YdnRcH!a5A^BsQAbr8p(7gPmR;i(13^b;K@Y}H`4@zjwkQuZ5AGX zpclXQ6-U&`iEDOt7KW0Fiq-YhXm@wljmmdm;O$Fh-EgTK{mcE?>gsCcPoIuF(~t)v ziiJOq*D1&oeedHJ=AAFUDkv?bqN57|J;6bs5KVzbDyd>>X_;GF8*jVb0~Y9N`SL3t zDOBevwA&vQA8Y+|%KYY}e_AgK)qa`p0rPIj!d*v)*sv%3MCi}Z(2ue*roxHNe0+S?t1mV)JCb%(mCHx}%G87twzzWz?HUt)t5k98jxGlky4?F* z@e$GYhW{BA1oRnG(>|NmbtkFa&X0skS0NgjATV?;q|;MVF|o1ZCT*X8$E)b*C^$ND zQb z4N7mk2q_#}d=_;V?Dl%drfw9x?Q+Ve)5-R!ugm%QbUCpNTOA#+2YU{Du176b9~&L$ zV2+y4FgQ6m-@SjIMf-eXW5WaNJYcHR6tIROf8JBJ#;MA@$NH$%9=A5FB|CemP{t5x zmrfw!Jg$5`h1}TKNJ~dYMo%Bs8HCC1{oo;TZ{oU@=A0D@$)PC!8}mvY5$Z{W(93>m* zL0t~*^ER;cHr#BcbYdqUvnxfs_9P;j$;F@`R$2Lv`!PpQ`7^GOnnn<%k{_}A#{jcx zc5ppP_)jOMaCqmc-fBmHz}13%bzL3&t|OgvBoT^zoI&4tAw=S6SxEJFEu}B*^nzJ$ z=6JN;#5Z#;3CD3|rSW{F{QCOD1YNg~XQ(f2hB&8fdhktH9CzO_wcXjx&CLZ;Mqcbq zvzv`kK7aoFV}sr2j4e{vzmTVW#nzT}E8U$5dUZq^Qy=&ug&&d|`QAE*2O{z}?jSwa zjCP>LVNN!LJA2f0A>_521wy*DB#CwFP2SZ5vGYPZI9PK}c+wQDnhvj{MFnxXhFuOE;?V?T@={AuCD1Qr zKgOksG}0X2a4zAocS=);zJLGX*|TSVx3&y92sElqA>Y4$Z@GMmj zWCr~sw+T6Mcb=Na={(n`pw{*+FByHm;5&gR&)vxm<2G^!Njufe(^zBRdtL; zCHVDE=dbFRZWNS}a6!*X#D%-q;$=xiaV-w)U|euS?V4}5EUS3>F0J3h|9mSizt29% zv@kF*Kub@*S99%s_ohqC{6j4BcIS6Y1yWB{#iWTy?i3ZHt3iYr# z(&&9z1nP_0_fi-k9}SL_p-3<>i{sOEBxs)mSZQfP^!j6{jEs#{-@W^Lb`wF!9TO9? zmX_DJ#rWKRSkFLb}EVLLkvATE>c&=<|uYhkHQb7t~seBTA# zFa7x?SmP|y7E#A3Bh;2;>$vgEH{BkNB<7!Ku&3GC*#R@rem#O) z_5J(qCwN5qaEwIac|N+*Lqnd>Qq?3C9rt6Y_C|vuy7E9x*&M-sbC66>P!P|W3Xx3R z0wFVUrvJ|$Y9^-0ll9&zy>>X5JjJwuR!?XLVJe!gT3%(#4qUcLz5YC(PbQ1-w7We%+ykUlX|>45)Ou}@5ysp%nc%l>26sAv zymrnfk62pQFB6=oxA#uzfuw&{WnLPqFwkg1+0KqFBqZc3AJMQ?-T27Jh>38+t(}b~ z<1X$5wfI#A>#R|GzPNNwuHo9!Y3P7ph1f0(!q{P8GW=aSP4-e1c zaget-sEoB_%N#Xro{w2a2Ul6aHxYC`)ZYA)wzt@7yDoKfzn+29DKe}go=NR{DZXOo z!^J1{OBw{gx8(J=yT!BhwiM{-=m3%1Eqh++*A>&`XjwG`0DKvdpYHa&MOO*HPm8IN z9miAb2eTTU=6iUOernH^oIw9z%FD7PPT#+yD|Q7{(bN&oKWVd4(uS=3NYLe5J^P)& zY;tqD(asaMEm{gWf54&cB{bcQrlXb!SH`WWn!#Fb85;jIqRt%hS|&S3m&(JuX2x>@ zIX6nA3o8L$S!CK!ecI?s@^h~dBvbEceS)1vkg9j@o`f^EYdbvh2|J)FUL_FdMA@aM zmoIUl-@RG*$N=AdmqrPZV6BN-sm~*Gj?nuV&}GCnIx~Z3|Hu-WJu)*B+;8;UnYM#e z(V5+3SOP1fNKtyR-d)5R684#YW<%4MG{T_O0s)bTDF9%VD%%zBrG*7;fa45LZ_#7> zC9JHh>N~L>j;D~rTk1@3Mb>|rBUEVC`e~F=K_uwH7DFaiPiLiJcDs%JWDyYkd;kJ_ z#wkSxw|P3sfe_6~V$OxO&6sPMk;;KCS;#f)Z|^CE-jJUZJZ6F7zui5~kt-+!kyoCk z{8^3RDbFec_BcMTbTUkhSdp$c98UE1uTYe(5LxnI)pW_-C?$mS$pIsXI|Rogg20y~ zL}V%t8BrENrD)c3^rMv6k@ef1!(N3nJC&qh*d-P5-bv)K-oiaR(i`(_!%)!}7+;U#3kta%u3WAi*;$yZKdkdV^-WxRcVYM01G- z(IAve&R9`Uv~SzL{2+@!ZtRjA7)dJhJepswMNpa3;iQZ9>COu~-)j0sS<4oLWU65M z1V5uOCwMFP47*D2u`P%z4-Yp^;wi}ln>gK@H>Wqv*|ZB@&;x*_lmSQrD9g`wM!&Rh z{O|xzNY~AGl)p$OxL|785dnq(T|Ti~SKqP@?Ta=mHJGM>gjRa@w-@(9kN<_|L2z1d z+beD7*+2e4YdVj?_GamdQge)hGCN>sHG8d7F!ibrsae%C^9bWUoZ$9WnQ)`{q5F|b z0bYx6-_;s9J3>cP_Fr37%kmaIJw4bXSqUNnXRA!c$Hv4wTS|C$>q?7nQZ}U2r|yFI z%-48!j42M(k<^3O(b`d1S-`iCTQ_gKs;piSt0M_}A5^vW|B@abX^&@O@;o&(PieZo zPiN4S$-Wuq6vuPj$Bz;6ZEWQ03CCaeOif9V)6vn%xPSBJ4J{+%kLqfUP2=Zi1PQ3q zZ67L@zlZ2nK#8Q&4oOt!7RWxl3hSGgvD!#}TtrAEylsdx;sot+(z zO=i=;2Q4i*Ma4hLM0}T)IuV_5?aMkoBtU+XFW=t7s zh;5oCO6TQ@h*#ua=5laod+OKt`=LPrsv&*{w=TN;wKuw5oQ+p5yETpr7d@{WK5md# zwd2J|01WZ}&I~H6s)E)=D!S(|mYX}ju?qhRgq5CiG2P~eX461qB19xYt)ptI&To_& z?tgs2-Jm?%j2brTp)&)3i&x#V`LnnERnNKEvS9Gvc~p@Q>3Hy)lX+kyLvU8+xqnT;_8=Ttu`Ndj{ zwsj+>|0DdJYMC@hW%-KV^dVRxM!~K2(0X$~)j4C$HbigUnGwb_23c0al*ubu#k(P9 z$o28}3r1n%6Z`k_gs}rrn~__oYV54rpg5$sIiDkx99X^k?u~n7Ej$Y^f8i0Kyf#dNfWiP_U8T@H z@{wXw*yF?Cz>xQx7??#jk{W|)as4~%W3rskRz#Efm>+L)0ygmWmtd-_at{+?zdeN3MgSkRq}OSdGUzrZGHTUE zfBV+{o4HM1S6A1?msrdxKdf<+snufF$Xktue^2Ws`w*{bcm5}@&UQ6{ae7S8{i_#t zC+Dd`78X}D6zzS76bFlhsa!Q&D~Fh-ht*l*=FNLn=d52Kl%KOa*QFU|suRz8(uV$Y zkRIp9lfS7W{rjT`-jqX`h3%WHhHPr`_pUA#*>G8Ic0Q`~zb-AqW?BYml)k1F7HPLi zDlT*vgp5Y{i6bsAw@hzqhYxeq6o>?^RuXf2pg`??kk-w@>1U7;r0;(Js=&#PvRclQ_8&D^WBn^0wLMuM2$PiPV*+;0Yoz_(z=s zox0~)%B1*{*+=Y3LdhHcE;rvXO40}3)irx=tcyeu6FZ&r;1VO|e9J{(??*9KlvOakr7H}V4>y!=Oi~*g0;3%J-SYWB zKl7qxZo_!w?;iz6Th)cABQ8Qs7=$}0@C7?^e(c^wx(+uNeASLxeF8tz<>gRK z+%MS+xfM$x#X=!W3UCKpI6Be}4h`oH4Gs=`jvsLaoz5L-5j96vCBjfkZ)daG170RT z?H#jVIWi|fiYl5To->&_x-F7pHEzmj%4yy)V$NAWn)WgR@nZ6jpWupXq~K`POK~yR zc6qu0>QW08#TMn*HvKAi)VWXUBh}gd5;e9eW^!vS=GWZR7S$}>36WK4?~dw-X}VXpSsU^5dlHeRo5N7b~7M~0QKF(q&zneU6|OG7@g z2t+%RBH>KqKV`-|>ctP$Q$9bQrTutORr8{10}p@7>7xFSv|C@&wtCg>qY9CF4Lq2+ zH>0$nZedWN=bGBPwmN(PD5LstA%NEb5g($LfZcuMn>ZaOpUqceW9IzC~fdBmOUXM{pL!nw!nSr8at1nih^1cx@S}@atQmt3Ox{El1Ms9M*4Y zmnY2ZX?&Ly#D|Evp0nW~U9Dc_j(+9Ux!)Nrcj`!}_r4>s|Eq}Q=_N2+=srP=vtcR3Wn5iIG^z_t8e) znWf?8eihW&USZhV*Vo5$Lbw+m9skNVxN~sB|FY9O4D@3h)88+DqPx`8I+t49D`qWAG^zqmPfvBBaR~`kZWrb-y6y*@e|Wc2 z^?7#@l$DPAbI6Y5dDgk=*IeuExwUU-WC)S=9+(BZVXH5NSBW_9-Xl@$_N4wt#)X)vs~qd{@}9eHAFFRC9))qCf{O}$jJyCVSgi5UE# z>q-SE^##wXML{RE^(&zElF*n6s->V?g={q_2d zIkXvbiNMF?uX2=%_?MSRiV4`BoW8WL6~w=l9Q<^HXzXCK6sC2i<3RgwkyY2w6C?Nv zAqWK^kXKe#>dqgwJ$fB^#`bp=m$&jw=u47DAm-^j+qpU3l3U%d(C_EZJn~e%(xKQs zgN(H^rGOqH$KXPSI{w{#A9`RS;|cX-KQ8aW@fz_DT>Isjj_e`P_BRazcN?0`Mt{DbAZJ!*O(e1e}zJ64;`-yQcm{j{(_oWQNVo z_Cw#edaj5#SIr1cSsT>b`?{7sm_3J}P3Y{shL_pjt}`W}T*46<;DxQLn$2?IAS2 zbx0gXifUDLTQDR6>)UHarL^$Z46BzW>G9c|<0=Jlt&I z^V$KnohmLa?s$-W7-9Wqg{;a7X`3o@vG7s4u9Bzy$NQiiM^S}T=yO9-;vSp@&Y)xp z&kP*${kLV$f}XYNE?d}ZmgkW*)tMC(jt8ogcUy)poLrB-Sy2&(PfA2xDJm{Am@Inl zL&9|Fd4ag^hWe*Ti8yxAj|OsG0=bq!SeK&A1cARChdeu+mpDeM_ygsuPpgZm#)qsY zslN|PAw+xCu>{t5tDKIfLe9l~~xw zD|%B8mk30c^RjqaBAe0Jmx zAlJ!>#bsq>!(QI^d!Oi-m^M#;Gaot5dMSZaC@wx;Ra0|dG)Ed9ow1SU;CTASt~OJ` zUDU9vh7+-sVaLf?NouAP3=187h)&QgH3}JdM;B=U4Rr3!5p}F+Q1_u~Lel;yhfxK8 zQ;{iVuQni+|*xUMszk@K_mh^H(&_i1uZR=ac8czuD9TKpK)z1jUSbP6OEYb8Mkr5Ee{C??T!sy>WIgZrfcQ%8_y(~d8VL8G#ZpY?;8867}q0uR^g zPumY5W8B>MhJ_zJu*9P5FbJD3GInvt$IE=e)C<#0?hEGTyW&RsJ*T}U@kL0Nt;t9B zst1Wus5#*v4LzxdlfxaOIxIya?v+QCyzUVMyOsPcHP0a0qDc;iMmY9@pt31&y@FNN zhr6SR*|GOqZ&}*r^7+M^-#BO?d)2%%PMJv-iiCUaNU=vDTLOxt34b~XTUSj}zJHUo zy+5Rp`1rT}115hxvD6FfEvttLmz2QVDxL|-7K|F^<*ziu%EcY8gwfBuTstUXjvvY> zKJGJZD&cRq2YKaXU-DQF(1IcN9(@!z7V}roOm~C*yl(ZCgcGj#w%PrAAOLSWD&BQN-&llo(b6U?cZblX?hiJ^%VlIrPsK)yK=81 zO-nzp>kV=9(`b3fBnA09YM!xLO}T8~x6r;gl}s;<>?SF_Dll|>6rtG#Y27i%Vq(~$ zw6vjo%WfNXE|$rBY3J3F$Lpmwn@Y{gHi&B*N|=D7u6J=$eB{SpQ%XdJIof+{HhcUU z#n=_SUGE9~Pc1+{9;Sl(ugUw;<+&UwJ?A$(I-w3PgMv$xU&^N`9Cv@x-!pfV6>32- zW(Yi5hBdo)I8Xn&xU)7J)w)sL?2wlcGxZo5=wiz6&~ZfoQu$|UQYRfW(1wlu6Uwgs z3|)!na5zV}#wkAeK(tKf@#yX>494$5z9Z39qM4ele&x&RG@ z3r!x?dHuMBL5kA2zMzt%SsK;5Y#?brvEp?Xc)UJk8GdvptsA00=4T@FW$M%+A+%um zYz(JY*F=*(jz0;JkReBYA&cPWSfVbtdIXh8!_MB(a)kD&tqwl=_iwN?Qm%9YAa&!t z*S1-0yEB*)=em}LG{S+vav#U>@@3>2=Fzl`{)wq#KMN93K9=aJ0)jisM(VS#i*thJ zee5V{=MeuuN?#l^VYmzaOfUWk@4QHRq06+}RJvz9UZigmif~LKke9eE6XaH3m3vC% z54Bq}(ed3>H__}c9PTWgiv4lFhWEN1aC)#Cw+wePvws13O()0LtKim*V2+98(2#=}=-pV-bbnpj3RDo~Q`~mLja`cILRy?Bn^1CKu~z z$RRy*?rZj)zszi1m<49YulcFck(lW>FB57{K3RMG8ITJbz2qj44bI9Q6;b7?Chp1{ zHyAOqnOpEgxaF~q5aA0Gr>Mp88HY`a7_pUTNxqtatuf2*_H-|KIfqeXk?)qsuGb}T zq2;w{)W_sgLSBQ2Wq^?%hBS5XH;VLVy>Zr1!=nd=KM~#dLiLV>oiknLrh0T=Xzb7W z(d3E^oq)^EyQ9feu-a5>ok#p+%R4{YGgp|ixKA&}g9#CwE|E#Aw+ADK>QM7_Bhjs` zN>*^xnWI2~msmRUzToytYZXMx$Jil>h)!&Pr(Ezl zL;zP@d*yu}j!N?Q>ect~&Ah79q*O)}QGcI&sZ3h){GTn-5x=O@y0dT_LVj&1rx>dC z7KyVc6z&=h-@6R2bI9}|7@miJ<((PpcIU@Di(QlMm?<+$eN zsQ12ty~H`M&SVMGaNQAj@Iq(ycKbSAH^oZN91#$pF_^&?3NpP)sS-Sb{+xERfIrmo zh>Qf*5x@3ZB1N!8O#!P?@~JJI|F9lDf4o0}d#Nw<1-+Y~b&ci|y{J`d2`cn{37@=@ zK&23;ZKqGxW^vgUqC4|(U(q~;e|CAMzfAngKF>&pNlh=$-}Fr~Zwa`%40az2lPGjc z^^tT=IN@9>JWw7MdpKJNx%;up|E6yGWUuY$@3i-Ff5BfKm{6 zEdRAHGo4n;mtvZwOz}Mj8aQz{9j+Qnxp8GvgjD2IMVh)rCqhCl%h%l82~U_FFlcdf zYRymqP;&wW`3fKknkv!gWcE5ieJW#$U0))~4VE8QW%aZEawp;Bqa(u!OD3WBU*<#o6z8e`x#C)TS^)ZSC3_=UEHNA^R zklHVj$4|Xw(t>rjTJ<-U=YJV2A*fn4L?#Z>s8rlaI<=;_`6 zk!u{bT`@nP+M5~kD@L&&Sb6)rbAOfsF)->hdB@CGWm3ME zW7Lk#=y&cA%$WQbEyxjDL(`OZBc}Fy*`gSxTP#{Wo;hB0<*11sxK2_Gbr7C1<1no; z&j?b7*Ni|cmGbLxC%sxvAEpSQ#inY)5#1AALysNhUD(hdJt7t&py`wr2Utt_!-w8P zR>S5fdwcuYW>@<*==O!1s;Vl`q8I@YPs?R7kc4Ds!+oXrqON{#Uw0dI_+T<^KH=>V zAtiWHG(YKWnFh_!+43rJ6kfLXPMd0pLJW6f46$_!H)fP-nG$r;XtAC!YrYb!1FvDP zom2Mg$Q&;@FB4o)CY`SmMv>+cw1-f3?a&R#X3_Ruv1m%FY*+J|Rq>eC%$OZijvL#K z7(43K@K^9?e>_ku!Fctu2}iCR%0$HU3gfEF03%_|)3Tc=>(-IioEEIi-u?qP8^MMI7R0lF)dYt{&EXD3RmC(*VOpNnTXt zGF$nXL8}(+E0Dhwkv6{`gh+;9O&}x6<&3)E7^#Pn5-*9%tKb^9%s�lB1nVIr@Lv z6RnBgu5>~20n1k2Ep6hj80E@&a%^m;4?I$Hl!b*we}DguGwHuma^&-o4vJrY)>dT{ zX(4auv`Qg(j(Dj$dNMFZtGCLiJdnX;&amWUg3H6jupwhZK)>yVA^QhE6V{As`GOPu%vOqX99vIkSBH|7oW6+AL{AVSl zG#*WPdDLZ%yKkOkT)Mg>K&bcJ%&cYFf2P%wzi!EmzO=M-+kwyPqWF{TDMCo*0f(9C8RPnsqux1)6#k(eE$47?)&$PIj6__EBB)md1_tHi%C7Ax7XOe zLw;GQZ26m)s^w#u3GYAfjzOoU9moZ{8 zy+(r_Ronf6wflh~SBmRuz^g75{M`_+CS!A5`RF>mP3SlK7piG9*}R*CdYaLGBfs zl++KtP(cvLZE@@Ob4}-14ZDAE7l-^>jSK4+0~Nv&ysl&f{qa#4N3GSq1en&E`BKx@2o&Z!Xf!W!uzrP9rK}QRT z#lm#Kd46ka`d(R6B$$mk2PR^j>p@asUXhON%Z4v1(~1ugi5?KVWT82`*i0kGqz)xktc(Dej%EW3%~Zv`NO?%`_S5kW$`jnZ{1&T!>$vNNneTy#oqd!H8IIn1L9hN35K~Nz z+u1@;APHq^_=^oRdxL;GCkdoARQ63q#@<)xGTca1Z{Zo;wdsG~O-A{jr{A{p9sU$h z%KU4UdBW-5)_&r%0L}NpaTMtWa9W#GPQL4Al8FoW z-Su%NrkSPX- z5$AQ^ZAA<-`Jj^cWdA15E~H5W>9GqCgxy*)Gcs-@nWV$6fSq9j9K^dL1}W;OAxV@D zQ?PnxQ^=_x`T_YvMTZ_@SX5Sg`-m69(xWvetf?c*7sy~Eq%uEX)5X9=4o}vj*I8s( zVkKrZ=bz^KXG^U({Gusd>0I{dgv(zdRxrqR*@~|m~^j;1?(c|l%%h!mTGD^XIsN29sVeT8NwNxo5mT?f5{N(=ys~q zeUM}7DKDm$H?z>4i)B}!&cA*<(#wkYM@jjurF%7w|L9%QDE|mRKXsWnf&qsOQ3>6c~O2MLWJlM0e zQ^*q)E|QJ_(6IpFykA{i-R}Nk8h-a(i#1?Clzp+ifO;Vk{m_wr+1L32HBTFD>rq%1 zj-1@IC%qkgK+vHPZAl0&$%57a?kxg*TG6yYg)-oQ_Ghc8H2gz_0rd=Bi6Cv?#k>&s<12B>cbOK3hKWk@y_@l&wZgng85)0j~j+T`a6)~2*pp09o_84mU ziWj`rO@p%}FypUN0=1c3*11G{=pSf3;mFszc4|P5&H(zfA(q+~)H&;xw-EW>TZ7NT z0MX=N8h--Na^1)yu$j2SAZk&}oJ!9;GShzgp@_pM;U6--_meMGu#6&_;Gd?u9aH-j~bSJHBAGuwjCxRlw7zeK1X@3v)Fb59J=_til#Lc^9G89>4?{56+7ITC# z4I)0UCHD7Yi&_X;LfHrFF;wk>n3%}!UZ-`7OAF0@#7^*7lTf}VswX;bA;r{@7rX8^ z8ZoFTPV43?Mf6it{E$VS0klsl5g=OPw0Dt;xIK*YQ2CPr@e;$65)MQ*^V6N4nEJmD z{9(?mC~4?6x0P8DvdF^SJOAkK#N>n)!Br-_$!8wObJOA0H!;j)#IB2>d~o^lqQnN^ z_GG;k#2JxR<|9}R2u21nv?Y)(z%Sib-RSDFC^M`WcC5cw4u68hrETD2&_`Lt9M%@s z0rg=2WJ+If=G@5Vb|2lWAJ-i5>>CH^D6>Pi8hxCK#b1_Tvfelt%6cTb&5w?>9Bgyj zT%*!9a|p1atkNhU*%o&*rFD~0gY%!Dp?+CdY&rNn4T~$ZK!9++-|Q7U)sVn|`$*!$lyn^@!*2 zLp)CSOsmHjD6>_EW7`1JN1v%wS5Oc<{mDCx*M9T7DGHRCYv--j59*dT0qwsAG*oNg z>+`=q*Cg1eMLMl)cvsIpkR36|oVVDeVtp&ws)1)aGc|n{hfJ-MKA0;Tt5~n}@1*3v z6rMgr>ZyIfC^q{r9`8{Yq57NXtC2FuZ88yh+x~asrNzaDgNdw5y+BhiF*zA<`?K?d z6l~_Nz$P*?4*6D=1qjM&LcK009H7e_#+0s_&;H~9S@*CKZR_NRckjTa@D?ls=_nHP zTPP-KL)B|0$jBz0|?L*W2e@!Xm4fB*iqS@{Kfv_3bd3FICghfV*~)6`6Q85kMS zx9dCA=RSU{AZ1|GdyDSOp<=Ny@IBT2umP+@-|zGvDgn0hg3d4BE?kv09rEc5Cmky( znhR(hCPz)K8W|aA*LQ}Pk(FBmMEu|IaS-T(6sa8D&kU&J(9+7vn7#5glCR*ubnYdW z&MhyHY_9^`#PIQ_9&INf7pUGCQ74VaXkZk6#cp4Ixa0WAkq9OO$%iW`_=GEtAJ(@u;4R5|8kkEY5|_+r z!w9MMGs2x%B_UZLHE(F3`SjS3o$U+isxUi`*btgbiPsVwDLl3YZLh>42{=Pj1~0?o6ou6D9HJz2LwRs;08kA!4vwcT2i^TA@)+O%>IgbLwNo$G9Rei8 z#}+rvS2`0{yZf&`d5pS0J^_)&M$NL+S1NP{IPGORP2{I3;{d(_V&AB~^O#Q6Fl?gU z>0oa1$R6ydE1)0#f>OZe{h5kpAh3l2$nETWTw5=(d+|4GF^#PSH8sDEu| z7+X)iUQa_|i>_GG^+N?$5=Dgp7@)Gha-gI9+vU^{EQdg&`Ec5fM4Af{8rfLt6CkLe zkcV`DQv$6K#(&g{&XW}>h{zr3Mu6c0s7~L?%F2H19b(p~^dB4?)E$>aGfv*o`&KFF zqFSrOVEUPV+wUX%`Q(RBbWKhNs(*x_mK(qZaAEZbN-f`k@1)zHf)>Qa(wK~lavq|{ zpIt7)f>*Sdg6GN~BRvIzI0b?+6}4>0NGJH?;QN(tv3-$pbTlhDpGf@j^h zL;bKW{6Jx3n>wiM&E&TlLcz`+E63E}UsO~Sd}D&&$1(m8T}dpUT6@2)G#ib#Zk6loblS;>LgTtr6E$S{e!D5KBfH2dfWjH82WfR>L;sTSaKd2nLkz*+5hJ6`|o})tbnHi*XIPCDU10h>j792>nxI# z5;iik7??n^x&5K-_61-BK9zr2?~O9q`je&~Digc{x|jqgOb3DD+onMq_r;3}??4OSo>Bjaa4)_^eRN6hbJGo@hyE90ms z@q%uCmBNg30En(b59aIKNlAqnj}8}`z}S(49ya>?8QsxE>{P_c4uw?sYi4HV z1^r;WTHvc9ARq|5t5>a+q`grqqo{pyIZ6WuBM=U=mH<^IL+|%WMzQ`3J4Vm{&6#)4 zW3vJS++>CWadd!aIh`?#x|o$#!L@3;cLLfZS|%pry{S_D;CI2lBrHjNj{U|ldd)EE>BHl_L4_q! zv9>#yJydkOy9Y~AcW$l>_c`ad+eed2OMk!w@5zZ0dTVD_`RPbSMMV@q8(=6T5_IFp zbO{XGRMd)sUVdGofBD;q#hV6X!Cg~XONaMZL{m6Nggy>@#2`3;S#Ar+qp`6u?8E4v z^9R~av!DMlcaF(1ADnrB2!ez`bSzW`{CYGr`NLkn;~8^+GX~VYr6P&&#}W-Ckg7!x&5@md5nUHR@C^l_4QdmmVNR#c?K*L0w-NK`VnAy#53s( zfC}^tFrDq%XMpWY*Jbq?uB1N5P;zr~WgbPMs~rkx9-G4vG~r4h{#v=;57vQ(oT~QE zA+*=L^OZDKs%;N`%iJ8P+cp^x07?QU6EIElaJE?yF@wA=@WX=Jxh|4L5*d`?`s zed6d;)Y6&}+peR!hNB_on_WE%EO@{FLvI?%5!mPc8mZZuaU=&ronFx=^MA=rj>zpI zG~Gc~j1U>9wN|A7jZ>5vfJ=kS-76uij!jNV%F3c>XlM`#c_e~B0>3N#8$`*@^PTY| zRzpM(nNOKC$ql9}6!{B{;mwQzMUCW?PrpER!#MW4b^_TTqy;D3Scd2s@k5k6{&ro8 z-dS~ylao`W&8k?s%Nokl0tIf;gtj{>?qv`Ak89YgSyRYpxyh5Ld6AB@_}}nejkv!B z7CPV-=$e8JM3BKlISA?`j#wTvW{(nn;K3BWW5EdWd-A`5jvrlG!YDAjiXsYWC5XaH zjb{RPmBS5@a1UaYuzK=td~EX)jHOn{1~3I6-b>eqZ_*_CPn*W8SN4YuTb16A4|+uE zM8jGXeg2o*B*j9Ww+^9UVXnYa37{+Nw6;AuFc~6(Tzms;g88MTj0Co=4ADNesu3}E#O*~+e%KnPeuD7M> zdO2&t`*?Q-FIaNiy=g`8why5jMMvSE1c=Dq8>+-fD66o2$nY|YH8&^l0l3=LbaaLQ zTv|E1`IiRKNGQJDZm#|F2mUaeMK!!?QXhZFYQ$5H$n;t+f;$>FUpjyC$u^jaS}(;i z(xATNd8I=FfDMS4a@wg!WO{6*axemCXs&@#V(+4eusc&sVj8Lu;DMxI!o`mRJwW+a zh#tTm0CfCxKGL=1S{!iA|4%IdA@JQ~J(>T6=4-#KZ>Cs38P9;X3(-wxHOwTP%&*A| z8Lly2B-rLO9P6#^6=rTC`jYIn#PPFK zSDN#Zth+n^2W{JDVAt}*4nT$*77*`QPX?|YvC_j>ueZ%}!qEiQ$Cre`E2wWtML`|` z826UiMeoOZ0Dr)FSTHCQyAG`g*b>|0o;UKC7Gqk=`^6o;iUub6im$e#i17b z5b@|d2ky>iE#Mt}0aS7L90W3d0&B%rpQwZyr&(6~>aLwh$Iw^>L~A>&b{fF{fwC6L z?w7Icf?|k^b(yYqOW>%rp!`pojvdH`kuwhFLERs7o!vdjGk_;!zQ zCj~9q$yrKY^7rQ*O3ucvUo35Ao4%y`40U1K(JtB6pn!3Fsp?(M4}yDbIGK zi$F>A8z82^QwyFTQ@igom?zgA5JsWPqWy={%~K|l%1zAzVR2b4b{%~t?fFah^G}SV zD4-2sb9=G0hb*8VKD)9FCx_aVkAB#Kcyd7f&P~@M``_NRztu0iPy1=)Q@A2P0(RE4 zd>`4-aV&37WTDx#59+-wQG!DfppQ_|E$|eEjiMV^(;A-Ja|jIUs1jBPCHQ#yH00}?2HJ=d zi@*sQJV3y}BL}yOW!|)?C@$_d>84k~f(N)IDVQm=iLk^>C_TEttNME1(KXg(L# zsc`sDu>Wy8TxbAH-*l5Fcv!>|v{(3*Vh{$g0U-22+y^Kg;7KDRBY*yqf_&QNy^WEi zoVbfP!@$)Y4;Wzq_9!<>*>UB}|IsrMvJE^Ft2NWQ>xKF0V&&5~z|x(}X#qz#N)EGK z$!}X92YeZ>$${kg-n8)mD!hm+JA8nJ@k3b~|6xW8!`yN{hLQp33tr%FBh5Aq#2oHl z`Vb+K94ID!3rZB@7<`6DU+8#kR`vj&L!+bl_G^m%*r(U*l`U0&_Kd67R7<8a~ zN(bg3fRp7TZMpvehk^WPtRjn^2rWuV{U?ZR;O1*Ak*c)iK$8^-O{3%x(qp~X4`Zp} z{Mvuj+pde@reeWQdq;>IO&5^S&C`H7Nkzwpab>qwH~wHRII@nR@w-^uTml~+@TicA zj*T3%zEq4&G~n|ps@5cGnIbK9W!97C6YSOwkvUjz^oLdCmsZ2A=hEwhz>6D7W;?~8J z?~I}7+CR|AVwu=OTiT}N_aE>Wh>a3q&QYsBk~gOpWT9MK3pSnTKq%6>yao7#FTe&3 zvZ*YvUbU=S9FcRv6iOp5x{)qPk&u$^ZVVa$r6pdvL0ZD0q@|_1kvR9f-#P27Z~fN!T6I?&pr{ z+SlIux^!r?w0Y{h-oVaMqkmIu{#VUS6@dHb3zA@MG^6 zJ9TYqr3pNx28c%drw`Q^eNV@gw--uBdt(&wX6}v&k-wWKud5HIQHSF} zK=9CF&Rl`L-Mp7Wei{$+NQ=`R(`9n`wslvYEvxSy!@ceV-i;Y^#KwQaqTk6hi5#Cp z1s=?mZvr(O-G64xYfRWSoB@FikjJYLNTJ#vRJp2ekQz7cn7PkpmA~{vn;xZ^ccd*a z9jaZ>soy(HhGgZ)!c7=v{^>{uv`H-=)3j6*XwlLSkLEy^gu)ER+{NLC%Z8tTMS`(W zNnG<|Xb4dq*B}a4%@j;dNs$I2aAS9jnwjp&Lxb1Bil*-7{li|9`T;4gk|G`?l@8VN zebC(LX-JfJexKWyD3Wy@dk0$4{-S>EkqNyrF`p=Pt{lVCk0_io7ZAHKc&QHDA(ozu zqnM6q!5PK~TNiH-`+M1+K~BKiq|Tc@cq95Vz{c#?aI2E%FRzY6!(IQe*4ruG%=($v z8fO|yx{%wvJiAgsL4u@kdwC=U2cxTwY?c{=cPS)Ak(Fj*Ifug|SQ*}cn|(Z3J{y1< zY1C^u>4kx9pV3#uLXq}NpkOz1Q~WWD=aJcFz>9$UiQ8qu@M+K7)q{Ljj&>W-RKC^7 zo&Go>5Mk5&4t($j^Kf8v^ba^nzVDOd|6LBn1pwVJSZ?8qZ&;X_BbILeJhP}53Yl%d zc&&Y{MXfBIMLJ9v;)7aJ&1_uy30%|_9r+6;6d6n@GM7f(i){Nu)e z`X*c~(TDFJ3AAL-Osq=gQo6^{ahjHM2~F?4m&TKprbk7<-Yb!`^18YJW0VJJRMD zR;o`u1r2I8U2(5pANxO%U34w+=Y|O#QbKS(cH!eac5FWuY&}IGVAnsEIYpys+rg>N zth5>#^ww+F?>#-#vzUCM@*>vCO&;+y2FVHgXBe@_qe=RDGRC&wcip8h5(M2jBYoZo z{IKJN`_}&rMcSUr6_=%a*1>AGqD?+=&<++3^Vi4k;K|S^DXieqQc#V^0y}R?cJ>JH zJ^`*)7CVzA!N5qO940KBE)$7U4UC^?eD`>OB?tFRB@Vf1WrXtis$N^8E_TCC@5V9O zXp^X=qen@th*+(V7~=1y$>>&5sgwnLBbrtJ#Z+VcpW6HPTv=Mz8>nF{mvl3C|A++By)194SeBs5M`kR^YA(~z3VAb&&3X($VTOBNU?J1hfV1ypko z#EPE5W$ZFY(l7|)A~I56`yEIeAya&I_-v19+F2H?uMLOyltmo2t~&NJ?fd-=n#MAf zeLhvTa_q1w#%kAIPk~ACUGRY?%JB`<8@?u$h=sBR-HNw~ljkFe4QH#?v#ha-R#s$w z3X3kElzplkZDH)DvKc%twS2gIr+)uwl)?eRF>xpbxwR(gG50cg!uK$Gr`Y#9DXoS}^bD0TO>at>d1Z$h1ZY=j=2*!}w&&59^vLK0Ay~tSclR&+Z8Zb|^`Rd8`8{AkR8chIUC>TG9gu z3}ADG+AX?edey*h1Sw@ogha4{y!@S50R#VOA%Ew_e8$rzo2n3D)7QVO6^AdJ);c|f ztw}-zO3cirrx+kK6gy)KjYQf|6;Aw2S_MM>?1(;X;H;299Z!}O-y@t6bt)A8Y;{Rg zjejb9dcSAa^>YagzpBh>sa*!?$gbQ(>*sgj^b8los)U4OThk;NwY^sjydQ*tbh{OE4Kogmh5TEB7KIBCuNaQEWwQ#(Ox{Pf!HmFTKc>rgwT zD2_{gROZa=`g}%S9gahLP^ghCrG&jU-9uT@16R_=>D@!NzAydOaFa6#a!o`}ZjBj@ zl)3>yk4@(IX2Vs^W^@$nj|6e}e8^aQVOP#l_f=rX`{*oTZ>pp4Kng46_J66f<_sXp`2MxL>gr^Wg6BvWXm;9Bm%n2mR1N)QDD+o2>$-)E$hU*) zx7nknhR%ftg5T25SYxDL!~qutDfGlnYdF4DOw@q^uc7d9HEW*FVjwd8f%7DwrSOGz zAL1MDSa#3IVm%aZv*V=%^KEqwfE}i!v~+cAtf0~ODbN_JD=BS;X@VrY9K?P>2-}U! zH_ave$HB!4nslRR7s4)gf#09~4tuyF_#+B?@#22RXQr*bKM@bh(GLcjVlaIkhySG~ zP5$!GfcNCuojPsRd?y=8$IOm}VT|6UAU!lPLNX4fW9Bj-_X=hWmp11n1D-`p{~KaP zP}@LOjR3F&oqt0+QE){i0a?nkB|Gcti(!m5?==#~8ah+2P z?hd{+6BbP9UAxnaN`mJXyf~dWJs8@z&E+-H7Gt#pp0SyOz5<_?VG5C@KNPoduxRVz zD{Ji9sV?k9G&Sln=iarcfjSSxN=qfk4*r!sk^WRIw5g=vF&p3;SBG_8{WRa34C3fH!@`}_0p<^QWdL<0y)~6^=e){>>2lFv|3S_ zgCU&FeUx@G9xq6-)qtreDFO;EBzqXSYNNY-`gyk6aZ$RRhgYe>a;_31`j~V#IM&mE z;L)>1Z0mJHo#S*0@J$3Zc|iPFZrUaS)su&K=+Y0ryz&@mE}i&V`gX+lBf*65{5N4! zZ#=01)x=Fjr!q+V3$%Em5JkE`@vK{eFFr@f>qAEF;4&?4ig~!dJ{@GY#l|KHlj#hrItgBsZ+QP)!CYV0;4^=noojm=PJ7#647!?7<4M$@`P3|On&Zr)?MvJC) z{oJQ$eisXy?eoN%3zq(@NDS7Guo!a;V)b0{#jlG9ry_*)SCzR`k^2+smvs)r;3Ndl zzowDVb8Epw#RPxIp%^EP9p=G-Thop)A5A66)&fczVe=(qd<`hX%s9j8h!kN_M13Zl z)DQf+vXCll%nIj5d(xmPgNmO|X0G$9 zd?sPxbXsK3w9DBV>3I1K<5tx-UCO>Q9C0$gMGcd@w?|htBVaEqEVLAiwZsOM39HM4 z#cqeSsKRaN?ZH#Y(8><>Uyo5OrpHd>RBMy6sV1&NBu2uXTxma)N3;3)R0MoX7nPvJm|JJOGxIm)AA%DJ%v!g#_P$Y7^h97fafn3Idyn-{vpp|qvO4w!ejTUUC3-Em1?WH-veq=1h^Eh&Th}4!s=GA%eE7>WAq_ZHW(t!>) zH&P-F*&=Oja(7Z084(!j{!?-aOk!$6_R`WHz;};UvDiRIM;2iIKrbf>d>Z@Axsy^- zzR%S;b~|}q314Hh{sZABCUFkgJJ=PcDswKV=p8JNmKqG(G!{!{vv=WNeqEb3Z)ECG{&_Sj2Av_6k5d0gO#(!%M`up>7t@KpTDq zUBS3=!|>?8VCQk6Szy>|7s8e_Y)x0PulDmUPC$1~n)-tl3dNQqu-elIWOcC<*a=5p zZX=^`@G47#{sU>XPP6|OdTtgeao?gyecV}ZDu=YJo~z5p#`zKa4im177B00lThjnE zTI!0T_FiF)Ato@TIJEZjJzX->*erN+jccy0kIoy*BL`E#KSe+Jcu|QP3 zm0VB#>6bEYJn7a0nqu@1Q&`jAKk}0KGWqRRy6n3pOE=@Tp1%{wKx-hiMsr@~(%n61 z7e9VK?CmygdA;_V@9qwRkvd5lPw6WBa|PxRMi)~}#N1*j6>Sof`rCQc+NUZvv{qC0 zgBH2U&Xi|9U{K40?hl8gfA+vAe5pCLgEtvr=4Wfs2xnG`S{%9-~b&D%cF7;^UB+y-GVJ z;Xk?mfhO4cNGN0Z$k%0AwfKflh@vY4TGNi9|1|il1m)hYVP|9WP>%;D5MfmG%6*A@ z8UKs}Rf&iBAl-x9Q9`7z!MT=CxPTH@W}FiYZoE#5L4Bfg)l5f1C!>vt&_b!PF2}aS zKIw7~j!?bHYg-AF5v*TCjklg@#?Xt*E<5rw{kuQi1yn-w!<8S0x88YX{)ULiB<8^+ zhHU3&&$ijxAAr-`?XSA6_41|wu;#}V(;@v5$Rct0-p_GKihdZPrsUW;2krd)>{GdQ zRCamOm(35)g!wWXKbWL>hZ>Ak;F>%;zAljuxEYmtlan&qdP~##NTM&zR16s}Jgr?{ zH2kprf}AVBC2gZ-A6DggMh8A5>L*c?e%6RVyw3{0ca}L`c3_KgZw7~qOaV=U%w%P; z1nRkNenF)Kqp8tPlh>b;u+#NB&nmmFDkb$a6?1MvT~GWdzjl1HR>?{~X(_ziSCx0n z6-5qu%=gc1KygBD>nUzuQJ;%%*Nl|G^JXxK>>01#927cm$eYdC>pvm$&x0jW49GA> zYZ-royQy)kItV`zxdmacw^pmE&}>r;dX!Q)&%2~&>Ktc3(s0Q2C0{2^;>dJmnfoU5iiAEa$m`)}%M5>qU}lzkStn-@6}OTAVw7 z3)NE`j`-rrElf+$AI<5JLZ%;sk@DSw?5NoESAcsQ?ZY)KqhWkGS6c*IdRI*nS})mz zZ6cCv zF$F`;TeI)#C$hGc7k~>p7R_>PK-rUkUqWf=WI6Tbb%yg2v&e1Q`vCP7suy!6?3MmL zF=oyZKgOE%Y}D1(`psJM4|9TY1H4fKELG3~PAmCdUjK&a-G7a_#K~GaNMF0^lTh8t z*fB%~n~o@fpETSZE!LIf^R*~4K4J?qP<8tSkLt4vZZ+!4K>f&A#ppSsezMOJvz^gA zfPda6`0RPYr&FgtHnbd9>DNp(iL*7uM!a`gQ*@^zHRX}MWqG=cYG>^&q?tYOS zF+6p&)N266cr&POdtpsEJE%u4c!HST+`S>f_!(u@g*(;D(o!f^&^J@D{bhrXLA(o2 zG11$j?&8uP|GXMPI4!y_0t*~qbcfKNX=!WER#~6`e&W`(Oe%}?;Hix58Qz*pS(eaJ z-|>xL!c^VK^|rkDbB|!FbNaAUI{~-T_wFPk&2j03Dd^L)6yN9>1ts_Dg>pJJU;Mbg zb_=*XcCGhw{m8<8@#wE&?6bEUjf^MbYw6apue1!Q*0e2^swm{MCBcZvuJVN`Bvr7W znb~y_&F6`v6NPAeE@ek}<^g(#wXH4R+dnFx)Sf1CzG_(tTr88avWD|yA`w+z;9N`w zgmsXDsl~N(hejPPaJxfmz26*an?!3xbPcm;46|trO=!SB=KMA@sNU=t8c+UEjQ8?p|ltvkxCrSXWTldq-n?8vNtz@g(OimO)AqiH*LL%eXZ9WDBkeZ<9n zcjly$dS7-5>r|51ISOu7F{LRbHkd1Or&3wb|F&f8a-i$7Wc+PO*X6+2_b=EWxKl;u z_ZQ7%Ss>*XFXDa)c*7OU#|aCr!aB(qc8Md?OjJo4i^xoKIJuS6+`2Hj)Tk#9ZE7-c9QS z+8!RSY6%$A5I2-QZtcA%uoXoBf5^oC>Q)R8za-jrNxge}0*^ z5ZvP4B0dwLM#~P7sx*hQZFyj#Wh;_8PkM<9UL~Bzgyges5y9CoMX1}?VmFB%>N<}* zdlbL{MIb@4Bi`vSX@%{L$|Gc)&l(TK4vzp;biOwWjh(K*0s6Vu!CrlQmpL5|Pck5% z0aLe$l0^h-6oi;aq=wn8fk(#6v?i6OcMQ8d5>3A^aVsvVcm1Z%@6{yH(ac7`!3ake z!5k|gI~R#VsQYkIO(QkAN@uTsW;JwywF}q%rs*zoRz=c7a)>UZ-|Tfcjqrx&!Y4n-W4gxff=WZJ@ur=;M`$V zck0Mpv?xYD@=)wP61nowqU(X%#kFHsz$0iQ^DCY#Jw`g*kEF(w0nIGN)T+E#HRuc? zPY*aXz*quVLr14)^l*{NCYC-7b_78K!)D-@M`!dM&e4cPEa!aoAm-+y#7K~fk@2F{ zCr`$1fTCER!xoHKc{zt#jwrd1xW^6=Kq43GkG(}fJuD?dL^QTm{&7H}ur&SOSwkU=rf)psl6#z1d?I2|?Ox+%C+NUyMtI_1Zn=PnMVC zwT80u>j04}AWedOrT}Q{01GF_|6*3n$B!b$S{qa@YeTid!COtz|M*Js8cs3i{z zSfT%}GX!{zgkTK;G4YHX1eoj~|F!B*=(VW2Z8ZE>1 zU`XHE?d1HJ0{83vBb1zJ7;8z5H!hh}MX#lOw{{?sK!{bVypJt` zu1++qG8vU&6s<@cruQjE+ZKkSnLYd^vD{jpKq(Pgq_C{JGGMkm@oA;gD4)dphF`Pe z`edH2z+5)c3oTTI2fw6e?sHuNs{eB}IVi92qUkoaVt(vOn!vhim+h{_-?uLJ5CiSy z9p|nO%AKCqaQ{PyG^W%S0$UV*UQor3sT4_9=zaZOnl73?LJPu=Egp#d+y8~i{%|Yu zfgy_a0aEuCyAvD8vZGZ|=q8N1d3v;CC)Rp7CX^NPqw_MveJ-%PPbHSu)nG^s54ba% zvQAq?&%WTvvbW2<;;EfT;No9DegWp537Oy9T^S}+Q)18Zu*)10ti~65(kpHFx&-d5 zAoMMnDGbR+SN)2;(kHS|dIn(}3s++y(Gc-ftb^;%QJSx53Ec!k9v1FTqp}ak9S|Sz zi;?UZmfGHDRYGYxX_;|`Bw6x5SEFU_=+fP;S9jAr=10^&yLB()=eRYvtt;^d*GC_B z?h(JKnfPXzoCi~?wMam>J?&fyJWw|9=c~;M|NA?LT=^@+IAl+Np1cJw#5IR7h>8P; z$-kuT(dX%1Ac+C;hAQQ6$VyRUad^f;7#(+{W5*Iz#LTxH@HrAhs%p(!cPBX^>z_tN`7+|PQ@xE`)c#5IbVSBTrr5dkxYOU^~cHqH7O* z`O1^^9S!sC1bl{AZs4U1e!}eM?rqI6eqf4!z=Dtp&(&6_$J~|Fx!zv60wXUWw{-}D z6bTM^TtjcAUvp%rchn3*x)}3;XyLIdF>*4t`a~dp{mw&q?k(U_MuF2n#c_c9?%g}! zJc!ozYub@GK6Iyu!+hf*{Y%FUEjkOO%wi#UnxF*IBCO*EKLR2>TNnS%p&j$~Qvd%VPg$U0O2 z59|iQ0>x(vp@}A%VTd0JWGx=#LUp4KW}Jg~ql!VgDs-0}f+=aJX)^Nx*a^m>*)CNE zpsTE38{kR(7#}(!7L2|;$c)a7HuUcCgQyxmC<535ueG>b%On_?PykB(_LJgLDW+Y z0kVLb#)DuZPM&zwG9?!WQvU3aZ8NMy)&JbBumJ}-anBdYA*Po`9W$tCSSt6MM>9ln z1Evh$kG*b5r|}2iNsO3E>8P8yW}+9RRS(#j4f7IZioE7v{R=U-;m9=!8F0MCR?1J| z@wBUG7gBS%Ww0v=z752vG|@z?W8iJcP3i7-Q_R?`G(uc?9@(?ou4*0^-1=^%hAjrH zlgI9Rx2kS&bd0UQI2^=J1ryuNoTeyMuZBo~2rX{$&0&3K8zXAmF$NeL%|!198yIro z%+VY%6SzvuqeMcob4;IXV;w@wLe2 zW7WtRLxDE+_J2l?^-e(L3;MJm3Z0?XFO=|@ZKJl|zT0-AFbNd$KB5DB>)n5Jb#%gR zTY!t8oTer|*hWBKg^PPMCH=yWL4{JUDU8o6SL&Hd$#m?BL6nHt?DX{Hfs+El=nI&m zNX?4_yDzamBPNth(o5sPpQI+yR5V+(U|$f!LA{jM(<5O~&w*0qig?77mzRHbQdU+5 z8ivQRP0E8vjXUDi_8BVNq?TwK_@K=~mHW2VzhNHO1o3MZfqnt-{Z{}3j(m7psaZ<1 zhpw9bK{(Q?gH!$>J5z5d!r>$Ivw}r91(RcOECi#>S$2r%RS)Z^P^Y-E5lMKIY`80Y~ce z^mIVav8tJEu0`+{1A!dS8xU9Q?CrZY-0(?BN!^d*;|g9d5)2;k6?d)vr$vhbpt*wl zdu{aj;okTku;coh2Lj41*pGh@rx8TU@`jMT$3sM0fbW{|Bi1es_}A zkS{gK5Oi}&^^A`@+{d=pe~4mkS=Z8umZc}(P=qBZGNx!I+=CjsAMb*^d;kA^6Ze0; zhopr_b)pvbj~sonA|rkf6dNQ@gRBae!Lszpac=TicxO8FF2KeZbl5>iMsq zc>ph4X;0@!KZ0Gl*^a;tPoUS_2cGJ1paDqjyarTOd!Q%F=w5**PzmP)=8_#vA`6G$ zJ!o|`8F0Hs8@bWK)w_0V2ee&tK=mk4G*LoKL}Ujf?pO^kGYakJz~I(_=-eeU&mSn+ z=D^&oyS=^bY(l6a=YaH(AKWcK-R%-V8?K~z*x~*?c>TthY7<)(4FUQV?sq5aPdA^i zvm1bBCpIkrgyXH4NY zEt)^kjhH_GY>RC-ehD zCQuip0_7)2Q`4S%Jq0dK*HPtK(@zQ#7(+I0}B?Q)J4Bo0_{zz?sJ~@=1Nm< z34(i@qd(lQ81VHqhi?6*`DbPC(LeSR%$z`b#+R;=F=8|ErfK72XI)WlfZ@>K;220K zYY~nvz!Af=)gV*QDMJtl5cU(EAHYG1Oekmsp5AZ2Q&rAq&-4*LpA&GiT{XA538b}# zQc}Ts8XBKfvqc2TJvj|)6^8}};83*Cj~_mK{bt%`SOy@hH$de#@}|KNaHYp~c6TEe zaNapz(t?*t@qtsir8HOr^1}Fp6e)^e5y0ufCI9^oP!k}Cwtmm>|N4?X3890UHu3Th zxdc6)PMjYuoGt!Qq{qNM`Hh1M4(X)Bz=yx0=absmqpBJF(Oez3yecG0jCo+NSEMkd z!m0s>A8d}`7+3?-7tv4!sd4cjiAgP0@q2J$=HweW5;H8eET(ER{tcVi0+DuBEXp7q9W z-$R6C5#dnnxA}aj%N(NY_A=U9a=`bwABbeQLA@OqYC=F27g#%n?#(wO=I7G`>UPsk zX&ItL4!Bk7Aon6B{BXp@y`O?Gh>2wbl_6>Zm+Fx3790kiV{us-=>KKaIFhP}7Kiw; yVR3e_!xT`FBSsf&O+?85wNw57d^!4n{-{;m=`m8-sMuSs4bARu6Vl#}{|fbhZxD7mP}z$+?T zM2o;TBsYnV8mPb@Fsela@P9NHIbAmd1a!RT^5XAGz&-GyfV;GgySlTLyO-%_O9V$# zcNYg|cL!TDDo@MLZnn-&R9tMp-}h8D?(Qyv?Ck&R0ygK**6d+9)945YR0toX#5KG# z58J)K1~ZVSr;e!^%b^rjg?@r-8UqA|c@1+86Fn;W@5G3O^oLF z_^NOuFsNUUbrDZF$T7xY@E#MB5)EnASX|m(KR)ui70KnRk=jOOUmq0AjV?F4op9%K z=lC4&2=9=MabO^d;~-J9R=*QO0Dj23#z`PT5|=ZVg1!>R`AdxJBaRcwBO_%5Toa4? z|NNCr`1M*~4)=s`Qd^s_Obl_tt_xD0e#9WUgph@$Wwpf+9tHTcTPmCebp@zG4xLA7 ztF*G?wWv{>H>cSB2KEb`S}V+gf`a?|9Wm?muHYDA&XAp)z>XgCY%pxd!0)I&h6GeH zw@Dbf+MlwEfRxA1@4kzpsi~=smJLm=C;PCKkQ3_EoKMEF^oQYJ(Bp=XZTX8EZ zdL<>L?tySD@+j|)!oslr{{HnXfA|%r`|hM@vz{Es`I0)#2BDFbe(D?1+rwGCXQN6q(Jlob@vjVg(HIBaZfySL6RX7zDGjl`cv zg2D%iYvgwXf}NlHJl^g!LlYHfvMISNP!W+aOm-*p4E!%=gm0lqF_dDW+ni!I>xf)j zTsl=IFW^^4w6wHe+$KaC`PRayddZatF>(K9f$V2p#z1qbYHA6)sz`Yg35x&y#O^>z z^hz{BLak%Q*2oHI63kSdu~euMB(#vW|M*73jvDf<9~giTs-K)Run;O#+n9*|zkel> zsas=#CM_+km@O>8HXwA;c0M>UvGW_9J!amC82NhDkKKGA&hmFCn(*CjzNpRJvV zkuhSv!G4ZyTh>$_kFJBHZnNy%OH{qoW^al?b|l zoB}Wd^00MU+?nDiYU4Gup;u9scma@$qe77FsOU*|y&whiXXvmz!vn`5)c_?~@_7 z%le0B?+~Gm{tzVMccrSSnf%R7VTsT;>A3DFG~zx2mlhZamEPj70bQdIZhTKC+a(F- zzgZ2e|7ENHn~`#rizn7rwxH!yaDO%-OfU2}AU3K@jf#4$r>D0`W@zTxZ16oL#jJ4& zpFC=kLKK@gpvwBgh^x!LzN5*##R}>UM|~;L$Xg39P;`p_%PxFvm7RO0z7;`bY3Wx2 z0s?>&`mrSTW+=>*SVLP|T}`cfFo71IJZ_Sr^yDk;lF8$Q>B63itiYSNxRJc6YD3BU zrG|OX$I;-$?e&M@D!3uw(7yiu{k!gt#wK0H)YMeZ%GFkS<;5>C)XVU$$r;B?xdBhi zGv_55*hfYGX!iYw<8MyJNOBX`-#u^IbK%LBh`D}SzBlfUh-YBq=Zn7RqqVM-ygDgj z)+$Y|so|nm$sUy^GL&+3bo?QSclUCoNXqE?D@74*@nnTGG%2lxkR2=I>+kmrm#k-F zL3imfF&Ka)b#0Gj0CQpeY=Bb5T~5L{*H4qM5{1hr&^HpyTxXAa`>wE~Pd08!reS2( zyp5hQT9IrM1R8ps=7eO)d<;e6Y8jkqj#~WRC8?P0>$gFh4uP-f0&n`YJ);?X*s8{1Kz(k1KQeIo-?=w9ud$(jD#CAJ|69T7JQb>8GnY8Tz=`QZxu8rc zpiG(!QgRirvgS_mHup^heEn#SSk3@tVCG5S6P!4#TjYAVXN+$x^IKD>k<7J>XWN}0 zLsF{eis*ACm!_UdE#5E)1oG^X?(gP0`*+Sc10TWJ0e7|}BqRvG%F3XCrJ%)qiXd(2 z)I_uNt=pP?=hm8{C>p6o{|&FRLs6JIMXiK7A+hM?95f`s-JI;jM^vy%SZkC z1K>K7fKpot7(z%cgR^H_VJbt;>!X%|sOrF{fN|k-MSA7T!Ji+KyrBuQo4DGY0~{D6 z%havNakn1;hi z^q?0jkza6Jk7F(uw`1-Rbc{ZTN)PQ>MDI09|(YQEJ*0F=J~# zMYR&nCuH?$|Lm@<3m8;AxXGi9mxssY_FwAxX%BW%M#j?it>s8cwZj4zLL7w%N##@_ z>-Kt)Lu#x;kp)a53NN#ko(i@(bS>aI1Z_8B2fVL@FSUwrGuX5 z8FXi-)^>`%q75crs0jH@8!s&3=EhywamSo5J7A5eO5Gi*&)sp+V4v7*I1(}UuArkY zx==i&C#=vGm@a44_N#5ASdRO*uD{=My&8YAEb>}wa-{`KEh<%20c^+zmR1=b7`!Bodjcj57lpr8?o6Awo~ijfMUAi>L*DyK+>{&w@>@?@llX&_ z7GQYj_OaE8=s)W1#z}I|h~y&B`CkFYpS+*+YFs{~f>>Z3_sjXMsV}XeYuJHGRa~;W zgn+}9|FT4sS&K{sOgT|ZK_m6ZzG$LayO|QH@Pw97KiG@BhK-(JqUcV18t151rYng? zoL2ge#m;AH-w4uU-p^T@`@NnU%22P#cI|(g36$<5V5LP{b$&4T0TJ@5xWK&#Jyq7~ zWP+6g-q+3=2DojyB$ZF2uOto%-0lr2CH5HV+chl6*k$?vWC`7o}3C?nMK7 z^!<*|*kznV)oq@q$)7kZxX>1G$TqQ~Bhy%F@{HU(9`=|Px4524_6gXFprMSRqL+a8 zV!C8qU4PS)TgZ2MfIMad>0@8`<^x%zmLIT3maiI9TqVcxNnJ@y^i*P|qR9#M1`9gn zP(X&RUFe71$&xeUPMFFkmpt37{=5t-*Yr?om?C_0KU*0&bCzD=NR@q}ASH^%S;TH* z$bh|q?~^(r?cw2}=TD8%liSilk~%VDztgl|Qu@502zegn*42FnVu_Nu@#K`}(Hx_W2u)?-`-v1j( zyBBVCJeF}ule`<4r;=;Sb|0chF)0J_KDx_Qm&5D-P0mJ z$ssa7qOq?b`H4CN=D4Vca{Q}OS3jCl{?*cNiWvd+gS5G~U7-R?Xm6dxXWD(Jdf)~Q zb*xQ=T4Q$D)pcZbc4-ePzE8%haF7-~JFSslNCX(q%9#&#tGk+y@r4Bj9nq=t4L53Ws3m%S4fAy zdS+K|V}bUYo5yliLRwb8w1OH-G*PK(0;tF?AaE@ zu!b)MP5L&=t(p$RUT3PHw=y5->>zFiih-49O{CtmZcm$IWz*BFX^C&u;XOK?`Rj;fkwo2catgG5Z2CuSHt{5VW7 zM6Q|i%6g^E5p*(>BQRg4#q-&IT$53mS;U0L#!=qrM;^5x?Z(38t{bpaZZoQqR zFxE`q!a4P>=oMBPW)KUDwj*}N@XQ4?9u#3n`|jH*hQKV6WdJ3G#Fsl^ewys7rWx!| zflY$0Q+SA{lGN2|^0>CM`8pD&;WcdP8&K_k?binK?$}#b5&Z~T4e(zK4i0HA_0%NX zE25+$5B%KHlzUe=s87zx?IU@;$?32gR%lenl)%RWVn~|H51`6y7*t%Xvp;R7u5wP5 zX-_}f>zMcaB$hWJ{2VoKx@{{0+crpwJ=ay5;YoMI)GsGwr7tlK>QG5Y+su!I9Mhsg zwL=o>;Iym?-7jWVuz*S;%Gq2cbF0fRT2cgO9r_cD2w`8wq`7+v7b_I3*{{5m0R_}q zmHrGcg;chJwzf@zYZ$+UKn5@wt~=748UT5Yk@#kU;Of&F2%iF!RB>klbk%xPc} zG_K*1;Fx`q$_adGm=oxOwh~1nA6WYFE7^6wNxB4V_;>_6`wZw~_xQ}d z=f%P_j}PPE=TH)_($~QfxIWZ>(rD5R-|U9Q9{a)D%B5B>cCtzw;fPu)-UBQx*qF&f z`tB+&Yiu5EVd$+I^S}guwPYL~yk)XZ90x*{T77E>MX?b4m9S4jolr-n-KhHoA%Erl z($3`uciD|vM+;=gKDbn4C7RFuh|iu0Za=-eO0}E$Qxw*?5)Lzru{qG^zzGE__vb zbsce9a@uhYYEuXr-zCrLuCA9lu|6xTkNQa_vm9wu-S~^P&4<*(#=;Uw$F_SN=l`@j zN*hf**xb0{5X=2LjAO`oM_!52shYEw!1|4w-_$h1Fv*7Z;VmqzdosxecEdlro9F%k znSWGKv?d`1YP~s!i8c4pR%duhry%UnFC(v+x4L?oT%++4MQGJ|@D2Z-U6u7O$0G|^ z%i0%8bl=G&?CBwWa__2FJB6+~J%{NZ=ufCr=^c#zcov7&u-!d$6gJDO%zB(cuDEDm zkv|{5F=u7oIacZXDpNB~`TOFnUAl&!Rfde7;0OO|W;-(s3EV_VXLMm-Jn$7pSqn;b zJ7e|PG^J`IIohX(7lTY%*N$u+OUm?>aIkm2N1Gn`4UZp(5cUN0kH5~TIUo0}llB}^ z#bS)>vp~qfIgNubev;mP+B4io2b@c?iXKH;&axS0_MTFe1($1(QVfCEE z?s|ht?W+V&?XJEJhHK8*v|zJrcq&;8lnxZtUX5TOtG66d{9y_6K>6XtL0PFP z>dPO_TY8jbxmKk57`X2t-b&y9WIrJ`{V3Z|IuQ0k-zfNULP8RZ92+&r5S3LrlM4T? zACkdrm+m_M9%EFiR%vt8X-Y1Om*tCF)}a_Z1pG<;k>}pj6mERl&+OsnV*cx0wXYXc z)cFb3NRQ07?BH~{pz2PRJm+cN$@>`Z=DvBnZ|QAo{~MpF3N#BCcI9%fKg(jp$C$P7 zxd^kl`OF(06s`PnLvyUqVXD)uY38KB%X9e-_=O;^Hifg8vdR}cZ)@d?xVagzP%(qQ z4IP0qE2sC3G>x6!m~FQ?M>#BHE7%jpFDjqV%bMEFTl+bFUv(-umfkBqOc=vO!7%Tg z@ue4l&24V2{bK$aNrb|uInAShv<)ZgxoB8PVP*r6Vf6Fqa$==`g(^whoxX1oc4JOvgH)Y2DJiuHZ-EW&T~^Y?fxt z9ivStPqFiJdrSGs+*v^z)BA0EvyJm#q9Gw_`>tu0Q=6CPyRAY3t5D1+a6$G&lD$`+ ze)3@Jsp=He()gfMVdc=<@gFeBZ$SETP)EYU6uE?nNsVnM{+em~myrAZ*P37JOgrxs zS64jKt{W*M`5iB-nMnpCeCZS)HombEJ}yjaG6!R?t!flF)b-P5)jEvM#p>tYvF&3Q z55&smUpJ;XuJ^jle2NU`D>a9v{NkD&U;Io?MYA?XjNEpO?=d8F5EfAcm?jhG!5fw5 zuMGr@jAE~UdV9$`fp%s&Q=%C|$`{9J-hVn`{8+O^G<~Rf5S=dZ*NBja8kSCSwyX!$ z_iG{em$xH`=X^d;us;$v!cF>}*e9w;HXHlK?KXhI7p{|VcKZd&4kJI5(17Ul=Ho(AXyRZ5H_IX*Tz($ zpnSU9L=HIp+rQp2kiin~*47ZFB>Uj_ng~b>5hritmyx z-dFh|2=}%tqW1$VXO`F-mrDD$J7U^m8a;01O@}EBG?k6U5_^sFt~SiApmLJ%nUI-? zH@8+Rg@+h98SKn)`J^1?Hwd2Oj?m`#>rZn(`cv8()cnUM0_wua$|02ptjrnM7O;cs zS&jqilhfOQlajsYaOL>>KV^*CJ51SxixiKDh)@1Aa=M<(6mB~%EDi+f^Q z5W%Pa)Qld>Lh>*7+d(r(abgy)p%|JE?jU2yA;n~*S#qeVBX`bGX)SJC_rz@yO?(k|LB&qC&0=g;Qu9AQq|0=wLn84R8sO>l28Vx8)Jw<qbNU}FG@O8E3Mlcy((iika6?JWL?6l>JcQVTwC9)$!n`MC2CqH zSsTeb@QqKo6cpmsv-!j2&3G;5-L=zaR=vTu=-IYUh=O0|f4}&Mgf$}U{ZFf3*IK;m zj>1G+_tD=O-1oGrr6(GYvK+4si;}c%Vn|{qH#+w7W5SPC=`A{FJMFilZ@c8tZq;Y3 zo1StQG8xOZ+J<+UU8|_{pVX@D8b*1pa}x{W%48x_ip2#k=pG8q_I|hyz|xbg%J)Rt z;p-fq%^9;S^~Z}2(i^}rILNkKYnhR9+rHkFzPCTWbolJFVasOawqiNqrt1 zWnIBAklKy%sO~K%27z-wj>;aZEjx$%X;W@WT%%f@_!0#Tcx`V~%#U>5t_a_k!ub;( zme*U;WDi#kA_x*rSTGQcp0sB++%6UDs?>=yUe3HsQh-U2W;NU8My{dEPIlUDP8#qi zwQrA}N&Djk1pch4Ni^*VdqtU=k^8 zAObHXP1AcK)73+#J6wMvsp!}CLh^Isw6A6VA>f9}5TEtoi0D#vs_SO^^Y-m5QhcY| zPHLtQ6{UVs{K~ki1tuhF=XAK?1*r)SxheR(6l(X1%q4Eqd|&~beqf=sbsu5w(fvCG7n_+-Lyabr15*%dJzfE z1m&FM_|imoa=vUFm}r$H`uus-71{fNOn5a!$=M{`8WF!7KGd*>F*eadsw1}fD`6sm zNr6f5%m6%KFzv6^{jUQ%&q>VT9)GRM3dhBsSZoq&=37$oklhiNjE^V6w^Valv4P*k zAj-4yU=)b=qr`ofc;7G|#Gn;Y4w-Vr7X3mktzG3aK^-%nmqZ48?Bv z)~R@bxaVV^PF%f9S5h}63$j~JF8(^sa>m(ffz|v>fu=~cnT#O(*5x>9C_L)&sc7GL zqJuIlrQXL^;h!tA#Uj%XcBB1E$rh2|Zt@p3S-dh>qfv%3^cQb|ot5R@-vWfuOo60Y z_7)kDvsBXDnoO@slGmM%{ltw3OL58fM=*mJF~3Qfc&kl1>`*NC{kLyk3VYKO?T`m| zF?+62IGgVhldpzQ8U%uFCBqQKB1lHMSt)-j5OGcN_jjS8r}>_3oetqw?K^cOH@`SE zf9w5EzT$pm09^W5d7tVp@JL>I^NHPZymtd^{&+GSy!wE4|3KYwJw{zcB;R>XDz9M8 z1v)fPG2+8lrArs+qEgiwIGNZMn|S*waB33$^Mbzy9gk=kS=NJO)a&!KY7-vlO!w0D zE7lL`_#b9ZztlJ8iF3k2#Qw@CI2yNo%e%*UE}XZ@zXa@?-^|9ul;(CI|mcv=_kMU zy-6qNo|Rvdy}Hxf)-$|hRxHnhw-niiq8+5VZ|xWLc$31ntN#VPkC@E({{4GZVBoKq z@*h7!5)%`ND{Z7JV46x|+Cu-V>f39`%Fh@rFdcS0BsX@i)_XoFV5T4*P#5u2ogS$R zdlKrrY>;!JnoWGWf3=Rx2V|Php3xScKDYVX`8A>C;GP ziXcna1S4L)C%_t;5R2pYHeCtWRw7fpZQnV~Qdf>xUNcimVg8`Zi67+#0sY7=??S{# zN4Qd~`$9_POzb1wlg7b=ZEuu2%JW_z-{gDAEGNoP^TA{dvJBarCAPuF4q>>F_4t)- zLk=4a&Dzr86GPi6IU^b3nr}<265{&R?SkvC?2nS?G&wfb%059ubj=#Gydy7Z+6T*Y zYv-HY7>olSKos%eL`L4hU(ty?9}xs3ljo1X`nt}v+a->ztJ-vK)l#dZjIyJwnpus> z2a;yw=&cGKP;r~dzu$_fH?YZQr%bnExVK*kNoOD@b8dxlh;voajA0pYZ|tJ#e`xY| z(!8?qK$_SXi0UDkeRK?_4E+Gdnt(b2)e<%>VjBBaJ?7pyEYVss>a7o4B{4G$WVA1P zFUq|h3l1-5$|`p1>Ek8QB7K8WF{)4)p2dFJ5>r)Qi7s2Zw4asd2sx??KI}%?S!+Ig z>VAdYo#s<*Zi|9@y9ym?oc`5QChl@nx;`A;v6P407Vrh=e}c+9VpfUTHZp|lMtuHV zic+O%?ZVBNb3o7i?Ky(U*uQ_F7<}`Y07K-XWkdn@da2j+Rhef>_b3{E zN;iIjZ z$KKMzOz{)Mb?BX=z(C5FIJjHYbW1K|J~L>RIY|sh|C?L%moJ&y<7vYoOp^RQ7UFPt zhS;y_0DeVzM0iT*L*VD7A*lY85oy)p%&`8IBJrb=rjz4dwn6mZHFDUCoJXt__D`Lw zbDeK%Uj)=C#0F$iWPcRjt>GDdAE+*WUZq>NZvS=Fv^(S#7&s3*T&$1wJ85sUXQ$wh zSh>?PnIGDJtWwv2(1nKPf;N_-Mc&+B_M4*5eY-~>C9rhm7W-qeG98QXt-wnmu(C8SNm`O z91$fYLQ1A5u0C95LQd1blx5$o4 zg!YAmFcaGs`^VSW^u+#!i@fK^bRAkn!;?QuqmpOP*6urMj1M6k_oP`uCqGA~1(0LW z9fi&*(yI9_64EmLbJE3%>tk)Kjy;m)*M%~q(;?t4>p6$G^$6`w({3kBd@XJTAXpZs zq^LsKu8(Af z2yZFUa2F*gh;@2+(e zDn3n*)skQibQ!e9zGH`(GZLpcDXWKZ)CBD1`0XJ{swC`pV%-az=9aKv`TR^Q!B2h} ze<3B@{ujFYBB92Pmw1UoUPR954u*MFNx~Pepjo-T-3)=H3gqub=8p2;iG8sxxOL2_ z>l=rL6IpTE+OV-dx=|{02+%YPF#g0U9JKD=B|dcgU3-0O0egW?FPzkX(_Ifh*x3*2Sed%=O}WjzJ}djypmnRtwn$;2GPsumo%O*1El+`qn{r zo#xM4LaX|d6}ExLH_?Rz=OcWLXGTYlPmo>?K8tbQTt~M5QcNEP!%*c_$%u^#U}9>4Oh6 zLbhKBKuBD-I>~grsr&4wyrrQB!(zR0LuSE!m0m~wKhYkvp(0AE^^)azJ{F}dB6R}% zjl5Tipt{=(uafN3zq-}jU)fZrb~mz9`8eA+l9qmG&ZOx$mgEf#LSIy5iG*~5wYuY< z8j|-IFl_Xrm{3=`-`rNXw}sT0j>c)rHZcH)9C{vYi?OG`=_g46DQ2sJKl}3K@FLzK zoxk+ziDuH(9C>KENN{K6#{ArVz>V;l76S$edj7a-`&vP*$?4CgNMHU~CrZ92SCR02 zJ)MB5;=E?&#hw)0sU(ytJsygdnwXIQI4+;C{x~c{nObZL_Z$>5No|F^2COEybtYxJ z+Hjh+k}VKmxBJ=iGqw#eL4$nmA{_xTc9Ct3x~!428s(4a@jzNfvm~bEQFZ;w!~}Cp zt5$61O{tm%(2&cLFa5JkQARPAXwWow`JMw_U`u~^CPhq^6YHNe`rb|Mr*95&zkfJB2r_G3A#8pEE?Rc zmV{v<6q78o@+y-aUoZ*k+v;y|0(FhWJ@Uf^7_gu_smi80;zaUA4&%y}F#4hxW{bnhVg*1&rU_R0XGA(#hz&~<^|(t=uD;hb2AKLa0Shog z4cnF!c?Tox6!P>?y3uR~PGf%#&^WVs-d`;_tLy0v1M#FzlZ)x72glH$c8_loLJ!C3 z9cEhqd8P5d)|4&m#?}Q69CX-T+}M1E+q%PTT;RVPVJ>yuk{(|&_GPdEod>__Qiw73 z?Gx>5ZUIL{YU?=m%@|kdqf|LhWPO=YykVX1m?K3FI-+7m{E=RbngJ-XAp!du|DFo)$9Ef6(i?# zOn>g$JP@>$dvvDu{b06n*VHuUwBAAD>7j)0FTZC$Rt7)BP(*{h2!$$s*=|>)^8O%| zxA5rs!1sX%q1)9`96+`uYwN+|qLNnh^7K4cQwj0j5z;m%mjn z41`&ea1m>X)zXG`#TPIJqs%R%S7sa&_=Y?eo0`f(qerIi$$^xmF}dyfNDn61aHcCk zkT3jTMPr)h{I)|c4&=kpa#hXP-KgiX$g0CiqNUVhr`bpt9X9sE^bb$jwm-18m5M2$ z8;siO@OYS7qd83RU}AdM|CvsFO{la|jg(zG7_W4{TVXgQnAAA`0j0D(t9e6YwP7jm z9MTp6R`h)jThTqd@lMJJ1Zx&_lo4L`@pKNRbP?%@V68OT)cKZOHR|yk5@N<)89O)X zR_XH`YN20!*tTs%rqI`vA$jDVGNl`_r5!P)owB7{vQ=LqQ1HFZT|gL}Y&$&>YG7N2lHqdRT6q?KSytJKh-EWUM)_^I^EJbQQ_2&LPG> z`0h?@P0?O){thUcd6>j*yUnC{H0XK+HKMuF=on5-DH<&V^Xk7za5i+sSC;*fr}%RV zMDIU)w&+{E6@M(yTB)41IG-sp4sDI<`|+xbM5vGRt|KuS!p$cFi+6YP<8u$u4`FJ8BLNoJOM05#b?hP7Z0oltukFQ#uW36$u zI!4C*U#}QLD3or#R380gU?;ES1ms`g?4AanJ^^y%wyvDViz4q{`VS@z?enxoQzSY1 zu?032n&$L0$8*dqBU8CDqP`?Q*nHXC@s$o%71OLdD|EZ;dd%w8RIH!|ux@|z(Pd@` z*kJcRYCXJ$1Ip)*bA-<=n%Mo61^&C`R+=yrE1S20%0q#+ELL*NN2ZCd0zyG*&%btZ zV>+3KlyeE5S>wk;hER}}4|}3?2udzH{_MsK>K__rZ?<;g5~&0L8-n*bRa6w=czWgs zzFA<2GhWF{wqGmg_3)Xp?1Af^v)7k%F8p@~nLc)gV`btTr&2EeSTeejD^toxh;ej& zk1tc`jI%8g-8XVCIpN=7aVKHxa9({trqqO*`@lGl(t`$tYSlkGC>hgitt63Wpx-;y zn|$QkDL)}-8?&1or`6BfADJ{BGosnXsA&dvz0l;}kvkHPXm%x$hctA%+c_&U$Hk#< zdfps&l|zP>@)toXN8XrqMAdeJfVg6TleBh?Tu-gAk`se&9WEM-m?QqrT7G%V^dB$L zo9thOR@t7(!@cM-Os*5}zblq@{u!>Q);C`OiM-D{+;07-)Nc$$Nc-WUn+} zvSU}zJbMhv>q|5Q)KpE*U`qMIp7kMSp_ASp|0Klnk`3`MpnmyV^`+`;7m|RWh1?H_ z8v9}k&8v<;^&f8M>@^Fsb$_L3k$NCwh+)2#Rj^{~EmWef>|I%yiJKe$t{P=HMNI=6 zQf8R-Il>LgOA&e>_`0F3#3Anm?Q{tYpGe~Do8NmM_$iGLzm`%UXGU=~p3FB3W*-t-CQI)4(vwdzGw|QjI zAmsuU%M0X?}Mc5EcQh!LPI5 zq=JcJm)#10FVgm_1fRsy&J5ow()6YR2jXLkk#X9k>bhTpCaO%PF5-w@wrpEkvcBd7 zBqyFB5HPmL?V|tbU$b8Z*p_o$Z75XsChiMvi@yqr={#uBeG)!CK0kUsvW~t`E=QK^d!Oh2OS;vA z=N_rw;N3#YSaB54NAnYLw14A`8!FKnj_^yCnes`dXLa-ld*`$CAD>))|4)G}=1YlV z)#xR7^(LR?N3Po@svNT#^SIq}9?v5W6yC1rIf*~sO;?(O?;`>oY)1jjCmy-P{@<1@ zkQQ2j?a@3Sj|*X=q11+|D|&{|tbO(Qn-SNIzNSWAs{JI5)RBs2ya?OA>u5UnCn`^EIJ~ag_pbM_Dlwf(ntM;YIW$0kd#lj}S-B;M2R4>Mt3hso z$dV(zd=+nYvbdTT=3ykTd+3J6Um@|?;UUlnEFG`|%f+P?Rj)EjjXs21ePBRqp{h5qy_ z4&rV#Z{4Ph|8=`I(bVc}h8KD@$-{qSY|`a|AcHZw*)Nd)e+7+9QSC}cgN3<;klpNy=-~+hXToa zIllI5eeY1udf&K@k?6^PI!tc@R9dflODZ@q7z0U^(^%<}B=*hFP+R&+LMh%Q#pBb! zii2p^hYoy~b^tBlfM@r|xhsEQJlTJWYh|C1MVGTfap%w7*-@uXqkkpBc1^W1vZZSd| zP(zBxOBrcR>`5XksS(R7?h$+vA-Wi}CsG!$-ptb}yS2{p&hl3=(OA1Jn{}&jTCQ5J% z;6{-jlju#Wbr!!fJZutmnvAA#K5GXWSA9#_d!p6{#2z{6=;#1oPEAXze>j;1pAfwZ zVCIPVoXE`kV>VJd?=2DGk)_(21Bak6F4!+B1CS{aCB z$R2F-Isa8$yf;Jq)6k3Dc8(msvBB|zTEEc=1W+GNnE`iu{bEnI6YE#3`VGYDMam$6 z28vl}^&-ueiRA)|8XJcZLLcELe9uH;Xl5%&G-rYsWcR%qK)HI3JV~G5(crLEMyGBcK@H*t3OgAimg0!oBuoi>AB{BxPwyDgqn)N-S zYp{IE2UMl0n?LaZz1RV#hyebwha?4AzJE9gEc*E~6zC|2^Qv%vJmtiHtiW2NJW7($ zJulz-WO_gfHP9fxb3VmD3ydG_NSMj&o&-nLhm(RBJ7-H$ac zZuelKfF;cpkg>Y%6{G^VLd(xvE({9cv@a;wp9~B}0d|dvnR)+=v%qiw+jefHNXSu$ z=`bBQ1c3q3`?_cAEkMdG04F32IpEI{W&+-)CZ~_U;)eI9c4clf9Tc4<`dh-Tx$BIEy7r30AUs`nP=RxiE^k4!9y<^4sGn3BzV`c}^)u0rK3JH;%) znKXV^Gl?y|I-3Mei$Rqv^b(*%nZI!) z82^7oF9B{iF)K6@Tu0psw12bhd>okTZvm_?{Aj7s>&_c!AuoX0IW~x$_2MrB2@#$5 z`{n)lR(b$5s42&+5&)d@3SZ5eml=0v8$ax8FMBRIiimDk7`A$!^$|e?+~@&BSX9XC zI7ad(K&uvu|BV1kN+MGFU*H1V?JG-5%VqHSSoaGu_Rf2*BnB0ybH2dGd#v~a&(>!$ zFg4X}N{J6(lM`11SVT6R1L33qAmr2Az>w`7a^ipDhZZG=;~Q6Z(2IL*i`f!gaqtY{ z00ITx2}92XO9P;+2s+u?+Md<}4v=ZiIM6?S^U(3Q{n{vn-I$`<@nZMS{bgmKk}3ce zyZtm|i2FGNb#rrjEAaUpd;0}mZiyMM)AIb*meJ=Sy0)iBI6|3WYf82Gz|~D!dtZMn zDS&Cw-TnRhcb!=n_=zv@;lLQeW%(NL2iToY4<~*Hte0t+q`XMlW`Xdd#xD;j zfIGDWY60--&)X1dSmzVG6AWKkQ?~dOGHDC+B_(tLRL;Jl*rKm>yAe()vyz>YGePRy z_NUzZ3e-|DH8~lycJfTL76P7Nd)q1-U~`|rD4@rKULEJ;PAz-%6&-i`QsFG9SrUsL zW*>c^@8A^R&*fT`-=jgke*RCO{70n<%LV?`;esT< zjZ2KPI_mE#wM;eOCl18}v^fk0lgiZFMFDgL+@?Dz4XhXRE4E9UL;nXFdImHUWZG4| zqRQW*jdgPATm0)+E&!rv$K@~@{0EXUe{=<)?(PZcGT8c9)12=n`qF+JI+4@<-y{km z!Bc3_cK6X!sQ6iqXCC1508Z{1jOFzh3^P?VG*kizRKR~Ky7NmA-5R}YZ2E64z(#3? zkNK3ifhW50vKVD}`9YzCV1s=`;1Xdg{ac$7t;Vqd-+!k79{h%ouyBS*e2V8aI{Fk> z^Z_=IhC=-it-a%7c>Nf@H(x>h_)NdPJ@uO@&%0h^`g;_Ouy>n%hmI1@$KA%k?a~Q1 zOZji6=Pi&9u7u;0%Cei)>oEaP8w@&R;QmK?dUlpx@Ex@{kKa8YMTZ3ZM)-ghP?Gri zNDru)qi;pdIALON(4;2}(_ys@5)$%~BJlo9D*W9$RQ2hioNw4&!Hd)N%b)TL0Xhfq z@nQnn1NnbpP5tqD66q8enVHRiTdU<510NRvYzqG?pa^`r4!r(o@bF?P`>pzS$+(e} zzt2eOWJNyp^RqfuZ}jJgokXm3G(8AzX`*lgWJkxHHlK>FF5wSt0FJ%v(u0XmX4IYz ztO3s;97d1H#_z8{cz^;d!h98+4OVBHeao%`ui67B@>o&qHMd3i=cHXbSPHmrE$rw1d{YF*(J@`L%3d%7(n~tk>R@MQ z_IQ6Q{CKkkeuA$72q&<{P&jqmZin^~M8}IgrrAyv0v}VL8gN-^%xU}SV#4XaHB|Ys z@mH1+Ohdt2tUxZ)Wug4dj%8KxrgwZi(|;ni$alG+T)Km!qtHLHl>g>BAA!&)9ss@1 zFQ!z0361c<(vnU#j_jk$cMbrty*geQ0i4wB>UGBeU8=#~EHo$iQI+V*6n$-zJpxt(^}&HDE|7ywTE-nb(Z_#}hW6Y!1@0K#T4sTZD> zJNrl9-Q7ur%Q-o*EiBkIJ%qeMKlN=#%g7g9;dgKQy4i+-5C&zcJ~Y>JpdTOjhnGMr<2|6b8u$F_T;h0qE^ z8w8_H@B+-9CBf7q8i0j?6vl@tWzmPDbc>CW(h4(x#MIE#R0Hzjh}gnGbEN?e&dvV_ zA7QDTr@&HeQoArXIJo|m$VhJKPqKfcG2bu8t50c1NV!xaFS@E_RA_qS?Sbq~Z~%0O z0sWa!xV6;YMPu>+ez(llO9^DWJ{*$d<=~7$fn%FhqSiv-!#h-vfjIpRt(@Bj zC*j2L|Elb*!=ifP|4|eLK@bEaq-05@kxohJknV0N>6Y$TP^3{(8YHDVl&+OrVwJ9? zmcGO1_q+G`-uvA9$9*1oVBK@(oHH}$J@cM<#eZjWln3d$vK>3w-8U0`p#;+4xw=R{ zF8s_Ha5hb=z|00szh$>0uAIuN7{5FEAI>qYN&tBDyE(Oi-(fG9#6&mmw`G7~H#=EH zG!3*;l|8INDuU@4G98!ws1)OqyZYir=SGOGj&F>GBkUa`D8tfyIK#91o6@1kzr>f$ zH|#>Km!RL=DKvn7e^(?JHlXg?Glv7T2?u}76Al5lx1Udx#ukt$;y2tLejfDo6O5x0 zn;mhKPXbI-z;+{hlryv3np1u1H0lhi%t7qqMf?+N5A3yK^E#Hy)~R`Hch;R#iSA^l zJT7QI!x9}6<06<9OC^#H`WVT_yW6%N&F;ZqJbpEeONIR-^XWVwd*Bv3%mSJgx`ZBgbKuye3lmv1)Y+rirN0wOR?%98AY(|_ ztpGIpkYD4LPKU8FWUsr#w>kr|uh!k#8ZiCx@8R}4ZT5V+6Gv*J_NN7FnwBloFCAfY z%r4dT|3( zUBVXlg#b+}hsfDIu=;$yGnJLk@@&pM#~b-WN)M+?fyrG=t2;zey=(udmdO&|m^ zgn9!)aU)OzlaVoo=p2A)BZiZbz>>C3YyQm!Oc%)bEsP8^AJ&eNirtW z&|daHkv)0j`ek&?fU*0u=3Ts@6!K67FSoji$g_m*Q|c?IeaqZ|lm)WTFnR6A$|UYF z+Z+$umzb@st=bC-(r|Hickq#U{M(}}gic-tPV;A+h`M3d#lingSoJUvG!oL2SK2^R zul3*hFyn|Cc;wb{A+q;%AVae4I-vc+eJ|e-Y_rJ&jgdKbuVw=_c?E^$lR0{Ylmn2b zsB38SfOL0W*ohRwbIF^LS-XPn_3LEoZ0~SD$Uoyo1Sq-ZF_vheFA|=+Il#th>KC5_ zF6D!b0CwUxXWmt4Pg?kupl9`88;HGgNQ4ef|Dk6JPbnCMi~Kv>^$-Fxi=AH2L?0HT zmQJrcKO|Je+o+<7nYO(YeBHZ=X`m^@8IzI z+6Lql6sv=b_oxznnb>V<4wvH^t0LSh$yL6t@i3ty5TuFi7dcY3Lmgz0>O!pQtKB% z=EMv2o%A-D68j{yn6$y|Zy1heeD{JBMNLLir+IwdAbOMcMgNCb%f!SxDzD{xEk-A_ zzQ0);?i7%;Dhvj}TEg83etWZjOF-dbXRfR~lWmy%#k4;cyf5USexG-D*rlfVeGk%C zC2Lwadhq(ZObb%U<^A-0Z*2U}6QxP7tHb_Fru5^YR~!Z6ra~TZy}4?Mf4>S=<=~6; zRLF6gsuS8YHS8V*;8E4A@u(V_OL-y9V2=hzp-seS80+<7(KSr{y(@xG&%I~?PO;0+ zYnWOZk>}R36|{*{maZJ5!sShKF5qSm<*BB82@wO+<8N!M{?FdEgO%Cwjc;|-tbmh0 zO#Q=th(Mlpr~*nLPxB0n_h~D-q7?O~^w!Q5G2QMEI2XFo6?I?F(Pw# zm7nYm;l)&sC0fSay>^wk{MM}B zePo0?KX~56k=eFVHP^mUb>U(oICBoemeBrl@rvRiIO1n|bPt3wU7A9y{a$tJ}B z;N{~WbMLluqEkEplC4)?Klo2AMj&27#pu9x$6b*sZ@4LEmxu1DNM2rUQCcFY777P2 zU!OaxELFx+Z&Q@J@O>v;#DyMWO9&S;MM!3R&uV!<`Blf)%(?$ zNIxeNtG*G66B6d%PtFi=^$@3N^fbRzL-RJ7*V_O+g^WM&?S!$UwTxYU5_=f`{`8Xp z+M9qClh3FrX?B8v-&Jc>x;+(9uOZ0Rpk}JE4rsyiy5{WL_SV-42_-FOx0gfdA~ZDQ zg!T9{ZzA!fRBLl>q~qq^efwUZnO|pj?OwBFZ(pwcxM9iY%bZWaT=ZGJL^YGm_^S#H zjR#nem{1XNESgKM%k%5Qp)`5{LaQH%Ve8jEf8DMAWv*v3T95dRocZPKA6-+GIa>Yw zcb%p1`QatP{gnt=i*hCvyH@hOWN~pd30Cif-}fAwQ(3p4DAIYGDZCU)fJJPQcSXY- zMdO*W@6#p8+LVT{^SC%v@qIUN%FRkfY|m`j-D(jIbI^P4z3pJ&xqKF#pj zWLckwl_VZlWHKY+WyPPS>!3C~QCyz~>pR?wB$e%0EKeLvVG6l#?=JJ6*zx&6OlwWS z)3K-CDqheA@>Pyvwm>)B7b$ifNh)7OHX7T=qYQUyzOAXFhc;QImrBgZ(Y1DcYxugy zG1Nr)(Y$D$R7CiRv|4C$VS%1v&!nlMp0H+|N19h92^0b+ajQk#^DR|D?0(DLJ3L2F z+O3-{JdyN!gNPG{P=9J>5Y<8WYx&gd%e;dZG9txOT2fBlHQCd(4%Wl5I7i#5KCTt% zlVuUJ&(P1JJ<~h34oXlaO#Z4oC1>B(kOD#-u^=7eyglf*;Q;AoNXDM)pJ^lCrKMn$So54kF&3v z!;DL;6N~`t^Y{s-=<+6s91oW9b!;wQ@s!Q)wiFl9i@FA`e>wHMvv05y}7V@F$^|OW1&83 zmteJgf*^r#6JWtxE9?1^*>a4ZzTuzdfXXo=cD6>2b8a`=68w-HR-TJ(cMPLvN(f5F=W_=93r6qO zSX1$XcQu6ck!<@flV%!Qb!*1SyFtgKHiPnCm&&x@#>C*~8Y z`SkD@96zX-|06rR@FARC9s>{ObCz&f>EF8_>*o#}3>+Xec??L=7$d^-nHNxY3IUwt z%9K*|e#U*CUQ^8;3#P!#mciv5GW#9{VGq42Qi?t=0-JRUbxi0!sp*n9je?(_R5lZIxw(i{=+Anm=6KUD7LTyMMR_$F5oEGp|X6D?i4uU|J{{`Ihp zA4|d`<`c1>v3>^gHACGPi?02|OIYD#Ox&nJWb8VYJl|!)R;-~n*YHd6OH^4Z*6Fl) zm|R&{I=`7v!AUO3dM;IvMa)AisR-#-^icM2hH=+7>zvt=i5WCx_-iWN(@tVQ%F%{4 zm#n=&eq&wr+YjV9KC+_Jo*v<;+AFMJHhFlovUaf7eQ?q0jJW>l?|JBU(3!XDD|+s| zT%+XKd9g3WmwjJDLxbakMMptma{PxBZ8yj1v*5)Z#-B+Vr%k10@9Tp2h zK%K`EB($cvXNw(N62)>u2K1Ag+!E~O_sc&);N-^%148~c_0g1uPB1O<)YJA+YunHJ z8!fn@daHkP?!VIT!kdPO$&Nd%HG3s+NB2)A5#lx~9`=|s&b-f` zUMXxERMuWj-eA9(4bdhaObqh3-8wA$8hpSX(UgwBde{{ zq)WaH_f`V>v&N3vEFL1gt!L!iipx^ODr8#JujE7jZa!sM&>K05=fhC?&che{o2`pnJW{#Wde!|}%|@ggP7FEYw3p!a z3l1R9(V_ZIGV?b(T4pDlpWu_nhw$DDOrx5la;9hryD}8^g1pJ{v}NSIyl1`nQ7!Y- z5-%}~!Wz?YUt!4$c}P-(r_v?idX)I@J)f`Ac@ya;m!^VH;eKF-x=v|PK?q&^<>`Dv zyf>rX<<9FT@!eNiC;=MTQc78J)`hU|z1(UIa$ji+5n;zt<4C>VkFsz#Y0YM?c>JDM zKho03$S8i;>hUZCkjO06%)ABSP&KaBs9T5L=w~~BszX4kpO~FZrD=@8^R}UD<~Dp& z!L;jhme&4B)bS@KX(Kfvy_-x67Fz3KrPCM{?3I`CuBKNYbd9 zdFr;}bH$`o+eJ*r4YNnM-ofXbusvgYd!=~c(8^+hX(9#vU#LW0M)F+ zJ^uo?R~g+{yn_zQum>Ob>gGPyOU|ySX zOypjuVd1nC_N2?zrt`a%ghgYlyqYsydck6B4{@wvcN7?3mvrY=pB++E4*dzE5txTHh9w@@hqY+8QM=qE*Tr*vO9 zNzU;%Zi%_`&4L)UQOi$YE;w{AO77`BY*QrcW7Q2_=KH?C(AVF5%F^3 zaB8)`Ojy98vJayoX>0I5CU>uY%!8KD`re;^5VoB4zIKhD!SBej+iHy!PQ!9rO@c0O z{d8i^N;ygg@mq!BUn6r^JLU1REzuzmZP066tv-7huqBzE(Ie^!^GfA2BI>XBks-(R zhm6?z+jOxmQUVd78#YiH{w6YQ-sEB4!(K+@jEQI5_{Y_l0Z!&uSka5xL9e3tcQWlf z#{TRWaJp>e6?LqAy`C`s_DW`|iI#iT&`)iAU}Vj@ zLff7z&1kdSIets@|(1HGbt`_Sf*w;=1O0k71IU`_gcJOFaEU@o7 z`*q_^)t=Q;+j>MLesX^E?E2rhEJL2<9H!~d#sMX)WJUA8JMGf6i;LXi=VJ(3#mm5| zM1BnM*IZ}#_z|krk{Qi1qRnKy#Iw=<7^{N$mVK^OCcy0GAzym^5zll-&hH{5{&)wB6o7Huj-5o`PAcl-B6W z-VC`)RANZVVC{D@(nSXfU#6U9;WOlI?7rGeW><0s?gC!s2R&UQo4ow8APg0pb@DUh zZ%Mw1f5*!YlTI^UtcxabL;3U$$Tk{rs!iT;pmObJbZ(N_(_KyG?G5z&De|`NJyeXA zhwPG?g>PeAdsde24jSCGu9q#Wwh~2z3`^?KV&5)8GAm?LF$(pi~Kdjd||JNL~ z^2}4+c=aD5s@sCwZ-hQOfr$|l&3s$#AEMC3sMj=JpP~9-O9+K(_0gD?bf0qeO@INu9N4@6oWhnvEpYQmF+{1}AVThi0qZ(nd$ z;5=#T>GapbtFVMs|$`5nXLy`8Z7JOG-cqURg(r&THrnVe@n z)$#Z_I5hCWeU6p?Gd8lM2r1qR`8VT)_@Z7C<-nTPD*ksZbDzWa>e&v(rQxr5ijLCg zd(|@bymi0mvTZJ&H>B1(yDvDto7X=VUU|0@{$QvCT~kxeUbJJO5N4~QVm(zXFHGv~ z=R?LB5&vO~BkJKA*Q_r`Hm8gYFC9|+*NMS0Dw0T&S$$hOcVLya=@C9*XXEDG= zp{aru@8Dog)dT%Mhm2mkJTnGf&u0R#w97)v+bz|!aC?4sa7H^BxNtgG|4|!}#6kC3 zH~n(~&o8u;!2J`8E8Nac@^@VR2fN|DhlJluaM4`RHaIwrkEK;xBYI3XubgM&YI8_2 z1Jg%oYcdabW81bOdSY9%`;8Vyt|sgSPEPj+9?TTN2MJxJu&34F0XW&IBg5+johiI! zGK|^@3Zd#URE?$#OxS$HaiO_R=PmRAeBjx5r{ zc(3bM_|4gg#FBE1MX^0PyVBN7Pw%6J?p{z_RfKZy+g542GC6Yj#)RVipI88RWmEbp z?8(8^jY6XzlFw^7-B0Gcu+aEh$xeBu{HoAzIfsgmGgelLVtD^JwHC`5#>kAh8>AZ)tkTDvf(xA?7$`Tf{cW>`$2$I=#K=?(jZJ%#KaKq=) ze?!Y9F(a5@xZ~R8&nW7$RU`FT9fWlde)7?s@a3PEg0!Poc7A5=RW~AeFJ$oh-~sd6 zYXZSaoO(pF$w(tN?`MtGQ!h?3%$t_sAo+w*1G*3$!=!ZP6sH@Cp+n~-rLHr*o0plQ z6Sg11a(dpw>53)Mn2h-3i}%$G$w_yx=W(iIDH({1yZ%~?<$4m-3@S#O{+;m7{1FeC zbcy9HWBIui-62{_XQ8L|epiM08W!}Rv~tGs9ZpK4#nY%Y_!1-1PPNk!%{Ua73bT%d*GAPVV4kxgOEg$4 zpmc!!;6*NV;an1D(Vw1k?be&44aOo_78OeTO4sPGrwX@%(rQwdU-!}QO}*08rG!4J zw;g_ThKZ+-8YXfHj>$|kgIQBf1rZ@mdlU9QzxLn5nwpmLE0aT%Ux)=KHM`l7hHpo~ z2bq}e;q_-+pMEeN>ma&u&7>8#_^Zo=?oWP+eB8mSp3h|?e2uP&X*#QOTK04 z_SM%n9xG`HrBSM72iH&e45SWi)acu;nWH7Kmk;WOQYo20Psek2ZL-=uuv5H$ToVo^<}=?PooTC9>NyHkGQ zY^U_v$@MN&59!*E+YcJSH_*MdHRZuL^XQw$By5P~&X7Cw;^lt3SW}-|{l~;C_630( zYVQT-)QdWf-Qa*@vbGHQP5ngCmpe9rkLEbJgE&b;6Kza`#4q_!j*tF9rN3Q{F|eHf z-r%{EBsz&ai}G6;Fm2NfOdnwUib@Li-Y^*?SAw)~3?%U}n}yD-DnxzU$DldQBH&M{ zjBE^)`ObjyxmNh~L}OcSh@sOi*X!bu*-+oeJVwL#2GbOVnW`JAkSYV37cbulT?fO7mH$g9Sco@ zN3HqAcc&P15b8pe)UHrj<_yCZ3m>9rO@_jPPKtkaO@HDNtX=#ru-fOb#0ouo>D%Nb zfwk05=hI@unT^zd4!jaLbJRHuSZ?s{`}eBS->8?KkV`gx+ko~SemiTgmkbn>DO)s{ z(A{B&?F(DR-iMi7`zA!;7m3j5Kc>#GqM&|nk=2RNjIQnAT4B^pzZr&=hqy&QH|a{e z!#AyV20b}S1N5|W=h3|pvj<)Dxw=TBh7C!H!abVDAKv}(*)NDyj0>4~;i)w7h$x3= zZ_j2h#7oavsB^7j0~d!S{cxC-<3U@W%O;ke^M1jfcV^!@J!@R*KMF9&B2E@~#BW{s zVX{TM;$8FO&oNUk(Nk}fIAUfS%DmW*F;YL_iZN|oiQtWfQ11kzaJ=?mT@UkiX(>{? z8eN5YiqK6NU~*k~CC&#qxm&t_*+^Ze7Et$Ng~du1-wXMrCo6f}TyL>4B)p79ElR&Y zY9p*&ZhspeoMrvJDbkR0!@+?jsBB;9R)v*EbiRE8dl^!4aGJaJ)-#%5h;kl3q5jBwD9^dW)2!EV*rGZYFB za<2c2sqw~^Ne2>Ou7>O{e@mKevJ(CBB0N6lbw2NyY&?&;0e|opkCdalhlHfW@Sl6Z z`SurZ!%0GJl922UH_YL5rC3$On?})K*X3H+w*IfIIeH8SY9hms@tm%X1b7l&76w%n zq8l}Q4S`cMO_6&|-&m_FBGxC<=^(jiW|srMp8ImfW-jtwihd~;Ky$hxzw#hxL5k3v z!mg?IZg8-_cqlA`EOhlcq)3O?S`lV0fL}d;z97o}#p6rF?Ip@<%0CH*NTIEnE{v>k zn{8!*$M73ts*mWt@@{aMt^IvcDgN0smh(iz?^*uHZ`TJWO20|qnr=!G;f>>TR@>o$ zTe(cD20Ypk`;sa@R{}4r+SegGm(skj*2>5+jSyYBXy%J2v1ugdXH?tciYq-Z)>>cFfa1l*|jaIgaOP z?+YZ#OEV;%-sx#d%JcN2#WIi6!EGwqKS>RATl%&bd87)FQ<{0u)J4nOmvUkgMtE<< zK6dX%H$BGfzxPna_>r~<_Bkvj!y zK1^ z22oszr(Qv**`jG|mY-d%q?-!tGsxl)o)X8~#(Whgp4#x#&{R}pzI^bjK4vhK=klJW z0j4>7_~ZQ`IoL)*-0{abV$9omQ@pi_we!=3N9y=CE3HqHzCZ`cN#ZO|FyHEM&?o;M zMI3!Wku5;PPR)$N2aUSYA2qa4_-Dw9ZrhP7K%z$(_ov-qI_}$5={%mpWd6vuv@pX^ z&->qOu^^WJ8uFZIH_1*JXqKmqBZDcYeZTqS3{YT09(W;GQa`k!{1HSaX+py*rw1V< zo@(%at19s9>GL_<2znY-T8KnIt;v0As*=C`+nzNmm#$=AsDe1@$q*1R{IR3Wr~Bnqm(BzV_z3&J1N(;a3|r`=nG8-ra4; z4(Ga`+Ef8KdeQi*vv1>iFF`$}=y0GvV6eKk(#ti4*w9zBsVFy6UMHNn38CUcZ_>AMRjFvIs^dj04y zMbq&irq_Xb1osI~x|F=8Ox^T^*%v%S6>d>jd{--yH_nqlRbngDMBz#ny8klWhQZ>E z;p49!=F2?ydhsKZVOfWB)fo01piZ9AbJP&`aNSV6Qh`y|!eS;u9g3upJP-(u|>f2-Zyi8GOV^aBxh@zY*#`CZ)2`%k9+NPK*6O%YeOxcv20vlpfZKYJ(~@j(8+ zQ~use#hcdm)$>`yrH_k$d(F72Oyn6rCWOcphTb&vKWMi18R#jK$~M&M`Ic@qv(IGR zU4gwc$2dW#@=M+#oi)u?U{JA+{xzFO5aN$$dL!Q(uv@EM+pladv9T>X|9r^gN4Or6 z(jO_9fMiolt;?-4)I+v0VKf*j7AB4JptT(KkuLz~o|iBcK-P}{e_Gz7SaBWLl2G?aaJT9+~;{~Wh_6Fa4q z95gs9$CAbqt-z4~T8Qs6zXH30biV*a>l-5($Zfqdm)PYN-KiGu;Z5iBdg{{kU38u@ zI9a5ud^9H~7f(F2dzCcp`CXdRy~>*3t1o+UjT_UDXu@f_5l5~kMl0P`@h+jGMYCIYd@&=rmfx$u3|K+Ih z8W2Nnc}GRgC;)nTZS0%m9XTN9ddC{TSNCEsJsMm6ynm1-Xg>=qiSFO-U3=I7i-9Q& zSkr84JZpH{TUv7C&Xy3}z1zET8d<=+Q8ypc{TE9Y{_kK6L3lzOF@jc!SEEKF(kZX? z0cSly$x_3PB5!gvH8V@fNJe74^LD9_WPxXegOsT7@1t!>se+PUGD5~0+#jyom@VCR zKTS8N=}itb8_z5|`*!a!&%CEwvZEU@gN&GgKL`SeX|rd*=Vp_84 zD`}Ax%as+(3QI{$(Lp&u=ALWY=Sur5QhwhjAicB>K3M_8n z=++A^)(VK!@-Ng1EP(&66gMa>-7~TIG|*ocPN!I2&UV-5%j6P2 z(MBhdvO+Z2-c2xGKAgiRl9-(}oID@wAcG(cQKXZ7QB`ec0k}*Mx_ycwzzl%WqQ8uH z{qO;WNLJ}`H0Mf_RaX9Yyg7+Oy>xC}?{i|ORcVC#CVFsq|I5gMz6C=_)tDlUmhPCK zbf*PQ*>+>=?00-~VnRfC@OFnvKf?PuG?$4^M+y83;$9YcquEQCIl0#RSIfmqxKa3( zas%JSCM)Wtith*Y!wXSYu-hcA;$DK)Q-FEp0z-KfXjfGhe5! z+3P69svYhs;6Y10Gl%-T(F}8HZ$MtjUfl`1K4X^J`~`S?6>O1^&c&bd)F=ez{pkHd z2d?KG_s5z;TJSvchL=Ye#X?p6h+9iG9(kk&X^R>DrB@?*`Xwuo?cq|yuvK0eOQJ@3 zOAAHDFtG=D!@QEYIjybj2P?};Q|>6)e9?nJ1qmob>p6@@vs^KL zF7L+T&L~bCsEuBkq@1eAknOYe^3H(=nEL@%BlG`Wc?WbfH9$UdXjtrHZCH>1owB&N z7`&fG^I%etX5R8f_EbV?Ql(#7kO4%A~x7u}&!}my#w8mV^ z6V2C%xEE|SxP5^LS>(ZZ?Pb`gX*;NZAutpAZ9Vy{QR*hQDR0c{{&VHXT){X?v)KYw!=9&!hG@w#y8cxO)<@ zIp1)gdi0{klFk^Jk~xt{ozVXF&>t-BHi)8)B1pGAK*C2 zNs0ruMDrRh+?36ZV_M>EE-{VD#UYhHJ@ZwJxMUAw{M6w)?Wg!HsyN$@7#fX-4?(W2 z>b5OFdoU)c5CDi9@BdTkmp*hDRPCmUWDDMO#JJ~U*5~NOCMf#@0 zN~c{Bk?_+Joi1)8>jw8}z61__EQ9*Mk0T7N_GX#hj~Q%M1M+ksVX27hsH-TI<%0b; zGu(}v^w1P-0*M3(CSyPs{Qx5SMqWbW#a8K0u(Rh|YP?RtP~$vE>bCXszDfK;SDaMy z!{>@#b+4B0u0GU5_n6wpliwZR$N)!;w#YZpJ=tDC0^pK}AsNWEmYxtF?nuTO;j7H?Wo^#_% zan$GJ`vqHN-F?n9+o1yrIer>b)6>;nhi1UgqYr?KQSd|XnPjq_`1adP#s@Nx4l?!=8@@A!excA?>n* z`4lobVNy^Ep_+i2-ro? ztSlwKUL+&C_`3iKL<3%)et(&bO<@&=rqV_e=)vmbZuCea_LlRs7r)vB4R2%nO+E&`Qbj34rB_zMf``FB|bg|*!V z_};NMI2l0ISkM3&z!KQQSvT9SGw5ZfRha$7Yr!Z|FdfgiELuK$@iw~})D5$wTsT@( z`hfOErM4ytW)3<3^J$=FN&dbpl)7wSC?4yb~xA?PK;@}ENLf?8i5q`}aIZg9Z*#c|X% ztbyj^UCG1}Fa1H7R{jvLgVFr{$qnK2-zGE2o6X7pYF8RWE6FfAs05_P@@TUrF%_4v zaxX^|mnMGzPb(k9J`LH^D8I$0)x!RyPug)`x6|fm_};tg!D%yZz?W25-F;nODr3&5 zZ^cR3Uw=7qY7c*O_eyYuzT?tRCF0CD*|=0aB)h}^v4r%L-R#XKz5%T&UC5J&Ltkis zX~cI0hxPLK54K(}=Fx<3qhm5-k#W3_#bHmz!IjBml)n(r59?51Zi6L4#B`$Mf_**C zJlW}zmc-Re&h@VsV`!q>V6t=sgZMJhEm9CDj%ogY!vEVxHBC*Cc}yi)S(Ax;IqScQ+ERqvQ7s=C27P1Z*ehfW*T%b;Mp0m@3Xz zGLa5kZ?PllC@Fs!kB?{B>w_93h_ZM@D{TaU%7%0Fftmh6=MDb>V3S|2Rar}&G7DO? zW6V@HOMt(^<=ZbTmo>qWbk>-g72sDAO)QajloW)lD^n9{+#VnT=5M4p;mRv=chnko z_5@%*fE*3HIePEG9D0{UWDEntR+_M|FhE@W3BS01&`0jX;j$_PXu>+c?W+Bh9>l^v z4u`ore(fcX#o>&;6FsnFE> z>^lHt5f#7ln^s`=Jf$LbJ#~A&)apA87_!rj4W%HKr~#t5X2ZNcZ}Y!(ppF3?3-S_9 ze^(2wdNfZjEEt>s*VB^j71hVs*i)^(XQ!SGAb?Dd=e;d0QqJ1icl^HJe%sar%vE{B z#NfBHDuEa3?!bt$q@-jEsBcW)Nd>C_ocQ(zxGjt0nL2+h)^or$f9+zn4k5XVumFsx zQ?7MKs0MS|`35Jk3`6onKv~TKjFk_ruGKm$EI^(EP_n_LF^GUL1SgpI(&RXRB+T-+ zl>Zo@!5VP*ABQ&So|1>m1sSXdl;cE>}SFJMzOo30LnJW$|eSz`x zUFUKKswG>1el`jotnvI`#x&^EC18YCuWUWls{`UJ@Qd7%l8c1ED@jVRfR^-(j8f67 zgYN4&lDO^&yi&mGv=bK(614pFDPR`{^7E;(GL~rzu43K{C7_yNJv}$4=MIKSJ0qiP zpIOT<#YHMPdy}FA+k!p_cYiCN?YR_N-2dM8*Dn@$2*6vrN&f#4ZvLOa=nBmo+@~K< zH^4jJ0S*%X_L}$iim2r1MBW;~t|N%f@AX}u!AC0rIXZC^kWl+?t}ic(-xA1;LSgQ= zAk?E(1Ni~qc@0Eh{-O@ogs+b$(HadZjO2dMLys{*a~Xq>{X$+|{_67|xX(5#Xrz08 z8l0%Xuy~iNE3mhI>ZkIJ1<2+zYi;_Z$h%@8pxBiYA0QL~oZrFB2?JD^t&`I_0B~9Z zX@i}m){Fv$FUW4{8~o&A7-6J5oqupk#U%+a7K{WqoezkCry$1s$Fl}80*IUdftY7N zK_*0^Z}=e^8d{8;l(+`aw|Nc3R?yB4a4`OfRR0zQ{9|VPF7M0x8O%Cpnrgcg+-#S1~vfh<3K_Y-~rcUq04%9v-ez0s{Z10?5VPULYa|L4<|Hilq)#F!IjaTlDca zLf;%5&1k(H(YQxQNJy^uF^mtFz@#L<*g7`Gpn1iZXRZzozws%T_xoTLYe{q2a_w(q z20tHivT)F^ctNEf!y09zEaadkMkq~)+kbC>GtKrJfiZco2x+ake)<(BHpO-N$T$ zDAu=q`?luoNIJF^4F_VKhZZep;i>g2-0u0>@<#ePkDTU&Nf(UXJAXi6?x;kR192e~e}*dE|0D=W92 zPG~logT$QXdae%Im)BDt@f!c0p6+eGMGGwX?(nx^;0Nfdbmsk0L|~^=ZA22e@XdUgL16#95D|i!OLfYFnJaii#3bQ~OheY#PziW)9WRKbCr z&7YHPqN=r3=8cVw-!<{Zkjbk2L?&gIssSb8DhJ^ga=AqE|1MMT**qE5q-YrB3fcW5 zTjKH`o2rKqBUr&2JEnn@&o|L1m+#NW3pz7Ci71Qt))?`LFeOhH4V`u6P;sVord z!9&NGd_6NWO`tvH6RpDwG$)w;=h_H-SLzjhM+zB;b!qJi=HLbNoqrE^+cu3uHU95H z6C}__R+4L?>ar+4S`{QBeeX=}3l%F_(5(&yJ4tQ5RCFzEYl8ASwJ4FY@qJsZkf|#P z13+&2Mn>SkKsoURR~*z>4jJ@I^Jnt+$@AsbAE1e1UH3kgi@J_9>D9g}PfkgxwI5?n zOic8?+=3}t6oLwE6bc-j97d9;d(t=aNc?8KN;)emC81g}yw3d$r$>;D;ng95_S1^W zSM@P3Eq%hLr;VuvEQgiIWdF__lSClE^hm;yRNVR}4pA!`nUO=tH#^hie6Q*VK8|FF z8|v$KR#>!f3kaZU$K-7K;+Yf#Qh+9QCt>fx>W6$;Nxt_U!oGc@j){pWE-7Ib7f-o3 zLE$(=iMcEdpKeWJSIs&a85s$B?Jwkh({*6~LC-;NY3pk7jw|H zTc!@zjHMs{nA{bgSO&?*l9H#R*|H3$?&=Vo0{Z!OnwSRKs9M^H5e#?|rVFd8`kZ1F zm^Sayo^^AD5w;&?!~&3bakYG>qoJXpHw2)QTla*2+L3eAF>Z4s6IOKer|NYm=4jDt zc?3vIyX;W55y?;6OPLI$aLB5LVxhiR3niR1Ut7P&j96hSixPe!3Fgwxwq0uV(aMtg z3Sd3k|5!aJS(7+-e4lmN5l|}+?S&?2J2|Mkvc^zgywKo2mY_^J;kUp4{OKP~6Hb#4 zk~4(qpj9uxEc9ksJ@r7+}wnI{rVNyLhB&$p-x&VygzEP+}f*A z$-HEBz=f@5){)P&CX6fFJLLTQocT&qLxY=_x1g*n?(bjQAoyOD-OfVh2QtILY?@!a zy%Eg>H^-V$jHLLQ-}qLi&0LVu%NOzTmInV8$T?jW!L>xmE-CPUFh`o2N_iC!AtwL{ ztJ~w0Tka&0MS5941lgOp@2#=CW=hWo_uM?HN*-a+@7g(U}{7)yUM~{G`)6@Hj;YMFN zGFB|5Me~4>{5(%Sv`pyU`{^>%!tdX)1>M%b)O;pb&lMD~58xO}wLwk}YLViT&nyIQ zARyw@k+%mnaLWUWnH{u5R^G+UV=(<+y6Qc`FZOLsy|14oN-qHCy!eE`c@y!Asgt9r zJI(w-p2A`VMBkTbyr?+JY19W4-grF7+XN)|e1psKe!xP2m7uzIp+a_*_h|TY5`^n! z7Lh8TJB~%>rN-d=98F59iiHY`($vq(zuue5jP0ouyuOfDj}qyh&#d)u8okdBrj8At zo12SzkcgUoN*()4ppuJ;h#v9I%UWn#NCoPT*J~D+DYd+Y!3_5I=hoCbTT@x`b3R6r z0i$fogv@hHGp5o7#iTT+5aZ19E{jZTVr zDvcx1vSyaaLh4bj4X2l3DKC{W{WNfHfiWrU_kDH#{z#*@-PHa4uW7@E`GO$*0FyIN zZu`e})mb1#*|m)JMU+>q)X1^cJ1Qc2hnlVZee zSV)+f4Sg%kUo@jMqkZ(Q^hP)@FyJ2s2h;rJ@d7VW#N3u*Y#8?+U{u2@OwdW=79EAt zBiXaZzfy}`zLDS02vgG>-Q~axn_;DnCS(4TM-=n_`A&bv34V24c~_{+qD^UBeA(K! z-}8pJZ%qqcX5m?EG+z-lXH-eLb+IvPM{EtV>n(o79~x?D(0nQG&Q07r1k5*im|QrL+jit|5!CZN^Wv|0^8aSP=zlT-XxGTf_S^KhIO5yOnfA+d zJ7q)u%yRqiXGa&7Q%`;8B0MeqFWQH z#cWchT%!6_YEfPKNZ2;PUcQ;MSp5ti(@2v9bhbPaH2TICT&M4l&zeXcUXZ05`nYpG zIW!)USurA+Tc6iADNIrBu0sW;$ajU@;_e1fzFim}w^btfGMmdKIbG(wSs;loC?@pk zzdFcZDt+$qQ8RGD4q_J|Ocy;Je-NmZO^&{<=r^R~iJ{n>cmPcI`qfCA@w$^n=}^dIKrekKo3;%~drzrzgkeEq%2Eh(**Ea|Kv z6#HYV&=C^@v{_CdQV_f~pdD*J_JatU_va?7sD5$4u~n59)9@9EEfvPMKiiO`Frmtq z%l`CPA7<_s$!GZ|!2vLO*Ou>*px>O}JdZ;rZ&YA^6Eg@78|ywZvS5{$Z9|b7^3|cs zqOl%KP*&ATNgDH_l!KqJJ@{H6z4Dbs(E*$9R^T`0R(JfJmup>7^z|r8i5Wm7*72ND zgX(DPJsm}=2Y!~J?LjmYTpdo8UUX@{vtSTb`GOR3y7HCH0PnHFWC<;O--C-}0!Bi8 zL7o^X_SGrmXE~g2a1tSotAIh($PeQ?x!gA3u`E1Zi9Oi{oF}2#?`No1ORWcsWrszc(>(dA2nJrNH>yQf>$DN8W4Aw z6~_IW>i$_-C`>@V(kSar&>v>RlqUFbo5=Gl+hL_7a~#fMT@_M$Fh2JZRbn;gEbV%h z9|OWuRiskmk`G5wca_SA^k|(AkT#w!x2E`!+3o}jW0@yqOk82(LE1&f3zJQHpP0@z z-wo?&f+C)`IikgtgV$L)Rf8fz@4`~48u#5&tBLa?&QMELS5)hX`2#vz1?!!EFp>{H z>cH017sksj{^A14VW~xh;4U$}-|E$N-mc_%`^m~hxa%=x zHKqp3XB7uODv7@ZD&e{g?Yh-TF1EJr^n6~jBF;vD+uqf8u9hDndAB{QXkBh@#)I9{hBRu6SmQx)eF`e{U^9@f1c3Fx5*GCDaeW6 zXe)|PIg4jXV?{2#2-4X#x})rik1&;w=sHlEt5e81IYs_9WpGJ;S?w_`K{4l&GQk_F zY$3I09kX>(B`uKAQG=30e%Fn!-JKwm`>K7)$+n$vbI<5o{oSrXN_NZSV^qn@oVR0< zM=7LDP17{W`ra#_WKBNlF9eJf-jbb#^^XTdRitJPBa>8)ax%z{_d-Ne`pm8kjPnx7 zu_fkn_XRT-@$E6C^7dznH$u;`Jw7KA8M=g3*Rt&lGQZ5e9J0EFCTFQS_;|R<6}-XU z#1r>*$iL-!Jig^2<8LEJl>Mg@Ub(x`#4^%F`*=huh>n@fy(O;+kG>>#znDJ$^2}~g z=v}c9sud4SpY?@u>aFQ``F8*IDc$z2H1^M<(n*=Ku^T=$h^A^GWm z{)W!_#aX(%7CezDDHtrYVKl-2D5HQ*54PMbVLByGVHDn47lqgP>*~DPzL} zStnWV5BZ&BJ564lR1{?@%!`dVvM)%kD;Z82-?-N-D0JcH5$dB~9=bkjWWr%76%T>p zf)k8_RO~{bo_)TjYEe4dCcQ2<&9YX!p$@0xXgru&hBmIWfE5Si!38P!vm^-ku7@^*^z9aI%hfu{t}F z=+`cNu16Iq#XcZKxHr?{=E88;*wX>7G83~&sgcS*0H5RZ#GqA z-}T;fnCl<3wopGPc4h$_1rscDc# zB?rV-B*|bcHI+iiA>=ESad@^Vr0ri5}Br}ig+|k0!I=9@{U3nxHoEde* zbs9nn0y3H_1KKqgXSO{iCpHS3MwB%(VgciMgp_8ad|S+{H0g3fjDAmcY{Wx~mdXCL zW8zl^SOOcDX!d(Lj#Q~9+1x?s7$1lHK)gKC2pyQs#yRKPc-?!5i)}z0y1(cc@W({l z54AYV&T=}ZhWts2xMh!wIgX5Rj;J{ZjXB1PxcPdyhwsXPz|TfMMg-4SO92-wN3qA!RNQ+_S#^9}EfmVR86 z7=?}4XIdwAo?h^qx-UJnXtzrO-uHyl9c0x)#QT2vd4pz&pJUF-~}#wX#|p?}3F@`ni_-r%;~O4KqLzPMU6wc54sF}dM^IdWdLLnzDip~zpn zcp>DuYjWTVgn4oRzdK=FGm(^T%_iD;&jw$vO}fD> zZv@%9uh)(Iv1j4z<;Sbgi8OX?Ud&?lvMedbO)*nY=-hL5vHRULH37|-FPGb2s?l%w zu@lqqsKD9mWMBE(DdILc*3iH}QC*!73-Hfz$lgE1VfY&r?wUKZQ?*&(FO5$eB8nlq zk(6r?pO~DK^f@l{g4fg}o}PMGSs4@elB@7VbsRN4Nf-S<{pisnMp@rvplG_nVn|Z} z{x_i}Iv7lcn6Dx}^2>j%ppUTByt)rfe|r^vmUEKzjbvM7xLgc6JCr;ex(bOR#>3H- zMN|C?rU0-<4y7ceq@Z?&Vmi0&dvl`JJR8W4N`i|Zd-C;J%sGY_@hOk69?_0+yZqs8 z54$20w6wb6vSA9kPXGlbq5;_gA;DX39w8$e^<^kIX9$8<{%ik3Q60G4ti|*_Dz6 zqL1|a)Zo>oPWS&bYZv8miPUAz4~;~FD=HT^HoaAH&}ahvD6)d~-IU}IA!h4LQf|NN?WR7uD^|5Yp)i}1@diD0nJ^Lo+lam?z@r|qoU z^f|6*#zorlKL!&0QLNoXk8%ZWVt6iZ1w z<;rjCEI(E+e=H5ETuSA;SAjmp2d0CDB(Uc+E*@T-94={~&ACv%jl0=$F42;ifFlYb z7u8>U=)I0|UE`p|Xq#M8#AP9uF;T2Qx5DR5u~#SUo$`0EOFNWy>Fc=>xv@?9Enw>Q zr-s^pJv+ZGcaOpl13WI*^4lrdZ=U~aWYRfRlHF~-D}L=XayVykh@Ka`;&R=y3Cy7O zk@(!6JWVI9>k#zNFkEuC>g=t=v7G;o{0f6S+T|hw8<;KKeCYZ+X5XjYvQ0>hg#&KL_)Nx1H<$HB!V1Ov zt_wwABmiHux3Ma+V~7>xi9@Fe~*a_F&11JMtF?fce_-`0=wU5iCydmkz4=AV`Hj z2{W(3Ts4e3J~=UMaAty_ zM$s>QdVX#0Z5t~Ghh|u>y`T}tgwTrQwD}B;jG$jih6xO3^^W;8SATfA(xu*bos!2p zBlxhcvhsh%1Xh3ud8hCEYF@(-8>!2S6w1m6fj$vw*h(HFqBD9H7K=7l1qpJ4pTw6W zHpQRv@Z=R1;(lCvlQuS6>B}$>;LX6P9o94and-d+ognz2?aEnjkj;PmhQiIhbWWJ7 z+do9HxsfBdL2|~DGV9zVD-v|I{TtZLBOWl|`AgB!(d{lYB>_Re_z#uvX)7d!(!-=O zkbu#Tq3(IWlN}yXd|C9m2NoaxE0(6#yW0FQox4y0!VHmfsc0eJsttF7!y+iKACEMt z3B8rdykvAlYYOrWNdC9{$OKPJKJJyajg8H~zyRUdJn3u`1f`~@NM-adL@)BF*{pFU;iP% zXgDr33L%t_=jz^50(ID=r8DHOSIP1~IyujTg?YHSbBl|)%bx6;xA{x*@bLUaq5K-A zrly2~ZvCHVr}tc6ocyS)WH}E{W}Rzr$#Gxlz(&UKR_MvyoEjdS!Tm5#!^6X47M)+l zGfL(I)EkcuOgL3}XENpyZ}N*$iTo{dlc<-aE}uslAiHhS4SuQ$^QHAlUqPl9A*@T++rB_d~0hf zQ^sea#nRMN-PgBSK6a|I^V>zA{H@T8RZzf3O<{?=+YFL$m^mOeKFiirix$strzn*K z=8>&Q7!a*r2Us5<{z!bDS@mv||5aU7{f8Mq0E6QNsy~X0tpU0;4@8Xx)6F@P3%o(k zw4DA8n%_%NS>5Fq{rU4pL6n0+_%K=V&@ zGW&0Du9S?}u_@R`{=ogjof|T)ul?g$Fod7Ks1yI=TfBPQ-B;Wa#ZqVQo+>ZwYDk>}t1DLBS zKa4Y|{n{Pt{gMp>kw5T4fziKr0q&>y+rIAsM9L!|fT{3m_uTxQr=*oFla`)NZ(wK` zYSH>y8x&67rTQNVnBqU|Fhv(Yb^N1=|KH5%9rmCN2K{vZs1xWPOI=w9T%l+k@;?B` Cq>wxS literal 0 HcmV?d00001 diff --git a/doc/guide/images_scripts/BS_GF_up_2_rotated_diag.png b/doc/guide/images_scripts/BS_GF_up_2_rotated_diag.png new file mode 100644 index 0000000000000000000000000000000000000000..4b676f10444ffafd6918cd03e6ca979b39395b42 GIT binary patch literal 9702 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 G2L2!ZAr{{N literal 0 HcmV?d00001 diff --git a/doc/guide/images_scripts/BS_GFsumk.png b/doc/guide/images_scripts/BS_GFsumk.png new file mode 100644 index 0000000000000000000000000000000000000000..3dd578016d1518a50ef2e6dda4a5cbed77562820 GIT binary patch literal 45208 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 =k zyze)j!RFi*mjgU+j2C!R%mKxy4<;qn3!7l5$PdW7y0ddB_}h7M^75)xj<}plTHowq zF+wP|paX9q+p3X=1qB>)Fcrm(xEMkN&O>-!kjw>Ju$WOdGs`lv-h%~cF(fH!!zku^ zE@&|~`XTrY@W+*7` z%Led*+M^!p1(d%}I(9WPmH4enl4`n_l$J8chrIHZ2mA`mB`P{!f*Kh<1FXB4c0}FW zgO_&u9xLZtfnu0Qrc~_1 z2NLf%aZLg==MDFv8)6IC1;Gr{cVilt`C9-zj|Q9xvTOkcI<5tTTK4kJvAS7|@Io#SXg6Hh1%)$pC;9MKN+#f}( z3_d=MNaY~h+atKDY{4|}9_=C2v@P@vx`D!dIMV zPBAh4OF=uUFW$1Q4NLS#1#!97hqm-b(Onz$bdM@w?$N_XZrBZ(5Gdpk%DyKFSq~!L zL1tVmx_up~^GR1Rn!%R;YruV|L&?0|J4& zNAW3D6fl#Aa=Q+1afEMr!)rf%$^}~tz-r9FlnOmZq$A+gyln{Hsqf0_CcA|~Hpze9 zZm#Q~%Twu3yxW>`aWycxZLgtFBMliUpn1>$3jky;hE^?LxNzb+AiK3;XVe+5Af7ik zwc2_H?!}<&g76SQ$XJIkZK+*vFRw<~BQRMIfo=;dUBI>F`Lhn1cFzBO2S!LLcPECU o4R#0UzosVt=kfl3PRK#%;U|?Tk`p68QSe9YnwC Date: Fri, 27 Mar 2020 23:40:06 +0100 Subject: [PATCH 44/57] finalised doc on automatic basis rotations --- doc/guide/BasisRotation.rst | 49 +++++++++++++++++-------------------- 1 file changed, 23 insertions(+), 26 deletions(-) diff --git a/doc/guide/BasisRotation.rst b/doc/guide/BasisRotation.rst index 60fe23a4..88108f1e 100644 --- a/doc/guide/BasisRotation.rst +++ b/doc/guide/BasisRotation.rst @@ -12,44 +12,41 @@ to another basis. While this basis can in principle be chosen arbitrarily, two choices which have shown good results; name the basis sets that diagonalize the local Hamiltonian or the local density matrix of the system. -The transformation matrix can be stored in the :class:`BlockStructure` and the -transformation is automatically performed when using :class:`SumkDFT`'s :meth:`extract_G_loc` -and :meth:`put_Sigma` (see below). +As outlined in section :ref:`blockstructure`, the :class:`BlockStructure` includes all necessary functionalities. While it is possible to manually transform each Green's functions and self energies between the *sumk* and the *solver* basis, this leads to cumbersum code and is discouraged. Instead, in order to facilitate the block-structure manipulations for an actual DFT+DMFT calculation, some of the necessary steps are automatically included automatically. As soon as the +transformation matrix is stored in the :class:`BlockStructure`, the +transformation is automatically performed when using :class:`SumkDFT`'s :meth:`extract_G_loc`, +:meth:`put_Sigma`, and :meth:`calc_dc` (see below). + +Setting up the initial solver structure from DFT +------------------------------------------------ + +Before the actual calculation one has to specify the *solver* basis structure, in which the impurity problem will be tackled. The different available approximation were introduced in section :ref:`blockstructure`. An important feature of DFTTools is that there is an automatic way to determine the entries of the Green's function matrix that are zero by symmetry, when initialising the class:: + + from triqs_dft_tools.sumk_dft import * + SK = SumkDFT(hdf_file,use_dft_blocks='True') + +The flag *use_dft_blocks=True* analysis the local density matrix, determines the zero entries, and sets up a minimal *solver* structure. Alternatively, this step can be achieved by (see the reference manual for options):: + + SK.analyse_block_structure() -[UPDATE EVERYTHING FROM HERE ON:] Finding the transformation matrix --------------------------------- -The :class:`TransBasis` class offers a simple method to calculate the transformation -matrices to a basis where either the local Hamiltonian or the density matrix -is diagonal:: +The SumkDFT class offers a method that can determine transformation matrices to certain new basis. It is called as follows:: - from triqs_dft_tools.trans_basis import TransBasis - TB = TransBasis(SK) - TB.calculate_diagonalisation_matrix(prop_to_be_diagonal='eal', calc_in_solver_blocks = True) + SK.calculate_diagonalization_matrix(prop_to_be_diagonal='eal') - SK.block_structure.transformation = [{'ud':TB.w}] - - - -Transforming Green's functions manually ---------------------------------------- - -One can transform Green's functions manually using the :meth:`convert_gf` method:: - - # Rotate a Green's function from solver-space to sumk-space - new_gf = block_structure.convert_gf(old_gf, space_from='solver', space_to='sumk') +Possible option for *prop_to_be_diagonal* are *eal* (diagonalises the local hamiltonian) or *dm* (diagonalises the local density matrix). This routine stores the transformation matrix in the :class:`SK.block_structure` class, such that it can be used to rotate the basis. Automatic transformation during the DMFT loop --------------------------------------------- -During a DMFT loop one is often switching back and forth between the unrotated basis (Sumk-Space) and the rotated basis that is used by the QMC Solver. However, this need not be done manually each time. Instead, -once the block_structure.transformation property is set as shown above, this is -done automatically, meaning that :class:`SumkDFT`'s :meth:`extract_G_loc` -and :meth:`put_Sigma` are doing the transformations by default:: +During a DMFT loop one is often switching back and forth between the unrotated basis (Sumk-Space) and the rotated basis that is used by the QMC Solver. +Once the SK.block_structure.transformation property is set as shown above, this is +done automatically, meaning that :class:`SumkDFT`'s :meth:`extract_G_loc`, :meth:`put_Sigma`, and :meth:`calc_dc` are doing the transformations by default:: for it in range(iteration_offset, iteration_offset + n_iterations): # every GF is in solver space here @@ -70,7 +67,7 @@ and :meth:`put_Sigma` are doing the transformations by default:: S.G_iw << SK.extract_G_loc()[0] .. warning:: - One must not forget to also transform the interaction Hamiltonian to the diagonal basis! + Before doing the DMFT self-consistency loop, one must not forget to also transform the interaction Hamiltonian to the diagonal basis! This can be done with the :meth:`transform_U_matrix` method. However, due to different conventions in this method, one must pass the conjugated version of the transformation matrix:: From d54f157e170865e1a1d9c5b2d7f91dcca7297d16 Mon Sep 17 00:00:00 2001 From: aichhorn Date: Fri, 27 Mar 2020 23:45:35 +0100 Subject: [PATCH 45/57] changed default in calculate_diagonalisation_matrix to calculate in solver structure --- python/sumk_dft.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/sumk_dft.py b/python/sumk_dft.py index 392f068c..95bc21f8 100644 --- a/python/sumk_dft.py +++ b/python/sumk_dft.py @@ -1330,7 +1330,7 @@ class SumkDFT(object): # a block was found, break out of the loop break - def calculate_diagonalization_matrix(self, prop_to_be_diagonal='eal', calc_in_solver_blocks=False, write_to_blockstructure = True, shells=None): + def calculate_diagonalization_matrix(self, prop_to_be_diagonal='eal', calc_in_solver_blocks=True, write_to_blockstructure = True, shells=None): """ Calculates the diagonalisation matrix, and (optionally) stores it in the BlockStructure. From a3f792386e412d2623522cda13c9d0b4f087d76e Mon Sep 17 00:00:00 2001 From: aichhorn Date: Mon, 30 Mar 2020 13:24:14 +0200 Subject: [PATCH 46/57] updated SOC doc --- doc/guide/soc.rst | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/doc/guide/soc.rst b/doc/guide/soc.rst index f4b7ffd6..3491c2e0 100644 --- a/doc/guide/soc.rst +++ b/doc/guide/soc.rst @@ -9,12 +9,14 @@ DFT+DMFT calculations: - by performing a DFT calculation including SOC and then doing a DMFT calculation on top, or - by performing a DFT calculation without SOC and then adding the SOC term on the model level. +The second variant is a bit more involved and needs quite some expertise, so this guide will cover only the first variant with SOC included in the DFT calculations. + Treatment of SOC in DFT ----------------------- For now, TRIQS/DFTTools does only work with Wien2k when performing calculations with SO. The treatment of SOC in the VASP package is fundamentally different to the way Wien2k treats it, and the interface does not handle that at the moment. -Therefore, this guide describes how to do an AOC calculation using the Wien2k DFT package. +Therefore, this guide describes how to do an SOC calculation using the Wien2k DFT package. First, a Wien2k calculation including SOC has to be performed. For details, we refer the reader to the documentation of Wien2k. As a matter of fact, we need the output for the DFT band structure for both spin directions explicitly. That means that one needs to do a spin-polarised DFT calculation with SOC, but, however, with magnetic moment set to zero. In the Wien2k initialisation procedure, one can choose for the option -nom when ``lstart`` is called. This means that the charge densities are initialised without magnetic splitting. The SOC calculation is then performed in a standard way as described in the Wien2k manual. From a77844ea1a9bb55e4a40a52f5d3ebf57682c359f Mon Sep 17 00:00:00 2001 From: aichhorn Date: Mon, 30 Mar 2020 15:46:54 +0200 Subject: [PATCH 47/57] First draft of the Sr2MgOsO6 w/o SOC doc --- doc/tutorials.rst | 8 + .../images_scripts/Sr2MgOsO6_noSOC.indmftpr | 20 ++ .../images_scripts/Sr2MgOsO6_noSOC.struct | 40 +++ doc/tutorials/sr2mgoso6_nosoc.rst | 268 ++++++++++++++++++ 4 files changed, 336 insertions(+) create mode 100644 doc/tutorials/images_scripts/Sr2MgOsO6_noSOC.indmftpr create mode 100644 doc/tutorials/images_scripts/Sr2MgOsO6_noSOC.struct create mode 100644 doc/tutorials/sr2mgoso6_nosoc.rst diff --git a/doc/tutorials.rst b/doc/tutorials.rst index d02cdeb6..c24133fd 100644 --- a/doc/tutorials.rst +++ b/doc/tutorials.rst @@ -14,6 +14,14 @@ A simple example: SrVO3 tutorials/srvo3 +Basis rotations: Sr2MgOsO6 without SOC +-------------------------------------- + +.. toctree:: + :maxdepth: 2 + + tutorials/sr2mgoso6_nosoc + Full charge self consistency with Wien2k: :math:`\gamma`-Ce ----------------------------------------------------------- diff --git a/doc/tutorials/images_scripts/Sr2MgOsO6_noSOC.indmftpr b/doc/tutorials/images_scripts/Sr2MgOsO6_noSOC.indmftpr new file mode 100644 index 00000000..2f5c5f78 --- /dev/null +++ b/doc/tutorials/images_scripts/Sr2MgOsO6_noSOC.indmftpr @@ -0,0 +1,20 @@ +5 ! Nsort +2 1 1 4 2 ! Mult(Nsort) +3 ! lmax +complex ! choice of angular harmonics +0 0 0 0 ! l included for each sort +0 0 0 0 ! If split into ireps, gives number of ireps. for a given orbital (otherwise 0) +cubic ! choice of angular harmonics +0 0 2 0 ! l included for each sort +0 0 0 0 ! If split into ireps, gives number of ireps. for a given orbital (otherwise 0) +0 ! SO flag +complex ! choice of angular harmonics +0 0 0 0 ! l included for each sort +0 0 0 0 ! If split into ireps, gives number of ireps. for a given orbital (otherwise 0) +complex ! choice of angular harmonics +0 0 0 0 ! l included for each sort +0 0 0 0 ! If split into ireps, gives number of ireps. for a given orbital (otherwise 0) +complex +0 0 0 0 +0 0 0 0 +-0.088 0.43 ! 0.40 gives warnings, 0.043 gives occ 1.996 diff --git a/doc/tutorials/images_scripts/Sr2MgOsO6_noSOC.struct b/doc/tutorials/images_scripts/Sr2MgOsO6_noSOC.struct new file mode 100644 index 00000000..53439abd --- /dev/null +++ b/doc/tutorials/images_scripts/Sr2MgOsO6_noSOC.struct @@ -0,0 +1,40 @@ +Sr2MgOsO6 +B 5 87 + RELA + 10.507954 10.507954 14.968880 90.000000 90.000000 90.000000 +ATOM -1: X=0.00000000 Y=0.50000000 Z=0.75000000 + MULT= 2 ISPLIT=-2 + -1: X=0.50000000 Y=0.00000000 Z=0.75000000 +Sr 2+ NPT= 781 R0=.000010000 RMT= 2.50000 Z: 38.00000 +LOCAL ROT MATRIX: 1.0000000 0.0000000 0.0000000 + 0.0000000 1.0000000 0.0000000 + 0.0000000 0.0000000 1.0000000 +ATOM -2: X=0.00000000 Y=0.00000000 Z=0.00000000 + MULT= 1 ISPLIT=-2 +Os 6+ NPT= 781 R0=.000005000 RMT= 1.94 Z: 76.00000 +LOCAL ROT MATRIX: 1.0000000 0.0000000 0.0000000 + 0.0000000 1.0000000 0.0000000 + 0.0000000 0.0000000 1.0000000 +ATOM -3: X=0.00000000 Y=0.00000000 Z=0.50000000 + MULT= 1 ISPLIT=-2 +Mg 2+ NPT= 781 R0=.000100000 RMT= 1.89 Z: 12.00000 +LOCAL ROT MATRIX: 1.0000000 0.0000000 0.0000000 + 0.0000000 1.0000000 0.0000000 + 0.0000000 0.0000000 1.0000000 +ATOM -4: X=0.74270000 Y=0.21790000 Z=0.00000000 + MULT= 4 ISPLIT= 8 + -4: X=0.25730000 Y=0.78210000 Z=0.00000000 + -4: X=0.21790000 Y=0.25730000 Z=0.00000000 + -4: X=0.78210000 Y=0.74270000 Z=0.00000000 +O 2- NPT= 781 R0=.000100000 RMT= 1.58 Z: 8.00000 +LOCAL ROT MATRIX: 1.0000000 0.0000000 0.0000000 + 0.0000000 1.0000000 0.0000000 + 0.0000000 0.0000000 1.0000000 +ATOM -5: X=0.00000000 Y=0.00000000 Z=0.75390000 + MULT= 2 ISPLIT=-2 + -5: X=0.00000000 Y=0.00000000 Z=0.24610000 +O 2- NPT= 781 R0=.000100000 RMT= 1.58 Z: 8.00000 +LOCAL ROT MATRIX: 1.0000000 0.0000000 0.0000000 + 0.0000000 1.0000000 0.0000000 + 0.0000000 0.0000000 1.0000000 + 0 NUMBER OF SYMMETRY OPERATIONS diff --git a/doc/tutorials/sr2mgoso6_nosoc.rst b/doc/tutorials/sr2mgoso6_nosoc.rst new file mode 100644 index 00000000..36ddfd36 --- /dev/null +++ b/doc/tutorials/sr2mgoso6_nosoc.rst @@ -0,0 +1,268 @@ +.. _Sr2MgOsO6_noSOC: + +Here we will discuss a calculation where off-diagonal matrix elements show up, and will discuss step-by-step how this calculation can be set up. + +The full script for this calculation is also provided here (:download:`dft_dmft_cthyb.py `). + +Note that we do not include spin-orbit coupling here for pedagogical reasons. For the real material it is necessary to include also SOC. + + +DFT (Wien2k) and Wannier orbitals +================================= + +DFT setup +--------- + +First, we do a DFT calculation, using the Wien2k package. As main input file we have to provide the so-called struct file :file:`Sr2MgOs6_noSOC.struct`. We use the following: + +.. literalinclude:: images_scripts/Sr2MgOsO6_noSOC.struct + +The DFT calculation is done as usual, for instance you can use for the initialisation + + + init -b -vxc 5 -numk 2000 + +This is setting up a non-magnetic calculation, using the LDA and 2000 k-points in the full Brillouin zone. As usual, we start the DFT self consistent cycle by the Wien2k script :: + + run + +Wannier orbitals +---------------- + +As a next step, we calculate localised orbitals for the t2g orbitals. We use the same input file for :program:`dmftproj` as it was used in the :ref:`documentation`: + +.. literalinclude:: images_scripts/Sr2MgOsO6_noSOC.indmftpr + +Note that, due to the distortions in the crystal structure, we need to include all five d orbitals in the calculation (line 8 in the input file above). + +To prepare the input data for :program:`dmftproj` we execute lapw2 with the `-almd` option :: + + x lapw2 -almd + +Then :program:`dmftproj` is executed in its default mode (i.e. without spin-polarization or spin-orbit included) :: + + dmftproj + +This program produces the necessary files for the conversion to the hdf5 file structure. This is done using +the python module :class:`Wien2kConverter `. A simple python script that initialises the converter is:: + + from triqs_dft_tools.converters.wien2k_converter import * + Converter = Wien2kConverter(filename = "Sr2MgOsO6_noSOC") + +After initializing the interface module, we can now convert the input +text files to the hdf5 archive by:: + + Converter.convert_dft_input() + +This reads all the data, and stores everything that is necessary for the DMFT calculation in the file :file:`Sr2MgOsO6_noSOC.h5`. + +[CONTINUE HERE] + +The DMFT calculation +==================== + +The DMFT script itself is, except very few details, independent of the DFT package that was used to calculate the local orbitals. +As soon as one has converted everything to the hdf5 format, the following procedure is practially the same. + +Loading modules +--------------- + +First, we load the necessary modules:: + + from triqs_dft_tools.sumk_dft import * + from pytriqs.gf import * + from pytriqs.archive import HDFArchive + from pytriqs.operators.util import * + from triqs_cthyb import * + import pytriqs.utility.mpi as mpi + +The last two lines load the modules for the construction of the +:ref:`CTHYB solver `. + +Initializing SumkDFT +-------------------- + +We define some parameters, which should be self-explanatory:: + + dft_filename = 'SrVO3' # filename + U = 4.0 # interaction parameters + J = 0.65 + beta = 40 # inverse temperature + loops = 15 # number of DMFT loops + mix = 0.8 # mixing factor of Sigma after solution of the AIM + dc_type = 1 # DC type: 0 FLL, 1 Held, 2 AMF + use_blocks = True # use bloc structure from DFT input + prec_mu = 0.0001 # precision of chemical potential + + +And next, we can initialize the :class:`SumkDFT ` class:: + + SK = SumkDFT(hdf_file=dft_filename+'.h5',use_dft_blocks=use_blocks) + +Initializing the solver +----------------------- + +We also have to specify the :ref:`CTHYB solver ` related settings. +We assume that the DMFT script for SrVO3 is executed on 16 cores. A sufficient set +of parameters for a first guess is:: + + p = {} + # solver + p["random_seed"] = 123 * mpi.rank + 567 + p["length_cycle"] = 200 + p["n_warmup_cycles"] = 100000 + p["n_cycles"] = 1000000 + # tail fit + p["perform_tail_fit"] = True + p["fit_max_moment"] = 4 + p["fit_min_n"] = 30 + p["fit_max_n"] = 60 + +Here we use a tail fit to deal with numerical noise of higher Matsubara frequencies. +For other options and more details on the solver parameters, we refer the user to +the :ref:`CTHYB solver ` documentation. +It is important to note that the solver parameters have to be adjusted for +each material individually. A guide on how to set the tail fit parameters is given +:ref:`below `. + + +The next step is to initialize the +:class:`solver class `. +It consist of two parts: + +#. Calculating the multi-band interaction matrix, and constructing the + interaction Hamiltonian. +#. Initializing the solver class itself. + +The first step is done using methods of the :ref:`TRIQS ` library:: + + n_orb = SK.corr_shells[0]['dim'] + l = SK.corr_shells[0]['l'] + spin_names = ["up","down"] + orb_names = [i for i in range(n_orb)] + # Use GF structure determined by DFT blocks: + gf_struct = [(block, indices) for block, indices in SK.gf_struct_solver[0].iteritems()] + # Construct U matrix for density-density calculations: + Umat, Upmat = U_matrix_kanamori(n_orb=n_orb, U_int=U, J_hund=J) + +We assumed here that we want to use an interaction matrix with +Kanamori definitions of :math:`U` and :math:`J`. + +Next, we construct the Hamiltonian and the solver:: + + h_int = h_int_density(spin_names, orb_names, map_operator_structure=SK.sumk_to_solver[0], U=Umat, Uprime=Upmat) + S = Solver(beta=beta, gf_struct=gf_struct) + +As you see, we take only density-density interactions into +account. Other Hamiltonians with, e.g. with full rotational invariant interactions are: + +* h_int_kanamori +* h_int_slater + +For other choices of the interaction matrices (e.g Slater representation) or +Hamiltonians, we refer to the reference manual of the :ref:`TRIQS ` +library. + +DMFT cycle +---------- + +Now we can go to the definition of the self-consistency step. It consists again +of the basic steps discussed in the :ref:`previous section `, with +some additional refinements:: + + for iteration_number in range(1,loops+1): + if mpi.is_master_node(): print "Iteration = ", iteration_number + + SK.symm_deg_gf(S.Sigma_iw,orb=0) # symmetrizing Sigma + SK.set_Sigma([ S.Sigma_iw ]) # put Sigma into the SumK class + chemical_potential = SK.calc_mu( precision = prec_mu ) # find the chemical potential for given density + S.G_iw << SK.extract_G_loc()[0] # calc the local Green function + mpi.report("Total charge of Gloc : %.6f"%S.G_iw.total_density()) + + # Init the DC term and the real part of Sigma, if no previous runs found: + if (iteration_number==1 and previous_present==False): + dm = S.G_iw.density() + SK.calc_dc(dm, U_interact = U, J_hund = J, orb = 0, use_dc_formula = dc_type) + S.Sigma_iw << SK.dc_imp[0]['up'][0,0] + + # Calculate new G0_iw to input into the solver: + S.G0_iw << S.Sigma_iw + inverse(S.G_iw) + S.G0_iw << inverse(S.G0_iw) + + # Solve the impurity problem: + S.solve(h_int=h_int, **p) + + # Solved. Now do post-solution stuff: + mpi.report("Total charge of impurity problem : %.6f"%S.G_iw.total_density()) + + # Now mix Sigma and G with factor mix, if wanted: + if (iteration_number>1 or previous_present): + if mpi.is_master_node(): + with HDFArchive(dft_filename+'.h5','r') as ar: + mpi.report("Mixing Sigma and G with factor %s"%mix) + S.Sigma_iw << mix * S.Sigma_iw + (1.0-mix) * ar['dmft_output']['Sigma_iw'] + S.G_iw << mix * S.G_iw + (1.0-mix) * ar['dmft_output']['G_iw'] + S.G_iw << mpi.bcast(S.G_iw) + S.Sigma_iw << mpi.bcast(S.Sigma_iw) + + # Write the final Sigma and G to the hdf5 archive: + if mpi.is_master_node(): + with HDFArchive(dft_filename+'.h5','a') as ar: + ar['dmft_output']['iterations'] = iteration_number + ar['dmft_output']['G_0'] = S.G0_iw + ar['dmft_output']['G_tau'] = S.G_tau + ar['dmft_output']['G_iw'] = S.G_iw + ar['dmft_output']['Sigma_iw'] = S.Sigma_iw + + # Set the new double counting: + dm = S.G_iw.density() # compute the density matrix of the impurity problem + SK.calc_dc(dm, U_interact = U, J_hund = J, orb = 0, use_dc_formula = dc_type) + + # Save stuff into the user_data group of hdf5 archive in case of rerun: + SK.save(['chemical_potential','dc_imp','dc_energ']) + + +This is all we need for the DFT+DMFT calculation. +You can see in this code snippet, that all results of this calculation +will be stored in a separate subgroup in the hdf5 file, called `dmft_output`. +Note that this script performs 15 DMFT cycles, but does not check for +convergence. Of course, it would be possible to build in convergence criteria. +A simple check for convergence can be also done if you store multiple quantities +of each iteration and analyse the convergence by hand. In general, it is advisable +to start with a lower statistics (less measurements), but then increase it at a +point close to converged results (e.g. after a few initial iterations). This helps +to keep computational costs low during the first iterations. + +Using the Kanamori Hamiltonian and the parameters above (but on 16 cores), +your self energy after the **first iteration** should look like the +self energy shown below. + +.. image:: images_scripts/SrVO3_Sigma_iw_it1.png + :width: 700 + :align: center + +.. _tailfit: + +Tail fit parameters +------------------- + +A good way to identify suitable tail fit parameters is by "human inspection". +Therefore disabled the tail fitting first:: + + p["perform_tail_fit"] = False + +and perform only one DMFT iteration. The resulting self energy can be tail fitted by hand:: + + Sigma_iw_fit = S.Sigma_iw.copy() + Sigma_iw_fit << tail_fit(S.Sigma_iw, fit_max_moment = 4, fit_min_n = 40, fit_max_n = 160)[0] + +Plot the self energy and adjust the tail fit parameters such that you obtain a +proper fit. The :meth:`fit_tail function ` is part +of the :ref:`TRIQS ` library. + +For a self energy which is going to zero for :math:`i\omega \rightarrow 0` our suggestion is +to start the tail fit (:emphasis:`fit_min_n`) at a Matsubara frequency considerable above the minimum +of the self energy and to stop (:emphasis:`fit_max_n`) before the noise fully takes over. +If it is difficult to find a reasonable fit in this region you should increase +your statistics (number of measurements). Keep in mind that :emphasis:`fit_min_n` +and :emphasis:`fit_max_n` also depend on :math:`\beta`. From d6977d8bee95197dec25c97f0402024294095148 Mon Sep 17 00:00:00 2001 From: aichhorn Date: Mon, 30 Mar 2020 15:55:02 +0200 Subject: [PATCH 48/57] cleaned up files in Sr2MgOsO6 doc --- .../images_scripts/Sr2MgOsO6_noSOC.py | 19 ++ doc/tutorials/sr2mgoso6_nosoc.rst | 207 +----------------- 2 files changed, 20 insertions(+), 206 deletions(-) create mode 100644 doc/tutorials/images_scripts/Sr2MgOsO6_noSOC.py diff --git a/doc/tutorials/images_scripts/Sr2MgOsO6_noSOC.py b/doc/tutorials/images_scripts/Sr2MgOsO6_noSOC.py new file mode 100644 index 00000000..890c78c1 --- /dev/null +++ b/doc/tutorials/images_scripts/Sr2MgOsO6_noSOC.py @@ -0,0 +1,19 @@ +# Conversion: +from triqs_dft_tools.converters.wien2k_converter import * +Converter = Wien2kConverter(filename = "Sr2MgOsO6_noSOC") +Converter.convert_dft_input() + +import numpy +numpy.set_printoptions(precision=3, suppress=True) + +# Set up SK class: +from triqs_dft_tools.sumk_dft import * +SK = SumkDFT(hdf_file='Sr2MgOsO6.h5',use_dft_blocks=True) + +eal = SK.eff_atomic_levels() + +mat = SK.calculate_diagonalization_matrix(prop_to_be_diagonal='eal') + + + + diff --git a/doc/tutorials/sr2mgoso6_nosoc.rst b/doc/tutorials/sr2mgoso6_nosoc.rst index 36ddfd36..2c80b10b 100644 --- a/doc/tutorials/sr2mgoso6_nosoc.rst +++ b/doc/tutorials/sr2mgoso6_nosoc.rst @@ -2,7 +2,7 @@ Here we will discuss a calculation where off-diagonal matrix elements show up, and will discuss step-by-step how this calculation can be set up. -The full script for this calculation is also provided here (:download:`dft_dmft_cthyb.py `). +The full script for this calculation is also provided here (:download:`Sr2MgOsO6_noSOC.py `). Note that we do not include spin-orbit coupling here for pedagogical reasons. For the real material it is necessary to include also SOC. @@ -61,208 +61,3 @@ This reads all the data, and stores everything that is necessary for the DMFT ca The DMFT calculation ==================== -The DMFT script itself is, except very few details, independent of the DFT package that was used to calculate the local orbitals. -As soon as one has converted everything to the hdf5 format, the following procedure is practially the same. - -Loading modules ---------------- - -First, we load the necessary modules:: - - from triqs_dft_tools.sumk_dft import * - from pytriqs.gf import * - from pytriqs.archive import HDFArchive - from pytriqs.operators.util import * - from triqs_cthyb import * - import pytriqs.utility.mpi as mpi - -The last two lines load the modules for the construction of the -:ref:`CTHYB solver `. - -Initializing SumkDFT --------------------- - -We define some parameters, which should be self-explanatory:: - - dft_filename = 'SrVO3' # filename - U = 4.0 # interaction parameters - J = 0.65 - beta = 40 # inverse temperature - loops = 15 # number of DMFT loops - mix = 0.8 # mixing factor of Sigma after solution of the AIM - dc_type = 1 # DC type: 0 FLL, 1 Held, 2 AMF - use_blocks = True # use bloc structure from DFT input - prec_mu = 0.0001 # precision of chemical potential - - -And next, we can initialize the :class:`SumkDFT ` class:: - - SK = SumkDFT(hdf_file=dft_filename+'.h5',use_dft_blocks=use_blocks) - -Initializing the solver ------------------------ - -We also have to specify the :ref:`CTHYB solver ` related settings. -We assume that the DMFT script for SrVO3 is executed on 16 cores. A sufficient set -of parameters for a first guess is:: - - p = {} - # solver - p["random_seed"] = 123 * mpi.rank + 567 - p["length_cycle"] = 200 - p["n_warmup_cycles"] = 100000 - p["n_cycles"] = 1000000 - # tail fit - p["perform_tail_fit"] = True - p["fit_max_moment"] = 4 - p["fit_min_n"] = 30 - p["fit_max_n"] = 60 - -Here we use a tail fit to deal with numerical noise of higher Matsubara frequencies. -For other options and more details on the solver parameters, we refer the user to -the :ref:`CTHYB solver ` documentation. -It is important to note that the solver parameters have to be adjusted for -each material individually. A guide on how to set the tail fit parameters is given -:ref:`below `. - - -The next step is to initialize the -:class:`solver class `. -It consist of two parts: - -#. Calculating the multi-band interaction matrix, and constructing the - interaction Hamiltonian. -#. Initializing the solver class itself. - -The first step is done using methods of the :ref:`TRIQS ` library:: - - n_orb = SK.corr_shells[0]['dim'] - l = SK.corr_shells[0]['l'] - spin_names = ["up","down"] - orb_names = [i for i in range(n_orb)] - # Use GF structure determined by DFT blocks: - gf_struct = [(block, indices) for block, indices in SK.gf_struct_solver[0].iteritems()] - # Construct U matrix for density-density calculations: - Umat, Upmat = U_matrix_kanamori(n_orb=n_orb, U_int=U, J_hund=J) - -We assumed here that we want to use an interaction matrix with -Kanamori definitions of :math:`U` and :math:`J`. - -Next, we construct the Hamiltonian and the solver:: - - h_int = h_int_density(spin_names, orb_names, map_operator_structure=SK.sumk_to_solver[0], U=Umat, Uprime=Upmat) - S = Solver(beta=beta, gf_struct=gf_struct) - -As you see, we take only density-density interactions into -account. Other Hamiltonians with, e.g. with full rotational invariant interactions are: - -* h_int_kanamori -* h_int_slater - -For other choices of the interaction matrices (e.g Slater representation) or -Hamiltonians, we refer to the reference manual of the :ref:`TRIQS ` -library. - -DMFT cycle ----------- - -Now we can go to the definition of the self-consistency step. It consists again -of the basic steps discussed in the :ref:`previous section `, with -some additional refinements:: - - for iteration_number in range(1,loops+1): - if mpi.is_master_node(): print "Iteration = ", iteration_number - - SK.symm_deg_gf(S.Sigma_iw,orb=0) # symmetrizing Sigma - SK.set_Sigma([ S.Sigma_iw ]) # put Sigma into the SumK class - chemical_potential = SK.calc_mu( precision = prec_mu ) # find the chemical potential for given density - S.G_iw << SK.extract_G_loc()[0] # calc the local Green function - mpi.report("Total charge of Gloc : %.6f"%S.G_iw.total_density()) - - # Init the DC term and the real part of Sigma, if no previous runs found: - if (iteration_number==1 and previous_present==False): - dm = S.G_iw.density() - SK.calc_dc(dm, U_interact = U, J_hund = J, orb = 0, use_dc_formula = dc_type) - S.Sigma_iw << SK.dc_imp[0]['up'][0,0] - - # Calculate new G0_iw to input into the solver: - S.G0_iw << S.Sigma_iw + inverse(S.G_iw) - S.G0_iw << inverse(S.G0_iw) - - # Solve the impurity problem: - S.solve(h_int=h_int, **p) - - # Solved. Now do post-solution stuff: - mpi.report("Total charge of impurity problem : %.6f"%S.G_iw.total_density()) - - # Now mix Sigma and G with factor mix, if wanted: - if (iteration_number>1 or previous_present): - if mpi.is_master_node(): - with HDFArchive(dft_filename+'.h5','r') as ar: - mpi.report("Mixing Sigma and G with factor %s"%mix) - S.Sigma_iw << mix * S.Sigma_iw + (1.0-mix) * ar['dmft_output']['Sigma_iw'] - S.G_iw << mix * S.G_iw + (1.0-mix) * ar['dmft_output']['G_iw'] - S.G_iw << mpi.bcast(S.G_iw) - S.Sigma_iw << mpi.bcast(S.Sigma_iw) - - # Write the final Sigma and G to the hdf5 archive: - if mpi.is_master_node(): - with HDFArchive(dft_filename+'.h5','a') as ar: - ar['dmft_output']['iterations'] = iteration_number - ar['dmft_output']['G_0'] = S.G0_iw - ar['dmft_output']['G_tau'] = S.G_tau - ar['dmft_output']['G_iw'] = S.G_iw - ar['dmft_output']['Sigma_iw'] = S.Sigma_iw - - # Set the new double counting: - dm = S.G_iw.density() # compute the density matrix of the impurity problem - SK.calc_dc(dm, U_interact = U, J_hund = J, orb = 0, use_dc_formula = dc_type) - - # Save stuff into the user_data group of hdf5 archive in case of rerun: - SK.save(['chemical_potential','dc_imp','dc_energ']) - - -This is all we need for the DFT+DMFT calculation. -You can see in this code snippet, that all results of this calculation -will be stored in a separate subgroup in the hdf5 file, called `dmft_output`. -Note that this script performs 15 DMFT cycles, but does not check for -convergence. Of course, it would be possible to build in convergence criteria. -A simple check for convergence can be also done if you store multiple quantities -of each iteration and analyse the convergence by hand. In general, it is advisable -to start with a lower statistics (less measurements), but then increase it at a -point close to converged results (e.g. after a few initial iterations). This helps -to keep computational costs low during the first iterations. - -Using the Kanamori Hamiltonian and the parameters above (but on 16 cores), -your self energy after the **first iteration** should look like the -self energy shown below. - -.. image:: images_scripts/SrVO3_Sigma_iw_it1.png - :width: 700 - :align: center - -.. _tailfit: - -Tail fit parameters -------------------- - -A good way to identify suitable tail fit parameters is by "human inspection". -Therefore disabled the tail fitting first:: - - p["perform_tail_fit"] = False - -and perform only one DMFT iteration. The resulting self energy can be tail fitted by hand:: - - Sigma_iw_fit = S.Sigma_iw.copy() - Sigma_iw_fit << tail_fit(S.Sigma_iw, fit_max_moment = 4, fit_min_n = 40, fit_max_n = 160)[0] - -Plot the self energy and adjust the tail fit parameters such that you obtain a -proper fit. The :meth:`fit_tail function ` is part -of the :ref:`TRIQS ` library. - -For a self energy which is going to zero for :math:`i\omega \rightarrow 0` our suggestion is -to start the tail fit (:emphasis:`fit_min_n`) at a Matsubara frequency considerable above the minimum -of the self energy and to stop (:emphasis:`fit_max_n`) before the noise fully takes over. -If it is difficult to find a reasonable fit in this region you should increase -your statistics (number of measurements). Keep in mind that :emphasis:`fit_min_n` -and :emphasis:`fit_max_n` also depend on :math:`\beta`. From 5f2782980ed8592651a3e29037723a7a7ad9f37b Mon Sep 17 00:00:00 2001 From: aichhorn Date: Tue, 31 Mar 2020 09:43:05 +0200 Subject: [PATCH 49/57] worked on the sr2mgoso6 tutorial --- .../images_scripts/Sr2MgOsO6_noSOC.indmftpr | 4 +- .../images_scripts/Sr2MgOsO6_noSOC.outdmftpr | 12 ++++ .../images_scripts/Sr2MgOsO6_noSOC_DOS.png | Bin 0 -> 11570 bytes doc/tutorials/sr2mgoso6_nosoc.rst | 62 +++++++++++++++--- 4 files changed, 68 insertions(+), 10 deletions(-) create mode 100644 doc/tutorials/images_scripts/Sr2MgOsO6_noSOC.outdmftpr create mode 100644 doc/tutorials/images_scripts/Sr2MgOsO6_noSOC_DOS.png diff --git a/doc/tutorials/images_scripts/Sr2MgOsO6_noSOC.indmftpr b/doc/tutorials/images_scripts/Sr2MgOsO6_noSOC.indmftpr index 2f5c5f78..928c1656 100644 --- a/doc/tutorials/images_scripts/Sr2MgOsO6_noSOC.indmftpr +++ b/doc/tutorials/images_scripts/Sr2MgOsO6_noSOC.indmftpr @@ -1,5 +1,5 @@ 5 ! Nsort -2 1 1 4 2 ! Mult(Nsort) +2 1 1 4 2 ! Mult(Nsort) 3 ! lmax complex ! choice of angular harmonics 0 0 0 0 ! l included for each sort @@ -17,4 +17,4 @@ complex ! choice of angular harmonics complex 0 0 0 0 0 0 0 0 --0.088 0.43 ! 0.40 gives warnings, 0.043 gives occ 1.996 +-0.09 0.43 diff --git a/doc/tutorials/images_scripts/Sr2MgOsO6_noSOC.outdmftpr b/doc/tutorials/images_scripts/Sr2MgOsO6_noSOC.outdmftpr new file mode 100644 index 00000000..27328905 --- /dev/null +++ b/doc/tutorials/images_scripts/Sr2MgOsO6_noSOC.outdmftpr @@ -0,0 +1,12 @@ +Density Matrices for the Correlated States : + + Sort = 2 Atom = 3 and Orbital l = 2 + + 0.000739 0.000000 0.000000 0.000000 0.000000 -0.000000 -0.000000 -0.000000 0.000000 -0.000000 + 0.000000 -0.000000 0.502746 0.000000 0.000000 0.099298 0.000000 -0.000000 0.000000 -0.000000 + 0.000000 0.000000 0.000000 -0.099298 0.020434 0.000000 0.000000 -0.000000 0.000000 0.000000 + -0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.735763 0.000000 0.000000 0.000000 + 0.000000 0.000000 0.000000 0.000000 0.000000 -0.000000 0.000000 -0.000000 0.735763 -0.000000 + +The charge of the orbital is : 1.99544 + diff --git a/doc/tutorials/images_scripts/Sr2MgOsO6_noSOC_DOS.png b/doc/tutorials/images_scripts/Sr2MgOsO6_noSOC_DOS.png new file mode 100644 index 0000000000000000000000000000000000000000..505bc130e786a03dd0131a21538578466b4bf164 GIT binary patch literal 11570 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. A simple python script that initialises the converter is:: +At the end of the run you see the density matrix in Wannier space: + +.. literalinclude:: images_scripts/Sr2MgOsO6_noSOC.outdmftpr + +As you can see, there are off-diagonal elements between the :math:`d_{x^2-y^2}` and the :math:`d_{xy}` orbital. + +We convert the output to the hdf5 archive, using +the python module :class:`Wien2kConverter `. A simple python script doing this is:: from triqs_dft_tools.converters.wien2k_converter import * Converter = Wien2kConverter(filename = "Sr2MgOsO6_noSOC") - -After initializing the interface module, we can now convert the input -text files to the hdf5 archive by:: - Converter.convert_dft_input() This reads all the data, and stores everything that is necessary for the DMFT calculation in the file :file:`Sr2MgOsO6_noSOC.h5`. -[CONTINUE HERE] The DMFT calculation ==================== +Before starting the DMFT calculation it is beneficial to look a bit more closely at the block structure of the problem. Eventually, we want to use a basis that is as diagonal as possible, and include only the partially filled orbitals in the correlated problem. All this can be done using the functionalities of the :class:`BlockStructure ` class, see section :ref:`blockstructure`. + +We first initialise the SumK class:: + + from triqs_dft_tools.sumk_dft import * + SK = SumkDFT(hdf_file='Sr2MgOsO6_noSOC.h5',use_dft_blocks=True) + +The flag *use_dft_blocks=True* determines, as usual, the smallest possible blocks with non-zero entries, and initialises them as *solver* block structure. In order to disentangle the :math:`d_{x^2-y^2}` and the :math:`d_{xy}` orbitals, and pick out only the partially filled one, we do a transformation into a basis where the local Hamiltonian is diagonal:: + + mat = SK.calculate_diagonalization_matrix(prop_to_be_diagonal='eal',calc_in_solver_blocks=True) + +We can look at the diagonalisation matrix, it is:: + + >>> print mat[0]['down'] + [[ 1. +0.j 0. +0.j 0. +0.j 0. +0.j 0. +0.j ] + [ 0. +0.j -0.985+0.j 0. -0.173j 0. +0.j 0. +0.j ] + [ 0. +0.j 0.173+0.j 0. -0.985j 0. +0.j 0. +0.j ] + [ 0. +0.j 0. +0.j 0. +0.j 1. +0.j 0. +0.j ] + [ 0. +0.j 0. +0.j 0. +0.j 0. +0.j 1. +0.j ]] + >>> + +This transformation is already stored in the SK.block_structure class. The next step is actually not needed for a DMFT calculation, but lets see what the transformation does to the local Hamiltonian. We can calculate it before rotation, rotate it, and look at the 2x2 block with off-diagonals:: + + eal = SK.eff_atomnic_levels() + eal2 = SK.block_structure.convert_matrix(eal[0],space_from='sumk', space_to='solver') + + print eal[0]['up'][1:3,1:3] # prints the 2x2 block with offiagonals + [[ 0.391+0.j -0. -0.815j] + [-0. +0.815j 4.884-0.j ]] + + print eal2['up_1'] # prints the 2x2 block after rotation + [[0.247-0.j 0. +0.j] + [0. -0.j 5.028+0.j]] + +So the local Hamiltonian has been diagonalised. From the other entries we can see that the *up_0* block and the [1,1] entry of the *up_1* block correspond to :math:`e_g`-like orbitals, and the others are the +:math:`t_{2g}` orbitals that we want to keep. + +[TO BE CONTINUED...] From ec2184259ed65eee91031137fc20b41ef9f8edea Mon Sep 17 00:00:00 2001 From: hschnait Date: Tue, 31 Mar 2020 15:54:16 +0200 Subject: [PATCH 50/57] Correct description of Transformation matrix --- doc/guide/blockstructure.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/guide/blockstructure.rst b/doc/guide/blockstructure.rst index 178be061..a366cdf0 100644 --- a/doc/guide/blockstructure.rst +++ b/doc/guide/blockstructure.rst @@ -90,7 +90,7 @@ It is easy to check that the following matrix diagonalises this local Hamiltonia T_{mm'} = \begin{pmatrix} 1.0 & 0.0 & 0.0 \\0.0 & 1/\sqrt{2} & -1/\sqrt{2}\\0.0 & 1/\sqrt{2} & 1/\sqrt{2} \end{pmatrix} -With this unitary matrix, we can do a basis rotation to reduce the size of the off-diagonal matrix elements. Note that the transformation matrix has to be given in the *solver* basis form (a 3x3 matrix in this case):: +With this unitary matrix, we can do a basis rotation to reduce the size of the off-diagonal matrix elements. Note that the transformation matrix has to be given in the *sumk* basis form (a 3x3 matrix in this case):: import numpy as np # Unitary transformation matrix @@ -128,4 +128,4 @@ The Green's function GF4 consists now only of two 1x1 blocks, where *up_1* was t In summary, we started with a full 3x3 matrix in the very beginning, and ended with two 1x1 blocks containing the relevant matrix elements for the calculation. - \ No newline at end of file + From c1fdfd1d8ffcb32979fad2842ed120d64befcc56 Mon Sep 17 00:00:00 2001 From: aichhorn Date: Tue, 7 Apr 2020 20:50:37 +0200 Subject: [PATCH 51/57] Added Tutorial fro basis rotations: Sr2MgOsO6 w/o SOC --- .../images_scripts/Sr2MgOsO6_noSOC.py | 118 ++++++++++++++++-- .../images_scripts/Sr2MgOsO6_noSOC_Sigmas.png | Bin 0 -> 78192 bytes doc/tutorials/sr2mgoso6_nosoc.rst | 113 ++++++++++++++++- 3 files changed, 218 insertions(+), 13 deletions(-) create mode 100644 doc/tutorials/images_scripts/Sr2MgOsO6_noSOC_Sigmas.png diff --git a/doc/tutorials/images_scripts/Sr2MgOsO6_noSOC.py b/doc/tutorials/images_scripts/Sr2MgOsO6_noSOC.py index 890c78c1..232c087d 100644 --- a/doc/tutorials/images_scripts/Sr2MgOsO6_noSOC.py +++ b/doc/tutorials/images_scripts/Sr2MgOsO6_noSOC.py @@ -1,19 +1,121 @@ -# Conversion: +# Import the modules: +from triqs_dft_tools.sumk_dft import * +from pytriqs.gf import * +from pytriqs.archive import HDFArchive +from pytriqs.operators.util import * +from pytriqs.operators.util.U_matrix import * +from triqs_cthyb import * +import pytriqs.utility.mpi as mpi + +# Convert the input from triqs_dft_tools.converters.wien2k_converter import * Converter = Wien2kConverter(filename = "Sr2MgOsO6_noSOC") Converter.convert_dft_input() -import numpy -numpy.set_printoptions(precision=3, suppress=True) +# Init the SumK class: +filename = 'Sr2MgOsO6_noSOC.h5' +SK = SumkDFT(hdf_file=filename,use_dft_blocks=True) -# Set up SK class: -from triqs_dft_tools.sumk_dft import * -SK = SumkDFT(hdf_file='Sr2MgOsO6.h5',use_dft_blocks=True) +# Find diagonal local basis set: +SK.calculate_diagonalization_matrix(prop_to_be_diagonal='eal',calc_in_solver_blocks=True) -eal = SK.eff_atomic_levels() +########################### +# Now we pick the orbitals: +# BE CAREFUL: THIS NEEDS TO BE DONE PROPERLY +# AND IS DIFFERENT FORM CASE TO CASE! +indices_to_pick_sumk = [1,3,4] +SK.block_structure.pick_gf_struct_solver([{'up_1': [0],'up_2': [0],'up_3': [0],'down_1': [0],'down_2': [0],'down_3': [0]}]) +########################### -mat = SK.calculate_diagonalization_matrix(prop_to_be_diagonal='eal') +# Now we set up the U matrix, first in cubic (Wien2k) convention: +U = 2.0 +J = 0.2 +U_mat = U_matrix(l=2,U_int=U,J_hund=J,basis='other', T=SK.T[0].conjugate()) +# Now we transform the U Matrix: +U_trans = transform_U_matrix(U_mat, SK.block_structure.transformation[0]['up'].conjugate()) +# pick out the relevant orbitals: +U_red = subarray(U_trans,len(U_trans.shape)*[indices_to_pick_sumk]) +# Finally, set up the Hamiltonian: +h_int = h_int_slater(['up','down'], indices_to_pick_sumk, U_red, map_operator_structure=SK.block_structure.sumk_to_solver[0], off_diag=False, complex=False) +# Solver Init: +beta = 40.0 +S = Solver(beta=beta, gf_struct=SK.block_structure.gf_struct_solver_list[0]) + +# Solver parameters: +p = {} +# solver +p["random_seed"] = 123 * mpi.rank + 567 +p["length_cycle"] = 200 +p["n_warmup_cycles"] = 100000 +p["n_cycles"] = 1000000 +# tail fit +p["perform_tail_fit"] = True +p["fit_max_moment"] = 4 +p["fit_min_n"] = 30 +p["fit_max_n"] = 70 + +# double counting correction: +dc_type = 0 # FLL +# DMFT loops: +n_loops = 1 + +#for first iteration, add the outout group: +if mpi.is_master_node(): + with HDFArchive(filename) as ar: + if (not ar.is_group('dmft_output')): + ar.create_group('dmft_output') + +for iteration_number in range(1,n_loops+1): + + mpi.report("Iteration = %s"%iteration_number) + + SK.symm_deg_gf(S.Sigma_iw) # symmetrizing Sigma + SK.set_Sigma([ S.Sigma_iw ]) # put Sigma into the SumK class + chemical_potential = SK.calc_mu( precision = 0.01 ) # find the chemical potential for given density + S.G_iw << SK.extract_G_loc()[0] + + if (iteration_number==1): + # Put Hartree energy on Re Sigma + dm = S.G_iw.density() + SK.calc_dc(dm, U_interact = U, J_hund = J, orb = 0, use_dc_formula = dc_type) + S.Sigma_iw << SK.block_structure.convert_matrix(SK.dc_imp[0],space_from='sumk',space_to='solver')['up_1'][0,0] + + mpi.report("Orbital densities of local Green function :") + for s,gf in S.G_iw: + mpi.report("Orbital %s: %s"%(s,dm[s].real)) + mpi.report("Total charge of Gloc : %.6f"%S.G_iw.total_density().real) + + # Calculate new G0_iw to input into the solver: + S.G0_iw << S.Sigma_iw + inverse(S.G_iw) + S.G0_iw << inverse(S.G0_iw) + + # Solve the impurity problem: + S.solve(h_int=h_int, **p) + + # Solved. Now do post-solution stuff: + dm = S.G_iw.density() + mpi.report("Orbital densities of impurity Green function:") + for s,gf in S.G_iw: + mpi.report("Orbital %s: %s"%(s,dm[s].real)) + mpi.report("Total charge of impurity problem : %.6f"%S.G_iw.total_density().real) + + # Write the final Sigma and G to the hdf5 archive: + if mpi.is_master_node(): + with HDFArchive(filename) as ar: + ar['dmft_output']['iterations'] = iteration_number + ar['dmft_output']['G_0'] = S.G0_iw + ar['dmft_output']['G_tau'] = S.G_tau + ar['dmft_output']['G_iw'] = S.G_iw + ar['dmft_output']['Sigma_iw_%s'%iteration_number] = S.Sigma_iw + + # Set the new double counting: + dm = S.G_iw.density() # compute the density matrix of the impurity problem + SK.calc_dc(dm, U_interact = U, J_hund = J, orb = 0, use_dc_formula = dc_type) + + # Save stuff into the user_data group of hdf5 archive in case of rerun: + SK.save(['chemical_potential','dc_imp','dc_energ']) + diff --git a/doc/tutorials/images_scripts/Sr2MgOsO6_noSOC_Sigmas.png b/doc/tutorials/images_scripts/Sr2MgOsO6_noSOC_Sigmas.png new file mode 100644 index 0000000000000000000000000000000000000000..d6c97c731d72d5879e0444ba1e165e8441d37d08 GIT binary patch literal 78192 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%0D=GWk{5=y{|9W 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 class, see section :ref:`blockstructure`. We first initialise the SumK class:: @@ -90,9 +93,9 @@ We can look at the diagonalisation matrix, it is:: [ 0. +0.j 0. +0.j 0. +0.j 0. +0.j 1. +0.j ]] >>> -This transformation is already stored in the SK.block_structure class. The next step is actually not needed for a DMFT calculation, but lets see what the transformation does to the local Hamiltonian. We can calculate it before rotation, rotate it, and look at the 2x2 block with off-diagonals:: +This transformation is already stored in the SK.block_structure class. The next step is actually not needed for a DMFT calculation, but it is good to do this check to see what the transformation does to the local Hamiltonian. We can calculate it before rotation, rotate it, and look at the 2x2 block with and without off-diagonals:: - eal = SK.eff_atomnic_levels() + eal = SK.eff_atomic_levels() eal2 = SK.block_structure.convert_matrix(eal[0],space_from='sumk', space_to='solver') print eal[0]['up'][1:3,1:3] # prints the 2x2 block with offiagonals @@ -104,6 +107,106 @@ This transformation is already stored in the SK.block_structure class. The next [0. -0.j 5.028+0.j]] So the local Hamiltonian has been diagonalised. From the other entries we can see that the *up_0* block and the [1,1] entry of the *up_1* block correspond to :math:`e_g`-like orbitals, and the others are the -:math:`t_{2g}` orbitals that we want to keep. +:math:`t_{2g}` orbitals that we want to keep. So we pick the according orbitals in the block structure:: -[TO BE CONTINUED...] + SK.block_structure.pick_gf_struct_solver([{'up_1': [0],'up_2': [0],'up_3': [0],'down_1': [0],'down_2': [0],'down_3': [0]}]) + +We can now look at the final result:: + + print SK.block_structure.convert_matrix(eal[0],space_from='sumk',space_to='solver') + {'up_2': array([[0.156-0.j]]), 'up_3': array([[0.156-0.j]]), 'up_1': array([[0.247-0.j]]), 'down_3': array([[0.156-0.j]]), 'down_2': array([[0.156-0.j]]), 'down_1': array([[0.247-0.j]])} + +We see that we arrived at a structure with 3 orbitals per spin only, and blocks of size 1x1. + +The interaction Hamiltonian +--------------------------- + +We now set up the interaction Hamiltonian. Since we want to rotate the interaction matrix into the local basis, we are using the Slater convention for it:: + + from pytriqs.operators.util import * + from pytriqs.operators.util.U_matrix import * + + U = 2.0 + J = 0.2 + U_mat = U_matrix(l=2,U_int=U,J_hund=J,basis='other', T=SK.T[0].conjugate()) + +In the last line we use the Wien2k convention to write the U matrix in the cubic harmonics. Next, we want to rotate it, and pick out only the relevant :math:`t_{2g}` orbitals. At this step we need to give the indices of the wanted orbitals in the *sumk* basis:: + + U_trans = transform_U_matrix(U_mat, SK.block_structure.transformation[0]['up'].conjugate()) + indices_to_pick_sumk = [1,3,4] # these are the relevant indices in the sumk basis + U_red = subarray(U_trans,len(U_trans.shape)*[indices_to_pick_sumk]) + h_int = h_int_slater(['up','down'], indices_to_pick_sumk, U_red, map_operator_structure=SK.block_structure.sumk_to_solver[0], off_diag=False, complex=False) + +Now we have the interaction Hamiltonian for the solver, which we set up next:: + + from triqs_cthyb import * + import pytriqs.utility.mpi as mpi + + beta = 40.0 + S = Solver(beta=beta, gf_struct=SK.block_structure.gf_struct_solver_list[0]) + + # Solver parameters: + p = {} + # solver + p["random_seed"] = 123 * mpi.rank + 567 + p["length_cycle"] = 200 + p["n_warmup_cycles"] = 100000 + p["n_cycles"] = 1000000 + # tail fit + p["perform_tail_fit"] = True + p["fit_max_moment"] = 4 + p["fit_min_n"] = 40 + p["fit_max_n"] = 100 + + +The DMFT loop with automatic basis rotations +-------------------------------------------- + +After these initialisation steps, the formal DMFT cycle is very similar to a calculation without these basis rotations, since these rotations are done automatically, once the :class:`BlockStructure` property *transformation* is set, see :ref:`basisrotation`. + +The DMFT loop itself looks very much the same as in :ref:`SrVO3`:: + + # double counting correction: + dc_type = 0 # FLL + # DMFT loops: + n_loops = 1 + + for iteration_number in range(1,n_loops+1): + + mpi.report("Iteration = %s"%iteration_number) + + SK.symm_deg_gf(S.Sigma_iw) # symmetrizing Sigma + SK.set_Sigma([ S.Sigma_iw ]) # put Sigma into the SumK class + chemical_potential = SK.calc_mu( precision = 0.01 ) # find the chemical potential for given density + S.G_iw << SK.extract_G_loc()[0] + + if (iteration_number==1): + # Put Hartree energy on Re Sigma + dm = S.G_iw.density() + SK.calc_dc(dm, U_interact = U, J_hund = J, orb = 0, use_dc_formula = dc_type) + S.Sigma_iw << SK.block_structure.convert_matrix(SK.dc_imp[0],space_from='sumk',space_to='solver')['up_1'][0,0] + + # Calculate new G0_iw to input into the solver: + S.G0_iw << S.Sigma_iw + inverse(S.G_iw) + S.G0_iw << inverse(S.G0_iw) + + # Solve the impurity problem: + S.solve(h_int=h_int, **p) + + # Solved. Now do post-solution stuff: + # Set the new double counting: + dm = S.G_iw.density() # compute the density matrix of the impurity problem + SK.calc_dc(dm, U_interact = U, J_hund = J, orb = 0, use_dc_formula = dc_type) + + # Save stuff into the user_data group of hdf5 archive in case of rerun: + SK.save(['chemical_potential','dc_imp','dc_energ']) + +The only difference to the other example is in the initialisation of the real part of the self energy. We cannot just take an element of the *dc_imp* array, since this array is stored in the *sumk* structure. Therefore, we first need to transform this matrix into *solver* space, and then take the appropriate matrix element. After the first iteration (here done with 24e6 MC sweeps), you should get self energies like this: + +.. image:: images_scripts/Sr2MgOsO6_noSOC_Sigmas.png + :width: 600 + :align: center + +The two :math:`d_{xz}` and :math:`d_{yz}` orbitals are degenerate (blocks *up_2* and *up_3*), whereas the :math:`d_{xy}`-like orbital is different. + +A complete python script for this tutorial, including some more input/output, is available (:download:`Sr2MgOsO6_noSOC.py `). When running the script, you will encounter warnings during the transformation from the *sumk* to the *solver* basis. These warnings just reflect that the off-diagonal elements of the full Greens function are not zero at all frequencies, although the local Hamiltonian is. In that sense, we still do an approximation when restricting ourselves to the :math:`t_{2g}`-like orbitals. \ No newline at end of file From 85d4664d9698533fbe35caef503b0377eb0995f5 Mon Sep 17 00:00:00 2001 From: aichhorn Date: Mon, 27 Apr 2020 16:22:11 +0200 Subject: [PATCH 52/57] started SOC tutorial --- doc/tutorials.rst | 10 + .../images_scripts/Sr2MgOsO6_SOC.indmftpr | 20 ++ .../images_scripts/Sr2MgOsO6_SOC.outdmftpr | 31 +++ .../images_scripts/Sr2MgOsO6_SOC_DOS.png | Bin 0 -> 11563 bytes doc/tutorials/sr2mgoso6_soc.rst | 214 ++++++++++++++++++ 5 files changed, 275 insertions(+) create mode 100644 doc/tutorials/images_scripts/Sr2MgOsO6_SOC.indmftpr create mode 100644 doc/tutorials/images_scripts/Sr2MgOsO6_SOC.outdmftpr create mode 100644 doc/tutorials/images_scripts/Sr2MgOsO6_SOC_DOS.png create mode 100644 doc/tutorials/sr2mgoso6_soc.rst diff --git a/doc/tutorials.rst b/doc/tutorials.rst index c24133fd..a5dd7ea8 100644 --- a/doc/tutorials.rst +++ b/doc/tutorials.rst @@ -22,6 +22,16 @@ Basis rotations: Sr2MgOsO6 without SOC tutorials/sr2mgoso6_nosoc + +Sr2MgOsO6 with SOC (non-magnetic) +--------------------------------- + +.. toctree:: + :maxdepth: 2 + + tutorials/sr2mgoso6_soc + + Full charge self consistency with Wien2k: :math:`\gamma`-Ce ----------------------------------------------------------- diff --git a/doc/tutorials/images_scripts/Sr2MgOsO6_SOC.indmftpr b/doc/tutorials/images_scripts/Sr2MgOsO6_SOC.indmftpr new file mode 100644 index 00000000..de341fa1 --- /dev/null +++ b/doc/tutorials/images_scripts/Sr2MgOsO6_SOC.indmftpr @@ -0,0 +1,20 @@ +5 ! Nsort +2 1 1 4 2 ! Mult(Nsort) +3 ! lmax +complex ! choice of angular harmonics +0 0 0 0 ! l included for each sort +0 0 0 0 ! If split into ireps, gives number of ireps. for a given orbital (otherwise 0) +cubic ! choice of angular harmonics +0 0 2 0 ! l included for each sort +0 0 0 0 ! If split into ireps, gives number of ireps. for a given orbital (otherwise 0) +1 ! SO flag +complex ! choice of angular harmonics +0 0 0 0 ! l included for each sort +0 0 0 0 ! If split into ireps, gives number of ireps. for a given orbital (otherwise 0) +complex ! choice of angular harmonics +0 0 0 0 ! l included for each sort +0 0 0 0 ! If split into ireps, gives number of ireps. for a given orbital (otherwise 0) +complex +0 0 0 0 +0 0 0 0 +-0.09 0.43 diff --git a/doc/tutorials/images_scripts/Sr2MgOsO6_SOC.outdmftpr b/doc/tutorials/images_scripts/Sr2MgOsO6_SOC.outdmftpr new file mode 100644 index 00000000..815e1920 --- /dev/null +++ b/doc/tutorials/images_scripts/Sr2MgOsO6_SOC.outdmftpr @@ -0,0 +1,31 @@ +Density Matrices for the Correlated States : + + Sort = 2 Atom = 3 and Orbital l = 2 +Writing the matrix as : [ block up/up | block up/dn ] with + [ block dn/up | block dn/dn ] + # For the Up/Up block : + 0.003574 0.000000 0.000000 -0.000000 -0.000000 -0.000000 -0.000000 0.000000 -0.000000 -0.000000 + 0.000000 0.000000 0.254943 -0.000000 -0.020080 0.048438 -0.000000 -0.000000 -0.000000 -0.000000 + -0.000000 0.000000 -0.020080 -0.048438 0.011530 0.000000 0.000000 -0.000000 0.000000 -0.000000 + -0.000000 -0.000000 -0.000000 0.000000 0.000000 0.000000 0.363933 -0.000000 0.157594 -0.000000 + -0.000000 0.000000 -0.000000 0.000000 0.000000 0.000000 0.157594 -0.000000 0.363933 -0.000000 + # For the Down/Down block : + 0.003574 0.000000 0.000000 0.000000 0.000000 -0.000000 -0.000000 -0.000000 0.000000 -0.000000 + 0.000000 -0.000000 0.254943 0.000000 0.020080 0.048438 -0.000000 0.000000 0.000000 -0.000000 + 0.000000 0.000000 0.020080 -0.048438 0.011530 -0.000000 -0.000000 -0.000000 0.000000 0.000000 + -0.000000 0.000000 -0.000000 -0.000000 -0.000000 0.000000 0.363933 0.000000 -0.157594 -0.000000 + 0.000000 0.000000 0.000000 0.000000 0.000000 -0.000000 -0.157594 -0.000000 0.363933 0.000000 + # For the Up/Down block : + -0.000000 0.000000 0.000000 -0.000000 0.000000 0.000000 0.028268 0.000554 -0.028268 -0.000554 + -0.000000 0.000000 -0.000000 -0.000000 -0.000000 -0.000000 -0.111512 0.018026 -0.111512 0.018026 + 0.000000 0.000000 -0.000000 -0.000000 -0.000000 0.000000 0.014697 0.018147 0.014697 0.018147 + -0.028268 -0.000554 0.111512 -0.018026 0.014697 0.018147 -0.000000 -0.000000 0.000000 0.000000 + -0.028268 -0.000554 -0.111512 0.018026 -0.014697 -0.018147 0.000000 0.000000 -0.000000 0.000000 + # For the Down/Up block : + -0.000000 -0.000000 -0.000000 -0.000000 0.000000 -0.000000 -0.028268 0.000554 -0.028268 0.000554 + 0.000000 0.000000 -0.000000 0.000000 -0.000000 0.000000 0.111512 0.018026 -0.111512 -0.018026 + 0.000000 -0.000000 -0.000000 0.000000 -0.000000 -0.000000 0.014697 -0.018147 -0.014697 0.018147 + 0.028268 -0.000554 -0.111512 -0.018026 0.014697 -0.018147 -0.000000 0.000000 0.000000 -0.000000 + -0.028268 0.000554 -0.111512 -0.018026 0.014697 -0.018147 0.000000 -0.000000 -0.000000 -0.000000 + +The charge of the orbital is : 1.99583 diff --git a/doc/tutorials/images_scripts/Sr2MgOsO6_SOC_DOS.png b/doc/tutorials/images_scripts/Sr2MgOsO6_SOC_DOS.png new file mode 100644 index 0000000000000000000000000000000000000000..20a6f078bf681f90ce1ea6c7917149790cfa42d6 GIT binary patch literal 11563 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 literal 0 HcmV?d00001 diff --git a/doc/tutorials/sr2mgoso6_soc.rst b/doc/tutorials/sr2mgoso6_soc.rst new file mode 100644 index 00000000..596e7d29 --- /dev/null +++ b/doc/tutorials/sr2mgoso6_soc.rst @@ -0,0 +1,214 @@ +.. _Sr2MgOsO6_SOC: + +In this tutorial we will discuss how to set up and perform a calculation including spin-orbit coupling. As an example, we again take Sr2MgOsO6, as we used for the discussion of basis rotations (:ref:`Sr2MgOsO6_noSOC`). + + +The full script for this calculation is also provided here (:download:`Sr2MgOsO6_SOC.py `). + +DFT (Wien2k) and Wannier orbitals +================================= + +DFT setup +--------- + +First, we do the DFT calculation, using the Wien2k package. As main input file we have to provide the struct file :file:`Sr2MgOs6_noSOC.struct`: + +.. literalinclude:: images_scripts/Sr2MgOsO6_noSOC.struct + +The struct file is the same as for non SOC calculations. However, the DFT calculation is done a bit differently now. First, we need to do a spin-polarised DFT calculation, but with magnetic moment set to zero. In the Wien2k initialisation procedure, one can choose for the option -nom when ``lstart`` is called. This means that the charge densities are initialised without magnetic splitting. After initialisation, do a full SC DFT run:: + + runsp + +After this SC cycled finished, we continue with the spin-orbit calculation. We initialise it with the Wien2k command:: + + init_so + +In this initialisation procedure, be sure to select a spin-polarised calculation. Then the SC cycle including SOC is done by:: + + runsp -so + +After the SC cycled finished, you can calculate the DOS with SOC iuncluded. It should look like what you can see in this figure: + +.. image:: images_scripts/Sr2MgOsO6_SOC_DOS.png + :width: 700 + :align: center + +Wannier orbitals +---------------- + +As a next step, we calculate localised orbitals for the d orbitals. We use this input file for :program:`dmftproj`: + +.. literalinclude:: images_scripts/Sr2MgOsO6_SOC.indmftpr + +Note that, due to the distortions in the crystal structure and the SOC, we include all five d orbitals in the calculation (line 8 in the input file above). The projection window is set such that all d orbitals are included. + +To prepare the input data for :program:`dmftproj` we execute lapw2 with the following options:: + + x lapw2 -up -c -so -almd + x lapw2 -dn -c -so -almd + +Then :program:`dmftproj` is executed for SOC:: + + dmftproj -sp -so + +At the end of the run you see the density matrix in Wannier space: + +.. literalinclude:: images_scripts/Sr2MgOsO6_SOC.outdmftpr + +As you can see, there are a lot of off-diagonal elements now, in particular also off-diagonal in spin space. This is just telling us that spin is not a good quantum number any more in the presence of SOC. + +We convert the output to the hdf5 archive, using +the python module :class:`Wien2kConverter `. A simple python script doing this is:: + + from triqs_dft_tools.converters.wien2k_converter import * + Converter = Wien2kConverter(filename = "Sr2MgOsO6_SOC") + Converter.convert_dft_input() + +This reads all the data, and stores everything that is necessary for the DMFT calculation in the file :file:`Sr2MgOsO6_SOC.h5`. + +The DMFT calculation +==================== + +[TBC] + +Rotating the basis +------------------ + +Before starting the DMFT calculation it is beneficial to look a bit more closely at the block structure of the problem. Eventually, we want to use a basis that is as diagonal as possible, and include only the partially filled orbitals in the correlated problem. All this can be done using the functionalities of the :class:`BlockStructure ` class, see section :ref:`blockstructure`. + +We first initialise the SumK class:: + + from triqs_dft_tools.sumk_dft import * + SK = SumkDFT(hdf_file='Sr2MgOsO6_SOC.h5',use_dft_blocks=True) + +The flag *use_dft_blocks=True* determines, as usual, the smallest possible blocks with non-zero entries, and initialises them as *solver* block structure. In order to disentangle the :math:`d_{x^2-y^2}` and the :math:`d_{xy}` orbitals, and pick out only the partially filled one, we do a transformation into a basis where the local Hamiltonian is diagonal:: + + mat = SK.calculate_diagonalization_matrix(prop_to_be_diagonal='eal',calc_in_solver_blocks=True) + +We can look at the diagonalisation matrix, it is:: + + >>> print mat[0]['down'] + [[ 1. +0.j 0. +0.j 0. +0.j 0. +0.j 0. +0.j ] + [ 0. +0.j -0.985+0.j 0. -0.173j 0. +0.j 0. +0.j ] + [ 0. +0.j 0.173+0.j 0. -0.985j 0. +0.j 0. +0.j ] + [ 0. +0.j 0. +0.j 0. +0.j 1. +0.j 0. +0.j ] + [ 0. +0.j 0. +0.j 0. +0.j 0. +0.j 1. +0.j ]] + >>> + +This transformation is already stored in the SK.block_structure class. The next step is actually not needed for a DMFT calculation, but it is good to do this check to see what the transformation does to the local Hamiltonian. We can calculate it before rotation, rotate it, and look at the 2x2 block with and without off-diagonals:: + + eal = SK.eff_atomic_levels() + eal2 = SK.block_structure.convert_matrix(eal[0],space_from='sumk', space_to='solver') + + print eal[0]['up'][1:3,1:3] # prints the 2x2 block with offiagonals + [[ 0.391+0.j -0. -0.815j] + [-0. +0.815j 4.884-0.j ]] + + print eal2['up_1'] # prints the 2x2 block after rotation + [[0.247-0.j 0. +0.j] + [0. -0.j 5.028+0.j]] + +So the local Hamiltonian has been diagonalised. From the other entries we can see that the *up_0* block and the [1,1] entry of the *up_1* block correspond to :math:`e_g`-like orbitals, and the others are the +:math:`t_{2g}` orbitals that we want to keep. So we pick the according orbitals in the block structure:: + + SK.block_structure.pick_gf_struct_solver([{'up_1': [0],'up_2': [0],'up_3': [0],'down_1': [0],'down_2': [0],'down_3': [0]}]) + +We can now look at the final result:: + + print SK.block_structure.convert_matrix(eal[0],space_from='sumk',space_to='solver') + {'up_2': array([[0.156-0.j]]), 'up_3': array([[0.156-0.j]]), 'up_1': array([[0.247-0.j]]), 'down_3': array([[0.156-0.j]]), 'down_2': array([[0.156-0.j]]), 'down_1': array([[0.247-0.j]])} + +We see that we arrived at a structure with 3 orbitals per spin only, and blocks of size 1x1. + +The interaction Hamiltonian +--------------------------- + +We now set up the interaction Hamiltonian. Since we want to rotate the interaction matrix into the local basis, we are using the Slater convention for it:: + + from pytriqs.operators.util import * + from pytriqs.operators.util.U_matrix import * + + U = 2.0 + J = 0.2 + U_mat = U_matrix(l=2,U_int=U,J_hund=J,basis='other', T=SK.T[0].conjugate()) + +In the last line we use the Wien2k convention to write the U matrix in the cubic harmonics. Next, we want to rotate it, and pick out only the relevant :math:`t_{2g}` orbitals. At this step we need to give the indices of the wanted orbitals in the *sumk* basis:: + + U_trans = transform_U_matrix(U_mat, SK.block_structure.transformation[0]['up'].conjugate()) + indices_to_pick_sumk = [1,3,4] # these are the relevant indices in the sumk basis + U_red = subarray(U_trans,len(U_trans.shape)*[indices_to_pick_sumk]) + h_int = h_int_slater(['up','down'], indices_to_pick_sumk, U_red, map_operator_structure=SK.block_structure.sumk_to_solver[0], off_diag=False, complex=False) + +Now we have the interaction Hamiltonian for the solver, which we set up next:: + + from triqs_cthyb import * + import pytriqs.utility.mpi as mpi + + beta = 40.0 + S = Solver(beta=beta, gf_struct=SK.block_structure.gf_struct_solver_list[0]) + + # Solver parameters: + p = {} + # solver + p["random_seed"] = 123 * mpi.rank + 567 + p["length_cycle"] = 200 + p["n_warmup_cycles"] = 100000 + p["n_cycles"] = 1000000 + # tail fit + p["perform_tail_fit"] = True + p["fit_max_moment"] = 4 + p["fit_min_n"] = 40 + p["fit_max_n"] = 100 + + +The DMFT loop with automatic basis rotations +-------------------------------------------- + +After these initialisation steps, the formal DMFT cycle is very similar to a calculation without these basis rotations, since these rotations are done automatically, once the :class:`BlockStructure` property *transformation* is set, see :ref:`basisrotation`. + +The DMFT loop itself looks very much the same as in :ref:`SrVO3`:: + + # double counting correction: + dc_type = 0 # FLL + # DMFT loops: + n_loops = 1 + + for iteration_number in range(1,n_loops+1): + + mpi.report("Iteration = %s"%iteration_number) + + SK.symm_deg_gf(S.Sigma_iw) # symmetrizing Sigma + SK.set_Sigma([ S.Sigma_iw ]) # put Sigma into the SumK class + chemical_potential = SK.calc_mu( precision = 0.01 ) # find the chemical potential for given density + S.G_iw << SK.extract_G_loc()[0] + + if (iteration_number==1): + # Put Hartree energy on Re Sigma + dm = S.G_iw.density() + SK.calc_dc(dm, U_interact = U, J_hund = J, orb = 0, use_dc_formula = dc_type) + S.Sigma_iw << SK.block_structure.convert_matrix(SK.dc_imp[0],space_from='sumk',space_to='solver')['up_1'][0,0] + + # Calculate new G0_iw to input into the solver: + S.G0_iw << S.Sigma_iw + inverse(S.G_iw) + S.G0_iw << inverse(S.G0_iw) + + # Solve the impurity problem: + S.solve(h_int=h_int, **p) + + # Solved. Now do post-solution stuff: + # Set the new double counting: + dm = S.G_iw.density() # compute the density matrix of the impurity problem + SK.calc_dc(dm, U_interact = U, J_hund = J, orb = 0, use_dc_formula = dc_type) + + # Save stuff into the user_data group of hdf5 archive in case of rerun: + SK.save(['chemical_potential','dc_imp','dc_energ']) + +The only difference to the other example is in the initialisation of the real part of the self energy. We cannot just take an element of the *dc_imp* array, since this array is stored in the *sumk* structure. Therefore, we first need to transform this matrix into *solver* space, and then take the appropriate matrix element. After the first iteration (here done with 24e6 MC sweeps), you should get self energies like this: + +.. image:: images_scripts/Sr2MgOsO6_noSOC_Sigmas.png + :width: 600 + :align: center + +The two :math:`d_{xz}` and :math:`d_{yz}` orbitals are degenerate (blocks *up_2* and *up_3*), whereas the :math:`d_{xy}`-like orbital is different. + +A complete python script for this tutorial, including some more input/output, is available (:download:`Sr2MgOsO6_noSOC.py `). When running the script, you will encounter warnings during the transformation from the *sumk* to the *solver* basis. These warnings just reflect that the off-diagonal elements of the full Greens function are not zero at all frequencies, although the local Hamiltonian is. In that sense, we still do an approximation when restricting ourselves to the :math:`t_{2g}`-like orbitals. \ No newline at end of file From 37ccb46a8ccd277237a0286a546c0d1b1c134693 Mon Sep 17 00:00:00 2001 From: hschnait Date: Wed, 29 Apr 2020 16:13:06 +0200 Subject: [PATCH 53/57] Add convert_operator method to block_structure + Tests --- python/block_structure.py | 44 ++++++++++++++++++++++++++++++++++++ test/basis_transformation.py | 29 ++++++++++++++++++++++++ 2 files changed, 73 insertions(+) diff --git a/python/block_structure.py b/python/block_structure.py index 4b40a69a..86147109 100644 --- a/python/block_structure.py +++ b/python/block_structure.py @@ -769,6 +769,50 @@ class BlockStructure(object): "block " + block + \ " has wrong indices (shell {})".format(ish) + def convert_operator(self, O, ish=0): + """ Converts a second-quantization operator from sumk structure + to solver structure. + + Parameters + ---------- + O : pytriqs.operators.Operator + Operator in sumk structure + + ish : int + shell index on which the operator acts + """ + + from pytriqs.operators import Operator, c, c_dag + + T = self.transformation[ish] + sk2s = self.sumk_to_solver[ish] + + O_out = Operator(0) + + for monomial in O: + coefficient = monomial[-1] + new_monomial = Operator(1) + #if coefficient > 1e-10: + for single_operator in monomial[0]: + new_single_operator = Operator(0) + daggered = single_operator[0] + + blockname = single_operator[1][0] + i = single_operator[1][1] + for j in range(len(T[blockname])): + if sk2s[(blockname, j)] != (None, None): + if daggered: + new_single_operator += (T[blockname][j,i] * c_dag(*sk2s[(blockname, j)])) + else: + new_single_operator += (T[blockname][j,i].conjugate() * c(*sk2s[(blockname, j)])) + + new_monomial *= new_single_operator + + O_out += new_monomial * coefficient + return O_out + + + 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): """ Convert BlockGf from its structure to this structure. diff --git a/test/basis_transformation.py b/test/basis_transformation.py index dd0ddd46..05586a2d 100644 --- a/test/basis_transformation.py +++ b/test/basis_transformation.py @@ -68,3 +68,32 @@ dm = SK.density_matrix(method='using_point_integration') for dmi in dm: for e in dmi: assert is_diagonal_matrix(np.dot(np.dot(t_solver_dm[0][e], dmi[e].conj().T),t_solver_dm[0][e].conj().T)) + + +# Test convert_operator +SK = SumkDFT(hdf_file = 'SrVO3.h5', use_dft_blocks=True) +BS = SK.block_structure +from pytriqs.operators.util import h_int_slater, U_matrix, t2g_submatrix, transform_U_matrix + + +U3x3 = t2g_submatrix(U_matrix(2, U_int=2, J_hund=0.2, basis='spheric')) + +BS.transformation = [{'up':np.eye(3), 'down': np.eye(3)}] +H0 = h_int_slater(spin_names=['up','down'], orb_names=range(3), U_matrix=U3x3, off_diag=False) +H1 = h_int_slater(spin_names=['up','down'], orb_names=range(3), U_matrix=U3x3, off_diag=True) +assert( H0 == BS.convert_operator(H1) ) + +# Trafo Matrix switching index 1 & 2 +BS.transformation = [{'up':np.array([[1,0,0],[0,0,1],[0,1,0]]), 'down': np.array([[1,0,0],[0,0,1],[0,1,0]])}] +H2 = BS.convert_operator(h_int_slater(spin_names=['up','down'], orb_names=[0,2,1], U_matrix=U3x3, off_diag=True)) +assert( H0 == H2 ) + +BS.transformation = [{'up':np.array([[1,0,0],[0,1/np.sqrt(2),1/np.sqrt(2)],[0,1/np.sqrt(2),-1/np.sqrt(2)]]), 'down': np.array([[1,0,0],[0,1/np.sqrt(2),1/np.sqrt(2)],[0,1/np.sqrt(2),-1/np.sqrt(2)]])}] +H3 = BS.convert_operator(h_int_slater(spin_names=['up','down'], orb_names=[0,1,2], U_matrix=U3x3, off_diag=True)) +for op in H3: + for c_op in op[0]: + assert(BS.gf_struct_solver_dict[0][c_op[1][0]][c_op[1][1]] is not None) # This crashes with a key error if the operator structure is not the solver structure + +U_trafod = transform_U_matrix(U3x3, BS.transformation[0]['up'].conjugate()) # The notorious .conjugate() +H4 = h_int_slater(spin_names=['up','down'], orb_names=range(3), U_matrix=U_trafod, map_operator_structure=BS.sumk_to_solver[0]) +assert( H4 == H3 ) # check that convert_operator does the same as transform_U_matrix From 4b09b97ce4a1f33adb7be4ea7cb57453a18e72f7 Mon Sep 17 00:00:00 2001 From: aichhorn Date: Thu, 30 Apr 2020 12:47:03 +0200 Subject: [PATCH 54/57] Included block_structure.convert_operator() in doc and non-SOC tutorial --- doc/guide/BasisRotation.rst | 18 +++++++++++++----- .../images_scripts/Sr2MgOsO6_noSOC.py | 14 +++++--------- doc/tutorials/sr2mgoso6_nosoc.rst | 13 +++++++------ 3 files changed, 25 insertions(+), 20 deletions(-) diff --git a/doc/guide/BasisRotation.rst b/doc/guide/BasisRotation.rst index 88108f1e..b0df7fc4 100644 --- a/doc/guide/BasisRotation.rst +++ b/doc/guide/BasisRotation.rst @@ -67,8 +67,16 @@ done automatically, meaning that :class:`SumkDFT`'s :meth:`extract_G_loc`, :meth S.G_iw << SK.extract_G_loc()[0] .. warning:: - Before doing the DMFT self-consistency loop, one must not forget to also transform the interaction Hamiltonian to the diagonal basis! - This can be done with the :meth:`transform_U_matrix` method. However, due to different - conventions in this method, one must pass the conjugated version of the transformation matrix:: - - U_trans = transform_U_matrix(U, SK.block_structure.transformation[0]['ud'].conjugate()) + Before doing the DMFT self-consistency loop, one must not forget to also transform the + interaction Hamiltonian to the diagonal basis! + This can be also be done with a method of the :class:`BlockStructure` class, + namely the :meth:`convert_operator` method. Having set up a Hamiltonian in the *sumk* structure, it can easily + be transformed to the *solver* structure (including rotations of basis, picking of orbitals, + making matrices diagonal, etc) by:: + + H_solver = SK.block_structure.convert_operator(H_sumk) + + We refer to the tutorials on how to set up the Hamiltonian H_sumk in selected cases. + Note that this transformation might generally lead to complex values in the + interaction Hamiltonian. Unless you know better and can make everything real, + you should take care of using the correct version of the TRIQS CTQMC solver. \ No newline at end of file diff --git a/doc/tutorials/images_scripts/Sr2MgOsO6_noSOC.py b/doc/tutorials/images_scripts/Sr2MgOsO6_noSOC.py index 232c087d..8740b061 100644 --- a/doc/tutorials/images_scripts/Sr2MgOsO6_noSOC.py +++ b/doc/tutorials/images_scripts/Sr2MgOsO6_noSOC.py @@ -23,22 +23,18 @@ SK.calculate_diagonalization_matrix(prop_to_be_diagonal='eal',calc_in_solver_blo # Now we pick the orbitals: # BE CAREFUL: THIS NEEDS TO BE DONE PROPERLY # AND IS DIFFERENT FORM CASE TO CASE! -indices_to_pick_sumk = [1,3,4] SK.block_structure.pick_gf_struct_solver([{'up_1': [0],'up_2': [0],'up_3': [0],'down_1': [0],'down_2': [0],'down_3': [0]}]) ########################### -# Now we set up the U matrix, first in cubic (Wien2k) convention: +# Now we set up the U matrix, first in cubic Wien2k convention: U = 2.0 J = 0.2 U_mat = U_matrix(l=2,U_int=U,J_hund=J,basis='other', T=SK.T[0].conjugate()) -# Now we transform the U Matrix: -U_trans = transform_U_matrix(U_mat, SK.block_structure.transformation[0]['up'].conjugate()) -# pick out the relevant orbitals: -U_red = subarray(U_trans,len(U_trans.shape)*[indices_to_pick_sumk]) - -# Finally, set up the Hamiltonian: -h_int = h_int_slater(['up','down'], indices_to_pick_sumk, U_red, map_operator_structure=SK.block_structure.sumk_to_solver[0], off_diag=False, complex=False) +# Now we set up the Hamiltonian: +h_sumk = h_int_slater(['up','down'], range(5), U_mat, off_diag=True) +# And now we rotate into solver space: +h_int = SK.block_structure.convert_operator(h_sumk) # Solver Init: beta = 40.0 diff --git a/doc/tutorials/sr2mgoso6_nosoc.rst b/doc/tutorials/sr2mgoso6_nosoc.rst index 6902fef0..534e5cd2 100644 --- a/doc/tutorials/sr2mgoso6_nosoc.rst +++ b/doc/tutorials/sr2mgoso6_nosoc.rst @@ -130,12 +130,13 @@ We now set up the interaction Hamiltonian. Since we want to rotate the interacti J = 0.2 U_mat = U_matrix(l=2,U_int=U,J_hund=J,basis='other', T=SK.T[0].conjugate()) -In the last line we use the Wien2k convention to write the U matrix in the cubic harmonics. Next, we want to rotate it, and pick out only the relevant :math:`t_{2g}` orbitals. At this step we need to give the indices of the wanted orbitals in the *sumk* basis:: +In the last line we use the Wien2k convention to write the U matrix in the cubic harmonics. Next, we want to set up a Hamiltonian and rotate it into the *solver* basis:: - U_trans = transform_U_matrix(U_mat, SK.block_structure.transformation[0]['up'].conjugate()) - indices_to_pick_sumk = [1,3,4] # these are the relevant indices in the sumk basis - U_red = subarray(U_trans,len(U_trans.shape)*[indices_to_pick_sumk]) - h_int = h_int_slater(['up','down'], indices_to_pick_sumk, U_red, map_operator_structure=SK.block_structure.sumk_to_solver[0], off_diag=False, complex=False) + h_sumk = h_int_slater(['up','down'], range(5), U_mat, off_diag=True) + h_int = SK.block_structure.convert_operator(h_sumk) + h_int = h_int.real + +Note that we needed to set up the interaction matrix for the full set of five *d* orbitals. The :meth:`convert_operator` method then takes care of rotating and picking the relevant orbitals. In the last line above we made the Hamiltonian real, since we know it this case that there are only real numbers in the interaction Hamiltonian. Note that this is not generally the case! Now we have the interaction Hamiltonian for the solver, which we set up next:: @@ -201,7 +202,7 @@ The DMFT loop itself looks very much the same as in :ref:`SrVO3`:: # Save stuff into the user_data group of hdf5 archive in case of rerun: SK.save(['chemical_potential','dc_imp','dc_energ']) -The only difference to the other example is in the initialisation of the real part of the self energy. We cannot just take an element of the *dc_imp* array, since this array is stored in the *sumk* structure. Therefore, we first need to transform this matrix into *solver* space, and then take the appropriate matrix element. After the first iteration (here done with 24e6 MC sweeps), you should get self energies like this: +The only difference to the other example is in the initialisation of the real part of the self energy. We cannot just take an element of the *dc_imp* array, since this array is stored in the *sumk* structure. Therefore, we first need to transform this matrix into *solver* space, and then take the appropriate matrix element. After the first iteration (here done with 24e6 MC sweeps and using the real version of the CTMQC solver), you should get self energies like this: .. image:: images_scripts/Sr2MgOsO6_noSOC_Sigmas.png :width: 600 From 0ce04d34a7ad9ecdd599771082ec5d9941624b9c Mon Sep 17 00:00:00 2001 From: aichhorn Date: Tue, 5 May 2020 10:29:13 +0200 Subject: [PATCH 55/57] finished SOC tutorial --- doc/tutorials/images_scripts/Sr2MgOsO6_SOC.py | 112 ++++++++++++++++++ .../images_scripts/Sr2MgOsO6_SOC_Sigmas.png | Bin 0 -> 26720 bytes doc/tutorials/sr2mgoso6_nosoc.rst | 2 +- doc/tutorials/sr2mgoso6_soc.rst | 101 +++++++++------- 4 files changed, 170 insertions(+), 45 deletions(-) create mode 100644 doc/tutorials/images_scripts/Sr2MgOsO6_SOC.py create mode 100644 doc/tutorials/images_scripts/Sr2MgOsO6_SOC_Sigmas.png diff --git a/doc/tutorials/images_scripts/Sr2MgOsO6_SOC.py b/doc/tutorials/images_scripts/Sr2MgOsO6_SOC.py new file mode 100644 index 00000000..fe07a9a7 --- /dev/null +++ b/doc/tutorials/images_scripts/Sr2MgOsO6_SOC.py @@ -0,0 +1,112 @@ +# Import the modules: +from triqs_dft_tools.sumk_dft import * +from pytriqs.gf import * +from pytriqs.archive import HDFArchive +from pytriqs.operators.util import * +from pytriqs.operators.util.U_matrix import * +from triqs_cthyb import * +import pytriqs.utility.mpi as mpi + +# Init the SumK class: +filename = 'Sr2MgOsO6_SOC.h5' +SK = SumkDFT(hdf_file=filename,use_dft_blocks=True) + +# Find diagonal local basis set: +SK.calculate_diagonalization_matrix(prop_to_be_diagonal='eal',calc_in_solver_blocks=True) + +########################### +# Now we pick the orbitals: +# BE CAREFUL: THIS NEEDS TO BE DONE PROPERLY +# AND IS DIFFERENT FORM CASE TO CASE! +SK.block_structure.pick_gf_struct_solver([{'ud_0': [0,1,2],'ud_1': [0,1,2]}]) +########################### + +# Now we set up the U matrix, first in cubic (Wien2k) convention: +U = 2.0 +J = 0.2 +U_sph = U_matrix(l=2, U_int=U, J_hund=J) +U_sph = np.kron(np.reshape(np.eye(2),(1,2,1,2)),np.kron(np.reshape(np.eye(2),(2,1,2,1)),U_sph)) +U_mat = transform_U_matrix(U_sph, SK.T[0].conjugate()) + +# Now we set up the interaction Hamiltonian +h_sumk = h_int_slater(['ud'], range(10), U_mat, off_diag=True, complex=True) +# And convert it to the solver structure +h_int = SK.block_structure.convert_operator(h_sumk) + +# Solver Init: +beta = 40.0 +S = Solver(beta=beta, gf_struct=SK.block_structure.gf_struct_solver_list[0]) + +# Solver parameters: +p = {} +# solver +p["random_seed"] = 123 * mpi.rank + 567 +p["length_cycle"] = 200 +p["n_warmup_cycles"] = 100000 +p["n_cycles"] = 3000000 +# tail fit +p["perform_tail_fit"] = True +p["fit_max_moment"] = 4 +p["fit_min_w"] = 4.0 +p["fit_max_w"] = 8.0 + +# double counting correction: +dc_type = 0 # FLL +# DMFT loops: +n_loops = 1 + +#for first iteration, add the outout group: +if mpi.is_master_node(): + with HDFArchive(filename) as ar: + if (not ar.is_group('dmft_output')): + ar.create_group('dmft_output') + +for iteration_number in range(1,n_loops+1): + + mpi.report("Iteration = %s"%iteration_number) + + SK.set_Sigma([ S.Sigma_iw ]) # put Sigma into the SumK class + chemical_potential = SK.calc_mu( precision = 0.01 ) # find the chemical potential for given density + S.G_iw << SK.extract_G_loc()[0] + + if (iteration_number==1): + # Put Hartree energy on Re Sigma + dm = S.G_iw.density() + SK.calc_dc(dm, U_interact = U, J_hund = J, orb = 0, use_dc_formula = dc_type) + S.Sigma_iw << SK.block_structure.convert_matrix(SK.dc_imp[0],space_from='sumk',space_to='solver')['ud_0'][0,0] + + mpi.report("Orbital densities of local Green function :") + for s,gf in S.G_iw: + mpi.report("Orbital %s: %s"%(s,dm[s].real)) + mpi.report("Total charge of Gloc : %.6f"%S.G_iw.total_density().real) + + # Calculate new G0_iw to input into the solver: + S.G0_iw << S.Sigma_iw + inverse(S.G_iw) + S.G0_iw << inverse(S.G0_iw) + + # Solve the impurity problem: + S.solve(h_int=h_int, **p) + + # Solved. Now do post-solution stuff: + dm = S.G_iw.density() + mpi.report("Orbital densities of impurity Green function:") + for s,gf in S.G_iw: + mpi.report("Orbital %s: %s"%(s,dm[s].real)) + mpi.report("Total charge of impurity problem : %.6f"%S.G_iw.total_density().real) + + # Write the final Sigma and G to the hdf5 archive: + if mpi.is_master_node(): + with HDFArchive(filename) as ar: + ar['dmft_output']['iterations'] = iteration_number + ar['dmft_output']['G_0'] = S.G0_iw + ar['dmft_output']['G_tau'] = S.G_tau + ar['dmft_output']['G_iw'] = S.G_iw + ar['dmft_output']['Sigma_iw_%s'%iteration_number] = S.Sigma_iw + + # Set the new double counting: + dm = S.G_iw.density() # compute the density matrix of the impurity problem + SK.calc_dc(dm, U_interact = U, J_hund = J, orb = 0, use_dc_formula = dc_type) + + # Save stuff into the user_data group of hdf5 archive in case of rerun: + SK.save(['chemical_potential','dc_imp','dc_energ']) + diff --git a/doc/tutorials/images_scripts/Sr2MgOsO6_SOC_Sigmas.png b/doc/tutorials/images_scripts/Sr2MgOsO6_SOC_Sigmas.png new file mode 100644 index 0000000000000000000000000000000000000000..7147695d860c912bf8d0f8476fe615f706ceb75b GIT binary patch literal 26720 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 print mat[0]['down'] - [[ 1. +0.j 0. +0.j 0. +0.j 0. +0.j 0. +0.j ] - [ 0. +0.j -0.985+0.j 0. -0.173j 0. +0.j 0. +0.j ] - [ 0. +0.j 0.173+0.j 0. -0.985j 0. +0.j 0. +0.j ] - [ 0. +0.j 0. +0.j 0. +0.j 1. +0.j 0. +0.j ] - [ 0. +0.j 0. +0.j 0. +0.j 0. +0.j 1. +0.j ]] - >>> - -This transformation is already stored in the SK.block_structure class. The next step is actually not needed for a DMFT calculation, but it is good to do this check to see what the transformation does to the local Hamiltonian. We can calculate it before rotation, rotate it, and look at the 2x2 block with and without off-diagonals:: +This transformation is stored in the SK.block_structure class and can be used to transform Greens function or operators. The next step is actually not needed for a DMFT calculation, but it is good to do this check to see what the transformation does to the local Hamiltonian. Note that in case of SOC, although spin is not a good quantum number any more, there are two blocks of size 5x5, each corresponding to negative/positive :math:`m_j` values:: eal = SK.eff_atomic_levels() eal2 = SK.block_structure.convert_matrix(eal[0],space_from='sumk', space_to='solver') - print eal[0]['up'][1:3,1:3] # prints the 2x2 block with offiagonals - [[ 0.391+0.j -0. -0.815j] - [-0. +0.815j 4.884-0.j ]] + print eal2['ud_0'].diagonal().real. # diagonal of the first 5x5 block + [0.071 0.131 0.608 4.572 5.128] - print eal2['up_1'] # prints the 2x2 block after rotation - [[0.247-0.j 0. +0.j] - [0. -0.j 5.028+0.j]] + print eal2['ud_1'].diagonal().real. # diagonal of the second 5x5 block + [0.071 0.131 0.608 4.572 5.128] -So the local Hamiltonian has been diagonalised. From the other entries we can see that the *up_0* block and the [1,1] entry of the *up_1* block correspond to :math:`e_g`-like orbitals, and the others are the -:math:`t_{2g}` orbitals that we want to keep. So we pick the according orbitals in the block structure:: +We see that the orbitals are ordered from low to high energy, which makes picking the orbitals around the Fermi level quite easy. We just take indices 0 to 2:: - SK.block_structure.pick_gf_struct_solver([{'up_1': [0],'up_2': [0],'up_3': [0],'down_1': [0],'down_2': [0],'down_3': [0]}]) + SK.block_structure.pick_gf_struct_solver([{'ud_0': [0,1,2],'ud_1': [0,1,2]}]) We can now look at the final result:: - print SK.block_structure.convert_matrix(eal[0],space_from='sumk',space_to='solver') - {'up_2': array([[0.156-0.j]]), 'up_3': array([[0.156-0.j]]), 'up_1': array([[0.247-0.j]]), 'down_3': array([[0.156-0.j]]), 'down_2': array([[0.156-0.j]]), 'down_1': array([[0.247-0.j]])} - -We see that we arrived at a structure with 3 orbitals per spin only, and blocks of size 1x1. + eal3 = SK.block_structure.convert_matrix(eal[0],space_from='sumk', space_to='solver') + + print eal3['ud_0'] + [[ 0.071+0.j 0. +0.j -0. -0.j] + [-0. -0.j 0.131+0.j -0. -0.j] + [-0. +0.j 0. +0.j 0.608-0.j]] + + print eal3['ud_1'] + [[ 0.071+0.j -0. -0.j 0. +0.j] + [-0. +0.j 0.131-0.j 0. +0.j] + [ 0. -0.j 0. -0.j 0.608+0.j]] + +We see that we arrived at a diagonal structure with two blocks of size 3x3, and we have picked the orbitals around the Fermi level. The interaction Hamiltonian --------------------------- -We now set up the interaction Hamiltonian. Since we want to rotate the interaction matrix into the local basis, we are using the Slater convention for it:: +We now set up the interaction Hamiltonian. Since we want to rotate the interaction matrix into the local basis, we are using the Slater convention for it. We use *l=2* for *d* orbitals. Also, for SOC calculations, we need to inflate the resulting matrix to size 10x10:: from pytriqs.operators.util import * from pytriqs.operators.util.U_matrix import * U = 2.0 J = 0.2 - U_mat = U_matrix(l=2,U_int=U,J_hund=J,basis='other', T=SK.T[0].conjugate()) + U_sph = U_matrix(l=2, U_int=U, J_hund=J) + U_sph = np.kron(np.reshape(np.eye(2),(1,2,1,2)),np.kron(np.reshape(np.eye(2),(2,1,2,1)),U_sph)) # inflating the matrix + U_mat = transform_U_matrix(U_sph, SK.T[0].conjugate()) + -In the last line we use the Wien2k convention to write the U matrix in the cubic harmonics. Next, we want to rotate it, and pick out only the relevant :math:`t_{2g}` orbitals. At this step we need to give the indices of the wanted orbitals in the *sumk* basis:: +In the last line we use the Wien2k convention to write the U matrix in the cubic harmonics. Next, we want to set up a Hamiltonian and rotate it into the *solver* basis:: - U_trans = transform_U_matrix(U_mat, SK.block_structure.transformation[0]['up'].conjugate()) - indices_to_pick_sumk = [1,3,4] # these are the relevant indices in the sumk basis - U_red = subarray(U_trans,len(U_trans.shape)*[indices_to_pick_sumk]) - h_int = h_int_slater(['up','down'], indices_to_pick_sumk, U_red, map_operator_structure=SK.block_structure.sumk_to_solver[0], off_diag=False, complex=False) + h_sumk = h_int_slater(['ud'], range(2*(2*l+1)), U_mat, off_diag=True, complex=True) + h_int = SK.block_structure.convert_operator(h_sumk) + +Note that we needed to set up the interaction Hamiltonian first for the full set of *d* orbitals. The :meth:`convert_operator` method then takes care of rotating and picking the relevant orbitals. Now we have the interaction Hamiltonian for the solver, which we set up next:: @@ -157,16 +154,16 @@ Now we have the interaction Hamiltonian for the solver, which we set up next:: # tail fit p["perform_tail_fit"] = True p["fit_max_moment"] = 4 - p["fit_min_n"] = 40 - p["fit_max_n"] = 100 + p["fit_min_w"] = 4.0 + p["fit_max_w"] = 8.0 The DMFT loop with automatic basis rotations -------------------------------------------- -After these initialisation steps, the formal DMFT cycle is very similar to a calculation without these basis rotations, since these rotations are done automatically, once the :class:`BlockStructure` property *transformation* is set, see :ref:`basisrotation`. +After these initialisation steps, the formal DMFT cycle is very similar to a calculation without SOC, since the rotations are done automatically, once the :class:`BlockStructure` property *transformation* is set, see :ref:`basisrotation`. -The DMFT loop itself looks very much the same as in :ref:`SrVO3`:: +The DMFT loop itself looks very much the same as in :ref:`SrVO3` or :ref:`Sr2MgOsO6_noSOC`:: # double counting correction: dc_type = 0 # FLL @@ -177,7 +174,6 @@ The DMFT loop itself looks very much the same as in :ref:`SrVO3`:: mpi.report("Iteration = %s"%iteration_number) - SK.symm_deg_gf(S.Sigma_iw) # symmetrizing Sigma SK.set_Sigma([ S.Sigma_iw ]) # put Sigma into the SumK class chemical_potential = SK.calc_mu( precision = 0.01 ) # find the chemical potential for given density S.G_iw << SK.extract_G_loc()[0] @@ -186,7 +182,7 @@ The DMFT loop itself looks very much the same as in :ref:`SrVO3`:: # Put Hartree energy on Re Sigma dm = S.G_iw.density() SK.calc_dc(dm, U_interact = U, J_hund = J, orb = 0, use_dc_formula = dc_type) - S.Sigma_iw << SK.block_structure.convert_matrix(SK.dc_imp[0],space_from='sumk',space_to='solver')['up_1'][0,0] + S.Sigma_iw << SK.block_structure.convert_matrix(SK.dc_imp[0],space_from='sumk',space_to='solver')['ud_0'][0,0] # Calculate new G0_iw to input into the solver: S.G0_iw << S.Sigma_iw + inverse(S.G_iw) @@ -203,12 +199,29 @@ The DMFT loop itself looks very much the same as in :ref:`SrVO3`:: # Save stuff into the user_data group of hdf5 archive in case of rerun: SK.save(['chemical_potential','dc_imp','dc_energ']) -The only difference to the other example is in the initialisation of the real part of the self energy. We cannot just take an element of the *dc_imp* array, since this array is stored in the *sumk* structure. Therefore, we first need to transform this matrix into *solver* space, and then take the appropriate matrix element. After the first iteration (here done with 24e6 MC sweeps), you should get self energies like this: +The only difference to the other example is in the initialisation of the real part of the self energy. We cannot just take an element of the *dc_imp* array, since this array is stored in the *sumk* structure. Therefore, we first need to transform this matrix into *solver* space, and then take the appropriate matrix element. After the first iteration (here done with 18e6 MC sweeps), you should get this output at the end of the run:: -.. image:: images_scripts/Sr2MgOsO6_noSOC_Sigmas.png + Total number of measures: 18000000 + Average sign: (0.884535,-4.11253e-06) + Orbital densities of impurity Green function: + Orbital ud_0: + [[ 5.20045070e-01 -8.24863778e-10 5.95348202e-12] + [-8.24863778e-10 4.30734642e-01 -1.29359496e-03] + [ 5.95348202e-12 -1.29359496e-03 4.80477133e-02]] + Orbital ud_1: + [[ 5.24181422e-01 2.22991244e-09 -8.16290063e-10] + [ 2.22991244e-09 4.30431196e-01 2.19004569e-03] + [-8.16290063e-10 2.19004569e-03 4.77161009e-02]] + Total charge of impurity problem : 2.001156 + +We see that there is a small sign problem due to the off-diagonal elements in the hybridisation function. However, this sign problem is treatable, since we have rotated into the local basis where these off-diagonal elements are minimised. + +The imaginary part of the self energy matrix of the *ud_0* block looks like this: + +.. image:: images_scripts/Sr2MgOsO6_SOC_Sigmas.png :width: 600 :align: center -The two :math:`d_{xz}` and :math:`d_{yz}` orbitals are degenerate (blocks *up_2* and *up_3*), whereas the :math:`d_{xy}`-like orbital is different. +Plotted on the same scale, the off-diagonal elements are very small, only the *(1,2)* and *(2,1)* elements are visibly different from zero. -A complete python script for this tutorial, including some more input/output, is available (:download:`Sr2MgOsO6_noSOC.py `). When running the script, you will encounter warnings during the transformation from the *sumk* to the *solver* basis. These warnings just reflect that the off-diagonal elements of the full Greens function are not zero at all frequencies, although the local Hamiltonian is. In that sense, we still do an approximation when restricting ourselves to the :math:`t_{2g}`-like orbitals. \ No newline at end of file +A complete python script for this tutorial, including some more input/output, is available (:download:`Sr2MgOsO6_SOC.py `). When running the script, you will encounter warnings during the transformation from the *sumk* to the *solver* basis. These warnings just reflect that the off-diagonal elements of the full Greens function are not zero at all frequencies, although the local Hamiltonian is. In that sense, we still do an approximation when restricting ourselves to the low-energy subset. \ No newline at end of file From 0552cf205702c96920f1a263dae091d05ccfa5ff Mon Sep 17 00:00:00 2001 From: Alexander Hampel Date: Thu, 7 May 2020 13:28:22 +0200 Subject: [PATCH 56/57] Update doc/guide/blockstructure.rst --- doc/guide/blockstructure.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/guide/blockstructure.rst b/doc/guide/blockstructure.rst index a366cdf0..7d99ba24 100644 --- a/doc/guide/blockstructure.rst +++ b/doc/guide/blockstructure.rst @@ -41,7 +41,7 @@ A plot of this structure looks like this. Note that there are off-diagonal eleme The *solver* structure ---------------------- -The method:`BlockStructure.full_structure()` method, as we used it above to create our BlockStructure object, yields - as the name suggests - a full structure, where *sumk* and *asolver* structure are identical. Now we want to take advantage of the symmetries of the problem to reduce the *solver* block structure to the relevant matrix elements only. In our case the [0,0] matrix element of the Green's function is completely decoupled from the 2x2 matrix of [1:2,1:2] elements. We simplify the *solver* structure by setting the mapping of each orbital to its target block and orbital:: +The method:`BlockStructure.full_structure()` method, as we used it above to create our BlockStructure object, yields - as the name suggests - a full structure, where *sumk* and *solver* structure are identical. Now we want to take advantage of the symmetries of the problem to reduce the *solver* block structure to the relevant matrix elements only. In our case the [0,0] matrix element of the Green's function is completely decoupled from the 2x2 matrix of [1:2,1:2] elements. We simplify the *solver* structure by setting the mapping of each orbital to its target block and orbital:: BS.map_gf_struct_solver([{('up',0):('up_0',0), ('up',1):('up_1',0), ('up',2):('up_1',1)}]) From f3dfd1bc6a0404e2c184997b58655dbca5b2a032 Mon Sep 17 00:00:00 2001 From: Alexander Hampel Date: Thu, 7 May 2020 13:49:41 +0200 Subject: [PATCH 57/57] added Wien2k doc link --- doc/guide/soc.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/guide/soc.rst b/doc/guide/soc.rst index 3491c2e0..47356af6 100644 --- a/doc/guide/soc.rst +++ b/doc/guide/soc.rst @@ -19,7 +19,7 @@ The treatment of SOC in the VASP package is fundamentally different to the way W Therefore, this guide describes how to do an SOC calculation using the Wien2k DFT package. First, a Wien2k calculation including SOC has to be performed. -For details, we refer the reader to the documentation of Wien2k. As a matter of fact, we need the output for the DFT band structure for both spin directions explicitly. That means that one needs to do a spin-polarised DFT calculation with SOC, but, however, with magnetic moment set to zero. In the Wien2k initialisation procedure, one can choose for the option -nom when ``lstart`` is called. This means that the charge densities are initialised without magnetic splitting. The SOC calculation is then performed in a standard way as described in the Wien2k manual. +For details, we refer the reader to the `documentation of Wien2k `_ . As a matter of fact, we need the output for the DFT band structure for both spin directions explicitly. That means that one needs to do a spin-polarised DFT calculation with SOC, but, however, with magnetic moment set to zero. In the Wien2k initialisation procedure, one can choose for the option -nom when ``lstart`` is called. This means that the charge densities are initialised without magnetic splitting. The SOC calculation is then performed in a standard way as described in the Wien2k manual. Performing the projection ~~~~~~~~~~~~~~~~~~~~~~~~~