def __init__(self, **kwargs): """ * There are several possible constructors, which accept only keyword arguments. * BlockGf(name_list = list of names, block_list = list of blocks, make_copies = False, name = '') * ``name_list``: list of the names of the blocks, e.g. ["up","down"]. * ``block_list``: list of blocks of Green's functions. * ``make_copies``: If True, it makes a copy of the blocks and build the Green's function from these copies. * BlockGf(mesh = mesh, gf_struct = block structure, target_rank = rank of target space, name = '') * ``mesh``: The mesh used to construct each block * ``target_rank``: The rank of the target space of each block (default: 2) * ``gf_struct``: List of pairs [ [str, [str,...]], ... ] providing the block name and indices, e.g. [ ['up', ['0']], ['dn', ['0']] ] * BlockGf(name_block_generator, make_copies = False, name = '') * ``name_block_generator``: a generator of (name, block) * ``make_copies``: If True, it makes a copy of the blocks and build the Green's function from these copies. """ # first extract the optional name argument self.name = kwargs.pop('name','G') self.note = kwargs.pop('note','') self._rename_gf = kwargs.pop('rename_gf',True) # Default arguments if set(kwargs.keys()) == set(['mesh','gf_struct']): kwargs['target_rank'] = 2 if 'block_list' in kwargs.keys() and 'make_copies' not in kwargs.keys(): kwargs['make_copies'] = False if set(kwargs.keys()) == set(['block_list','make_copies']): kwargs['name_list'] = [str(i) for i in range(len(kwargs['block_list']))] if set(kwargs.keys()) == set(['name_list','block_list','make_copies']): BlockNameList, GFlist = kwargs['name_list'],kwargs['block_list'] assert all([isinstance(name,str) for name in BlockNameList]), "Error in BlockGf Construction: Block-Names must be Strings" elif set(kwargs.keys()) == set(['mesh','gf_struct','target_rank']): BlockNameList = [] GFlist = [] for bl, idx_lst in kwargs['gf_struct']: BlockNameList.append(bl) if len(idx_lst) > 0 and kwargs['target_rank'] > 0: GFlist.append(Gf(mesh=kwargs['mesh'], target_shape=[len(idx_lst)]*kwargs['target_rank'], name='G_%s'%bl, indices=[idx_lst]*kwargs['target_rank'])) else: GFlist.append(Gf(mesh=kwargs['mesh'], target_shape=[], name='G_%s'%bl)) elif set(kwargs.keys()) == set(['name_block_generator','make_copies']): BlockNameList,GFlist = zip(* kwargs['name_block_generator']) else: raise RuntimeError, "BlockGf construction: error in parameters, see the documentation" if kwargs.get('make_copies', False): GFlist = [g.copy() for g in GFlist] # First a few checks assert GFlist !=[], "Empty list of blocks !" for ind in BlockNameList: assert str(ind)[0:2] !='__', "indices should not start with __" assert len(set(BlockNameList)) == len(BlockNameList),"Block indices of the Green Function are not unique" assert len(BlockNameList) == len(GFlist), "Number of indices and of Green Function Blocks differ" assert 'block_names' not in BlockNameList, "'block_names' is a reserved keyword. It is not authorized as a block name ! " # All blocks are compatible for binary operation # --> correction: All blocks have the same type #if not reduce (operator.and_,[ GFlist[0]._is_compatible_for_ops(x) for x in GFlist[1:] ] , True): # raise RuntimeError, "The blocks are not compatible for binary operations: not the same type, same temperature, etc..." if len(set([ type(g) for g in GFlist])) != 1: raise RuntimeError, "BlockGf: All block must have the same type %s"%GFlist # init self.__indices,self.__GFlist = BlockNameList,GFlist try: self.__me_as_dict = dict(self) except TypeError: raise TypeError, "indices are not of the correct type" self.__BlockIndexNumberTable = dict( (i,n) for n,i in enumerate(self.__indices) ) # a dict: index -> number of its order # Add the name to the G self.note = '' if self._rename_gf: for i,g in self: g.name = "%s_%s"%(str(self.name),i) if self.name else '%s'%(i,) del self._rename_gf
def fit_legendre(g_t, order=10): """ General fit of a noisy imaginary time Green's function to a low order Legendre expansion in imaginary time. Only Hermiticity is imposed on the fit, so discontinuities has to be fixed separately (see the method enforce_discontinuity) Author: Hugo U.R. Strand Parameters ---------- g_t : TRIQS imaginary time Green's function (matrix valued) Imaginary time Green's function to fit (possibly noisy binned data) order : int Maximal order of the fitted Legendre expansion Returns ------- g_l : TRIQS Legendre polynomial Green's function (matrix valued) Fitted Legendre Green's function with order `order` """ import numpy.polynomial.legendre as leg if isinstance(g_t, BlockGf): return map_block(lambda g_bl: fit_legendre(g_bl, order), g_t) assert isinstance(g_t, Gf) and isinstance(g_t.mesh, MeshImTime), "fit_legendre expects imaginary-time Green function objects" assert len(g_t.target_shape) == 2, "fit_legendre currently only implemented for matrix_valued Green functions" # -- flatten the data to 2D N_tau x (N_orb * N_orb) shape = g_t.data.shape fshape = [shape[0], np.prod(shape[1:])] # -- extend data accounting for hermiticity mesh = g_t.mesh tau = np.array([ t.value for t in mesh ]) # Rescale to the interval (-1,1) x = 2. * tau / mesh.beta - 1. data = g_t.data.reshape(fshape) data_herm = np.transpose(g_t.data, axes=(0, 2, 1)).conjugate().reshape(fshape) # -- Separated real valued linear system, with twice the number of RHS terms data_re = 0.5 * (data + data_herm).real data_im = 0.5 * (data + data_herm).imag data_ext = np.hstack((data_re, data_im)) c_l_ext = leg.legfit(x, data_ext, order - 1) c_l_re, c_l_im = np.split(c_l_ext, 2, axis=-1) c_l = c_l_re + 1.j * c_l_im # -- make Legendre Green's function of the fitted coeffs lmesh = MeshLegendre(mesh.beta, mesh.statistic, order) # Nb! We have to scale the actual Legendre coeffs to the Triqs "scaled" Legendre coeffs # see Boehnke et al. PRB (2011) l = np.arange(len(lmesh)) scale = np.sqrt(2.*l + 1) / mesh.beta scale = scale.reshape([len(lmesh)] + [1]*len(g_t.target_shape)) g_l = Gf(mesh=lmesh, target_shape=g_t.target_shape) g_l.data[:] = c_l.reshape(g_l.data.shape) / scale return g_l