3
0
mirror of https://github.com/triqs/dft_tools synced 2024-10-31 19:23:45 +01:00

Change tail implementation with fixed array size

Now the tail have a fixed size. It actually makes everything simpler. I took
order_min = -1 and order_max = 8. This makes the tails compatible with the
previous implementation. However we might want to change this to something like
-10, 10 so that they are self-contained. This commit should also fix issue #11.
This commit is contained in:
Michel Ferrero 2013-09-11 18:23:38 +02:00
parent d4c96a9d93
commit f0dfabff38
13 changed files with 359 additions and 369 deletions

View File

@ -6,10 +6,15 @@ Changelog
This document describes the main changes in TRIQS. This document describes the main changes in TRIQS.
From TRIQS 0.x to TRIQS 1.0 master (latest commit on github)
--------------------------- --------------------------------
There have been changes from versions 0.x to 1.0 that will most likely have * The tails now have fixed size avoid mpi problems
version 1.0.0
-------------
There have been changes from versions 0.x to 1.0.0 that will most likely have
consequences for your scripts and archives. consequences for your scripts and archives.
Python classes Python classes

View File

@ -23,7 +23,7 @@ r""" """
import numpy import numpy
from math import * from math import *
from gf import MeshImFreq, TailGf, MeshReFreq from gf import MeshImFreq, MeshReFreq
from lazy_expressions import LazyExprTerminal, LazyExpr, transform from lazy_expressions import LazyExprTerminal, LazyExpr, transform
def is_lazy(y): def is_lazy(y):
@ -68,7 +68,7 @@ class Function (Base):
:param function: the function:math:`\omega \rightarrow function(\omega)` :param function: the function:math:`\omega \rightarrow function(\omega)`
:param tail: The tail. Use None if you don't use any tail (will be put to 0) :param tail: The tail. Use None if you don't use any tail (will be put to 0)
""" """
Base.__init__(self,function=function, tail=tail) Base.__init__(self, function=function, tail=tail)
def __call__(self,G): def __call__(self,G):
if not(callable(self.function)): raise RuntimeError, "GFInitializer.Function: f must be callable" if not(callable(self.function)): raise RuntimeError, "GFInitializer.Function: f must be callable"
@ -97,8 +97,7 @@ class Const(Base):
C = C*numpy.identity(G.N1) C = C*numpy.identity(G.N1)
if C.shape !=(G.N1,G.N2): raise RuntimeError, "Size of constant incorrect" if C.shape !=(G.N1,G.N2): raise RuntimeError, "Size of constant incorrect"
t = G.tail G.tail.zero()
G.tail = TailGf(shape = t.shape, size = t.size, order_min=0)
G.tail[0][:,:] = C G.tail[0][:,:] = C
Function(lambda om: C, None)(G) Function(lambda om: C, None)(G)
@ -116,9 +115,12 @@ class Omega_(Base):
Id = numpy.identity(G.N1) Id = numpy.identity(G.N1)
G.tail.zero() G.tail.zero()
G.tail[-1][:,:] = Id G.tail[-1][:,:] = Id
for n,om in enumerate(G.mesh): G.data[n,:,:] = om*Id for n,om in enumerate(G.mesh): G.data[n,:,:] = om*Id
return G return G
##########################################################################
Omega = Omega_() Omega = Omega_()
iOmega_n = Omega_() iOmega_n = Omega_()
@ -139,8 +141,7 @@ class A_Omega_Plus_B(Base):
if A.shape !=(G.N1,G.N2): raise RuntimeError, "Size of A incorrect" if A.shape !=(G.N1,G.N2): raise RuntimeError, "Size of A incorrect"
if B.shape !=(G.N1,G.N2): raise RuntimeError, "Size of B incorrect" if B.shape !=(G.N1,G.N2): raise RuntimeError, "Size of B incorrect"
t,Id = G.tail, numpy.identity(G.N1) G.tail.zero()
G.tail = TailGf(shape = t.shape, size = t.size, order_min=-1)
G.tail[-1][:,:] = A G.tail[-1][:,:] = A
G.tail[0][:,:] = B G.tail[0][:,:] = B
@ -160,17 +161,17 @@ class OneFermionInTime(Base):
if G.mesh.TypeGF not in [GF_Type.Imaginary_Time]: if G.mesh.TypeGF not in [GF_Type.Imaginary_Time]:
raise TypeError, "This initializer is only correct in frequency" raise TypeError, "This initializer is only correct in frequency"
t,Id = G.tail, numpy.identity(G.N1) Id = numpy.identity(G.N1)
G.tail = TailGf(shape = t.shape, size = 3, order_min=1) G.tail.zero()
t[1][:,:] = 1 G.tail[1][:,:] = 1*Id
t[2][:,:] = L G.tail[2][:,:] = L*Id
t[3][:,:] = L*L G.tail[3][:,:] = L*L*Id
G.tail.mask.fill(3)
fact = -1/(1+exp(-L*G.beta)) fact = -1/(1+exp(-L*G.beta))
Function(lambda t: fact* exp(-L*t) *Id, None)(G) Function(lambda t: fact* exp(-L*t) *Id, None)(G)
return G return G
################################################## ##################################################
def _SemiCircularDOS(half_bandwidth): def _SemiCircularDOS(half_bandwidth):
@ -223,11 +224,12 @@ class SemiCircular (Base):
raise TypeError, "This initializer is only correct in frequency" raise TypeError, "This initializer is only correct in frequency"
# Let's create a new tail # Let's create a new tail
G.tail = TailGf(shape = G.tail.shape, size=5, order_min=1) Id = numpy.identity(G.N1)
for i in range(G.N1): G.tail.zero()
G.tail[1][i,i] = 1.0 G.tail[1][:,:] = 1.0*Id
G.tail[3][i,i] = D**2/4.0 G.tail[3][:,:] = D**2/4.0*Id
G.tail[5][i,i] = D**4/8.0 G.tail[5][:,:] = D**4/8.0*Id
G.tail.mask.fill(6)
Function(f,None)(G) Function(f,None)(G)
return G return G
@ -267,11 +269,12 @@ class Wilson (Base):
raise TypeError, "This initializer is only correct in frequency" raise TypeError, "This initializer is only correct in frequency"
# Let's create a new tail # Let's create a new tail
G.tail = TailGf(shape = G.tail.shape, size=5, order_min=1) Id = numpy.identity(G.N1)
for i in range(G.N1): G.tail.zero()
G.tail[1][i,i] = 1.0 G.tail[1][:,:] = 1.0*Id
G.tail[3][i,i] = D**2/3.0 G.tail[3][:,:] = D**2/3.0*Id
G.tail[5][i,i] = D**4/5.0 G.tail[5][:,:] = D**4/5.0*Id
G.tail.mask.fill(6)
Function(f,None)(G) Function(f,None)(G)
return G return G

View File

@ -238,13 +238,8 @@ class GfGeneric:
else: else:
raise RuntimeError, " argument type not recognized in += for %s"%arg raise RuntimeError, " argument type not recognized in += for %s"%arg
if rhs !=None : if rhs !=None :
new_tail = TailGf(shape=lhs.tail.shape, size=lhs.tail.size, order_min=min(0,lhs.tail.order_min)) new_tail = TailGf(shape=lhs.tail.shape)
new_tail[0][:,:] = rhs new_tail[0][:,:] = rhs
# if it is add, then we CAN change the shape of the tail, and
# reassign it since it is a new object, just create (then use the
# _singularity object.
# otherwise we can not, since it could be view, so we use the tail
# and if shape is not correct, = i.e. copy_from will raise an error
if is_add : lhs._singularity = lhs.tail + new_tail if is_add : lhs._singularity = lhs.tail + new_tail
else : lhs.tail = lhs.tail + new_tail else : lhs.tail = lhs.tail + new_tail
return lhs return lhs
@ -275,7 +270,7 @@ class GfGeneric:
else: else:
raise RuntimeError, " argument type not recognized in -= for %s"%arg raise RuntimeError, " argument type not recognized in -= for %s"%arg
if rhs !=None : if rhs !=None :
new_tail = TailGf(shape=lhs.tail.shape, size=lhs.tail.size, order_min=min(0,lhs.tail.order_min)) new_tail = TailGf(shape=lhs.tail.shape)
new_tail[0][:,:] = rhs new_tail[0][:,:] = rhs
if is_sub : lhs._singularity = lhs.tail - new_tail if is_sub : lhs._singularity = lhs.tail - new_tail
else : lhs.tail = lhs.tail - new_tail else : lhs.tail = lhs.tail - new_tail
@ -336,7 +331,7 @@ class GfGeneric:
MatrixStack(self.data).matmul_L_R(L, G.data, R) MatrixStack(self.data).matmul_L_R(L, G.data, R)
# this might be a bit slow # this might be a bit slow
t = TailGf(shape=(N1,N2), size=G.tail.order_max-G.tail.order_min+1, order_min=G.tail.order_min) t = TailGf(shape=(N1,N2))
for o in range(t.order_min, t.order_max+1): for o in range(t.order_min, t.order_max+1):
t[o] = numpy.dot(L, numpy.dot(G.tail[o], R)) t[o] = numpy.dot(L, numpy.dot(G.tail[o], R))
self.tail = t self.tail = t

View File

@ -49,7 +49,7 @@ class GfImFreq ( GfGeneric, GfImFreq_cython ) :
indicesL, indicesR = indices_pack indicesL, indicesR = indices_pack
N1, N2 = len(indicesL),len(indicesR) N1, N2 = len(indicesL),len(indicesR)
data = d.pop('data') if 'data' in d else numpy.zeros((len(mesh),N1,N2), self.dtype ) data = d.pop('data') if 'data' in d else numpy.zeros((len(mesh),N1,N2), self.dtype )
tail = d.pop('tail') if 'tail' in d else TailGf(shape = (N1,N2), size=10, order_min=-1) tail = d.pop('tail') if 'tail' in d else TailGf(shape = (N1,N2))
symmetry = d.pop('symmetry', Nothing()) symmetry = d.pop('symmetry', Nothing())
name = d.pop('name','g') name = d.pop('name','g')
assert len(d) ==0, "Unknown parameters in GFBloc constructions %s"%d.keys() assert len(d) ==0, "Unknown parameters in GFBloc constructions %s"%d.keys()
@ -93,7 +93,7 @@ class GfImFreq ( GfGeneric, GfImFreq_cython ) :
# Change the order_max # Change the order_max
# It is assumed that any known_coef will start at order -1 # It is assumed that any known_coef will start at order -1
self.tail = TailGf(shape = (self.N1,self.N2), size = order_max+2, order_min = -1) self.tail = TailGf(shape = (self.N1,self.N2))
# Fill up two arrays with the frequencies and values over the range of interest # Fill up two arrays with the frequencies and values over the range of interest
ninit, nstop = 0, -1 ninit, nstop = 0, -1

View File

@ -49,7 +49,7 @@ class GfImTime ( GfGeneric, GfImTime_cython ) :
indicesL, indicesR = indices_pack indicesL, indicesR = indices_pack
N1, N2 = len(indicesL),len(indicesR) N1, N2 = len(indicesL),len(indicesR)
data = d.pop('data') if 'data' in d else numpy.zeros((len(mesh),N1,N2), self.dtype ) data = d.pop('data') if 'data' in d else numpy.zeros((len(mesh),N1,N2), self.dtype )
tail = d.pop('tail') if 'tail' in d else TailGf(shape = (N1,N2), size=10, order_min=-1) tail = d.pop('tail') if 'tail' in d else TailGf(shape = (N1,N2))
symmetry = d.pop('symmetry', Nothing()) symmetry = d.pop('symmetry', Nothing())
name = d.pop('name','g') name = d.pop('name','g')
assert len(d) ==0, "Unknown parameters in GFBloc constructions %s"%d.keys() assert len(d) ==0, "Unknown parameters in GFBloc constructions %s"%d.keys()

View File

@ -47,7 +47,7 @@ class GfReFreq ( GfGeneric, GfReFreq_cython ) :
indicesL, indicesR = indices_pack indicesL, indicesR = indices_pack
N1, N2 = len(indicesL),len(indicesR) N1, N2 = len(indicesL),len(indicesR)
data = d.pop('data') if 'data' in d else numpy.zeros((len(mesh),N1,N2), self.dtype ) data = d.pop('data') if 'data' in d else numpy.zeros((len(mesh),N1,N2), self.dtype )
tail= d.pop('tail') if 'tail' in d else TailGf(shape = (N1,N2), size=10, order_min=-1) tail= d.pop('tail') if 'tail' in d else TailGf(shape = (N1,N2))
symmetry = d.pop('symmetry',None) symmetry = d.pop('symmetry',None)
name = d.pop('name','g') name = d.pop('name','g')
assert len(d) ==0, "Unknown parameters in GFBloc constructions %s"%d.keys() assert len(d) ==0, "Unknown parameters in GFBloc constructions %s"%d.keys()

View File

@ -47,7 +47,7 @@ class GfReTime ( GfGeneric, GfReTime_cython ) :
indicesL, indicesR = indices_pack indicesL, indicesR = indices_pack
N1, N2 = len(indicesL),len(indicesR) N1, N2 = len(indicesL),len(indicesR)
data = d.pop('data') if 'data' in d else numpy.zeros((len(mesh),N1,N2), self.dtype ) data = d.pop('data') if 'data' in d else numpy.zeros((len(mesh),N1,N2), self.dtype )
tail= d.pop('tail') if 'tail' in d else TailGf(shape = (N1,N2), size=10, order_min=-1) tail= d.pop('tail') if 'tail' in d else TailGf(shape = (N1,N2))
symmetry = d.pop('symmetry',None) symmetry = d.pop('symmetry',None)
name = d.pop('name','g') name = d.pop('name','g')
assert len(d) ==0, "Unknown parameters in GFBloc constructions %s"%d.keys() assert len(d) ==0, "Unknown parameters in GFBloc constructions %s"%d.keys()

View File

@ -3,7 +3,7 @@ from arrays cimport *
cdef extern from "triqs/gfs/local/tail.hpp" : cdef extern from "triqs/gfs/local/tail.hpp" :
cdef cppclass tail "triqs::python_tools::cython_proxy<triqs::gfs::local::tail_view>" : cdef cppclass tail "triqs::python_tools::cython_proxy<triqs::gfs::local::tail_view>" :
tail() tail()
tail(array_view[dcomplex,THREE], int, array_view[long,TWO]) except + tail(array_view[dcomplex,THREE], array_view[long,TWO], long) except +
matrix_view[dcomplex] operator()(int) except + matrix_view[dcomplex] operator()(int) except +
array_view[dcomplex,THREE] data() array_view[dcomplex,THREE] data()
array_view[long,TWO] mask_view() except + array_view[long,TWO] mask_view() except +

View File

@ -5,8 +5,8 @@ cdef class TailGf:
cdef tail _c cdef tail _c
def __init__(self, **d): def __init__(self, **d):
""" """
TailGf ( shape, size, order_min ) TailGf ( shape )
TailGf ( data, order_min ) TailGf ( data, mask, order_min )
""" """
c_obj = d.pop('encapsulated_c_object', None) c_obj = d.pop('encapsulated_c_object', None)
if c_obj : if c_obj :
@ -20,17 +20,24 @@ cdef class TailGf:
boost_unserialize_into(<std_string>bss,self._c) boost_unserialize_into(<std_string>bss,self._c)
return return
omin = d.pop('order_min') # default values
omin = -1
omax = 8
a = d.pop('data',None) a = d.pop('data',None)
if a==None : if a==None :
(N1, N2), s = d.pop('shape'), d.pop('size') (N1, N2) = d.pop('shape')
a = numpy.zeros((s,N1,N2), numpy.complex) a = numpy.zeros((omax-omin+1,N1,N2), numpy.complex)
m = d.pop('mask',None) m = d.pop('mask',None)
if m==None : if m==None :
m = numpy.zeros(a.shape[1:3], int) m = numpy.zeros(a.shape[1:3], int)
m.fill(omin+a.shape[0]-1) m.fill(omax)
o = d.pop('order_min',None)
if o==None: o = omin
assert len(d) == 0, "Unknown parameters in TailGf constructions %s"%d.keys() assert len(d) == 0, "Unknown parameters in TailGf constructions %s"%d.keys()
self._c = tail(array_view[dcomplex,THREE](a), omin, array_view[long,TWO](m))
self._c = tail(array_view[dcomplex,THREE](a), array_view[long,TWO](m), o)
#-------------- Reduction ------------------------------- #-------------- Reduction -------------------------------
@ -71,17 +78,22 @@ cdef class TailGf:
def __get__(self) : return self._c.size() def __get__(self) : return self._c.size()
def copy(self) : def copy(self) :
return self.__class__(data = self.data.copy(), order_min = self.order_min, mask = self.mask.copy()) return self.__class__(data = self.data.copy(), mask = self.mask.copy())
def copy_from(self, TailGf T) : def copy_from(self, TailGf T) :
assert self.order_min <= T.order_min, "Copy_from error "
self._c << T._c self._c << T._c
def _make_slice(self, sl1, sl2): def _make_slice(self, sl1, sl2):
return self.__class__(data = self.data[:,sl1,sl2], order_min = self.order_min, mask = self.mask[sl1,sl2]) return self.__class__(data = self.data[:,sl1,sl2], mask = self.mask[sl1,sl2])
def __repr__ (self) : def __repr__ (self) :
return string.join([ "%s"%self[r]+ (" /" if r>0 else "") + " Om^%s"%(abs(r)) for r in range(self.order_min, self.order_max+1) ] , " + ") omin = self.order_min
while ((omin <= self.order_max) and (numpy.max(numpy.abs(self.data[omin-self.order_min,:,:])) < 1e-8)):
omin = omin+1
if omin == self.order_max+1:
return "%s"%numpy.zeros(self.shape)
else:
return string.join([ "%s"%self[r]+ (" /" if r>0 else "") + " Om^%s"%(abs(r)) for r in range(omin, self.order_max+1) ] , " + ")
def __getitem__(self,i) : def __getitem__(self,i) :
"""Returns the i-th coefficient of the expansion, or order Om^i""" """Returns the i-th coefficient of the expansion, or order Om^i"""
@ -164,11 +176,11 @@ cdef class TailGf:
def transpose (self) : def transpose (self) :
"""Transpose the array : new view as in numpy""" """Transpose the array : new view as in numpy"""
return TailGf(data=self.data.transpose(), order_min=self.order_min, mask=self.mask.transpose()) return TailGf(data=self.data.transpose(), mask=self.mask.transpose())
def conjugate(self) : def conjugate(self) :
"""Transpose the array : new view as in numpy""" """Transpose the array : new view as in numpy"""
return TailGf(data=self.data.conjugate(), order_min=self.order_min, mask=self.mask) return TailGf(data=self.data.conjugate(), mask=self.mask)
def __write_hdf5__ (self, gr , char * key) : def __write_hdf5__ (self, gr , char * key) :
h5_write (make_h5_group(gr), key, self._c) h5_write (make_h5_group(gr), key, self._c)

Binary file not shown.

View File

@ -94,9 +94,7 @@ void test_1(){
/* ----- Fourier ----- */ /* ----- Fourier ----- */
size_t N1=1; size_t N1=1;
size_t N2=1; size_t N2=1;
size_t size_ = 5; triqs::gfs::local::tail t(N1,N2);
long order_min=-1;
triqs::gfs::local::tail t(N1,N2, size_, order_min);
t(1)=1; t(1)=1;
auto Gt = make_gf<imtime> (beta, Fermion, make_shape(1,1),100,full_bins, t); auto Gt = make_gf<imtime> (beta, Fermion, make_shape(1,1),100,full_bins, t);

View File

@ -90,7 +90,7 @@ namespace triqs { namespace gfs {
local::tail_view get_tail(gf_view<legendre> const & gl, int size = 10, int omin = -1) { local::tail_view get_tail(gf_view<legendre> const & gl, int size = 10, int omin = -1) {
auto sh = gl.data().shape().front_pop(); auto sh = gl.data().shape().front_pop();
local::tail t(sh, size, omin); local::tail t(sh);
t.data() = 0.0; t.data() = 0.0;
for (int p=1; p<=t.order_max(); p++) for (int p=1; p<=t.order_max(); p++)

View File

@ -63,7 +63,6 @@ namespace triqs { namespace gfs { namespace local {
typedef arrays::matrix_view<dcomplex> mv_type; typedef arrays::matrix_view<dcomplex> mv_type;
typedef arrays::matrix_view<dcomplex> const_mv_type; typedef arrays::matrix_view<dcomplex> const_mv_type;
//typedef arrays::matrix_view<const dcomplex> const_mv_type;
data_view_type data() { return _data;} data_view_type data() { return _data;}
const data_view_type data() const { return _data;} const data_view_type data() const { return _data;}
@ -92,19 +91,19 @@ namespace triqs { namespace gfs { namespace local {
data_type _data; data_type _data;
// All constructors // All constructors
tail_impl(): omin(0), mask(), _data() {} // all arrays of zero size (empty) tail_impl(): mask(), _data(), omin(0) {} // all arrays of zero size (empty)
tail_impl(size_t N1, size_t N2, size_t size_, long order_min): tail_impl(size_t N1, size_t N2, long omin_, long size_):
omin(order_min), mask(tqa::make_shape(N1,N2)), _data(tqa::make_shape(size_,N1,N2)) { omin(omin_), mask(tqa::make_shape(N1,N2)), _data(tqa::make_shape(size_,N1,N2)) {
mask() = order_min+size_-1; mask() = omin+size_-1;
_data() = 0; _data() = 0;
} }
tail_impl(data_type const &d, long order_min, mask_type const &om): omin(order_min), mask(om), _data(d) {} tail_impl(data_type const &d, mask_type const &m, long omin_): mask(m), _data(d), omin(omin_) {}
// tail_impl(tail_impl const & x): omin(x.omin), mask(x.mask), _data(x._data){} tail_impl(tail_impl<!IsView> const & x): mask(x.mask), _data(x._data), omin(x.omin) {}
tail_impl(tail_impl<!IsView> const & x): omin(x.omin), mask(x.mask), _data(x._data){}
tail_impl(tail_impl const &) = default; tail_impl(tail_impl const &) = default;
tail_impl(tail_impl &&) = default; tail_impl(tail_impl &&) = default;
friend class tail_impl<!IsView>; friend class tail_impl<!IsView>;
public: public:
mv_type operator() (int n) { mv_type operator() (int n) {
@ -116,16 +115,16 @@ namespace triqs { namespace gfs { namespace local {
const_mv_type operator() (int n) const { const_mv_type operator() (int n) const {
if (n>this->order_max()) TRIQS_RUNTIME_ERROR<<" n > Max Order. n= "<<n <<", Max Order = "<<order_max() ; if (n>this->order_max()) TRIQS_RUNTIME_ERROR<<" n > Max Order. n= "<<n <<", Max Order = "<<order_max() ;
if (n<this->order_min()) { mv_type::regular_type r(this->shape()); r()=0; return r;} if (n<this->order_min()) { mv_type::regular_type r(this->shape()); r()=0; return r;}
return this->_data(n-omin,tqa::range(), tqa::range()); return this->_data(n-omin, tqa::range(), tqa::range());
} }
/// same as (), but if n is too large, then returns 0 instead of raising an exception /// same as (), but if n is too large, then returns 0 instead of raising an exception
const_mv_type get_or_zero (int n) const { const_mv_type get_or_zero (int n) const {
if ( (n>this->order_max()) || (n<this->order_min()) ) { mv_type::regular_type r(this->shape()); r()=0; return r;} if ( (n>this->order_max()) || (n<this->order_min()) ) { mv_type::regular_type r(this->shape()); r()=0; return r; }
return this->_data(n-omin,tqa::range(), tqa::range()); return this->_data(n-omin, tqa::range(), tqa::range());
} }
operator freq_infty() const { return freq_infty();} operator freq_infty() const { return freq_infty(); }
/// Save in txt file : doc the format ? ---> prefer serialization or hdf5 ! /// Save in txt file : doc the format ? ---> prefer serialization or hdf5 !
void save(std::string file, bool accumulate=false) const {} void save(std::string file, bool accumulate=false) const {}
@ -133,7 +132,7 @@ namespace triqs { namespace gfs { namespace local {
/// Load from txt file : doc the format ? /// Load from txt file : doc the format ?
//void load(std::string file){} //void load(std::string file){}
friend std::string get_triqs_hdf5_data_scheme(tail_impl const & g) { return "TailGf";} friend std::string get_triqs_hdf5_data_scheme(tail_impl const & g) { return "TailGf"; }
/// ///
friend void h5_write (h5::group fg, std::string subgroup_name, tail_impl const & t) { friend void h5_write (h5::group fg, std::string subgroup_name, tail_impl const & t) {
@ -175,70 +174,58 @@ namespace triqs { namespace gfs { namespace local {
}; };
// ----------------------------- // -----------------------------
///The View class of GF // the view class
class tail_view : public tail_impl <true> { class tail_view : public tail_impl <true> {
typedef tail_impl <true> B; typedef tail_impl <true> B;
friend class tail; friend class tail;
public : public :
template<bool V> tail_view(tail_impl<V> const & t): B(t){} template<bool V> tail_view(tail_impl<V> const & t): B(t){}
tail_view(B::data_type const &d, long order_min, B::mask_type const &om): B(d, order_min, om){} tail_view(B::data_type const &d, B::mask_type const &m, long order_min=-1): B(d, m, order_min) {}
tail_view(tail_view const &) = default; tail_view(tail_view const &) = default;
tail_view(tail_view &&) = default; tail_view(tail_view &&) = default;
void rebind( tail_view const &X) {
void rebind(tail_view const &X) {
omin = X.omin; omin = X.omin;
mask.rebind(X.mask); mask.rebind(X.mask);
_data.rebind(X._data); _data.rebind(X._data);
} }
inline void rebind( tail const &X); inline void rebind(tail const &X);
//using B::operator=; // import operator = from impl. class or the default = is synthetized
//tail_view & operator=(const tail_view & rhs) { if (this->data.is_empty()) rebind(rhs); else B::operator=(rhs); return *this; }
// operator = for views // operator = for views
tail_view & operator = (const tail_view & rhs) { tail_view & operator = (const tail_view & rhs) {
if (this->_data.is_empty()) rebind(rhs); if ((_data.shape()[1] != rhs._data.shape()[1]) || (_data.shape()[2] != rhs._data.shape()[2]) || (omin != rhs.omin))
else { TRIQS_RUNTIME_ERROR<<"tails are incompatible";
if (rhs.omin < omin) TRIQS_RUNTIME_ERROR<<"rhs has too small omin"; mask = rhs.mask;
if ((_data.shape()[1] != rhs._data.shape()[1]) || (_data.shape()[2] != rhs._data.shape()[2])) _data = rhs._data;
TRIQS_RUNTIME_ERROR<<"rhs has different shape";
for (size_t i=0; i<mask.shape()[0]; ++i)
for (size_t j=0; j<mask.shape()[1]; ++j)
mask(i,j) = std::min(rhs.mask(i,j), long(omin+size()-1));
for (size_t n=0; n<std::min(size(), size_t(rhs.size()-omin+rhs.omin)); ++n)
if (n < rhs.omin-omin) _data(n,tqa::range(),tqa::range()) = 0.0;
else _data(n,tqa::range(),tqa::range()) = rhs._data(n-rhs.omin+omin,tqa::range(),tqa::range());
}
return *this; return *this;
} }
inline tail_view & operator=(const tail & rhs); inline tail_view & operator=(const tail & rhs);
tail_view & operator=(std::complex<double> const & x) { tail_view & operator = (std::complex<double> const & x) {
if (omin > 0) TRIQS_RUNTIME_ERROR<<"lhs has too large omin"; _data() = 0.0;
for (size_t n=0; n<size(); ++n) _data(n, tqa::range(), tqa::range()) = 0.0; mv_type(_data(-omin, tqa::range(), tqa::range())) = x;
_data(-omin, tqa::range(), tqa::range()) = x; mask() = omin+_data.shape()[0]-1;
mask() = omin+size()-1;
return *this; return *this;
} }
using B::operator(); // import all previously defined operator() for overloading using B::operator(); // import all previously defined operator() for overloading
friend std::ostream & triqs_nvl_formal_print(std::ostream & out, tail_view const & x) { return out<<"tail_view";} friend std::ostream & triqs_nvl_formal_print(std::ostream & out, tail_view const & x) { return out<<"tail_view"; }
void print_me() const { std::cout << *this << std::endl ; }
}; };
// ----------------------------- // -----------------------------
///The regular class // the regular class
class tail : public tail_impl <false> { class tail : public tail_impl <false> {
typedef tail_impl <false> B; typedef tail_impl <false> B;
friend class tail_view; friend class tail_view;
public : public :
tail():B() {} tail():B() {}
typedef tqa::mini_vector<size_t,2> shape_type; typedef tqa::mini_vector<size_t,2> shape_type;
tail(size_t N1, size_t N2, size_t size_ = 10, long order_min=-1): B(N1,N2,size_,order_min) {} tail(size_t N1, size_t N2, long order_min=-1, long size=10): B(N1,N2,order_min,size) {}
tail(shape_type const & sh, size_t size_ = 10, long order_min=-1): B(sh[0],sh[1],size_,order_min) {} tail(shape_type const & sh, long order_min=-1, long size=10): B(sh[0],sh[1],order_min,size) {}
tail(tail const & g): B(g){} tail(tail const & g): B(g) {}
tail(tail_view const & g): B(g){} tail(tail_view const & g): B(g) {}
tail(tail &&) = default; tail(tail &&) = default;
// operator = for values // operator = for values
@ -258,71 +245,68 @@ namespace triqs { namespace gfs { namespace local {
using B::operator(); using B::operator();
/// The simplest tail corresponding to : omega /// The simplest tail corresponding to : omega
static tail_view omega(size_t N1, size_t N2, size_t size_) { static tail_view omega(size_t N1, size_t N2) {
tail t(N1, N2, size_, -1); tail t(N1, N2);
t(-1) = 1; t(-1) = 1;
return t; return t;
} }
/// The simplest tail corresponding to : omega, constructed from a shape for convenience /// The simplest tail corresponding to : omega, constructed from a shape for convenience
static tail_view omega(tail::shape_type const & sh, size_t size_) { return omega(sh[0],sh[1],size_);} static tail_view omega(tail::shape_type const & sh) { return omega(sh[0],sh[1]); }
}; };
template<typename RHS> void assign_from_expression(tail_view & t,RHS const & rhs) { t = rhs( tail::omega(t.shape(),t.size())); } template<typename RHS> void assign_from_expression(tail_view & t,RHS const & rhs) { t = rhs( tail::omega(t.shape()) ); }
inline void tail_view::rebind( tail const &X) { inline void tail_view::rebind(tail const &X) {
omin = X.omin; omin = X.omin;
mask.rebind(X.mask); mask.rebind(X.mask);
_data.rebind(X._data); _data.rebind(X._data);
} }
inline tail_view & tail_view::operator = (const tail & rhs) { inline tail_view & tail_view::operator = (const tail & rhs) {
if (this->_data.is_empty()) rebind(rhs); if ((_data.shape()[1] != rhs._data.shape()[1]) || (_data.shape()[2] != rhs._data.shape()[2]) || (omin != rhs.omin))
else {
if (rhs.omin < omin) TRIQS_RUNTIME_ERROR<<"rhs has too small omin";
if ((_data.shape()[1] != rhs._data.shape()[1]) || (_data.shape()[2] != rhs._data.shape()[2]))
TRIQS_RUNTIME_ERROR<<"rhs has different shape"; TRIQS_RUNTIME_ERROR<<"rhs has different shape";
for (size_t i=0; i<mask.shape()[0]; ++i) mask = rhs.mask;
for (size_t j=0; j<mask.shape()[1]; ++j) _data = rhs._data;
mask(i,j) = std::min(rhs.mask(i,j), long(omin+size()-1));
for (size_t n=0; n<std::min(size(),size_t(rhs.size()-omin+rhs.omin)); ++n)
if (n < rhs.omin-omin) _data(n,tqa::range(),tqa::range()) = 0.0;
else _data(n,tqa::range(),tqa::range()) = rhs._data(n-rhs.omin+omin, tqa::range(), tqa::range());
}
return *this; return *this;
} }
/// Slice in orbital space /// Slice in orbital space
template<bool V> tail_view slice_target(tail_impl<V> const & t, tqa::range R1, tqa::range R2) { template<bool V> tail_view slice_target(tail_impl<V> const & t, tqa::range R1, tqa::range R2) {
return tail_view(t.data()(tqa::range(),R1,R2),t.order_min(),t.mask_view()(R1,R2)); return tail_view(t.data()(tqa::range(),R1,R2), t.mask_view()(R1,R2), t.order_min());
} }
inline tail inverse(tail_view const & t) { inline tail inverse(tail_view const & t) {
// find in t
long omin1 = - t.smallest_nonzero(); long omin1 = - t.smallest_nonzero();
long omax1 = t.order_max() + 2*omin1; long omax1 = std::min(t.order_max() + 2*omin1, t.order_min()+long(t.size())-1);
size_t si = omax1-omin1+1; size_t si = omax1-omin1+1;
tail t_inv(t.shape(), si, omin1);
t_inv(omin1) = inverse(t(-omin1)); tail res(t);
res.data() = 0.0;
res.mask_view() = omax1;
res(omin1) = inverse(t(-omin1));
for (size_t n=1; n<si; n++) { for (size_t n=1; n<si; n++) {
for (size_t p=0; p<n; p++) { for (size_t p=0; p<n; p++) {
t_inv(omin1 + n) -= t(n-omin1-p) * t_inv(omin1+p); res(omin1 + n) -= t(n-omin1-p) * res(omin1+p);
} }
t_inv(omin1 + n) = t_inv(omin1) * make_clone(t_inv(omin1 + n)); res(omin1 + n) = res(omin1) * make_clone(res(omin1 + n));
} }
return t_inv; return res;
} }
inline tail mult_impl(tail_view const & l, tail_view const& r) { inline tail mult_impl(tail_view const & l, tail_view const& r) {
if (l.shape()[1] != r.shape()[0]) TRIQS_RUNTIME_ERROR<< "tail multiplication : shape mismatch"; if (l.shape()[1] != r.shape()[0] || l.order_min() != r.order_min()) TRIQS_RUNTIME_ERROR<< "tail multiplication : shape mismatch";
long omin1 = l.smallest_nonzero() + r.smallest_nonzero(); long omin1 = l.smallest_nonzero() + r.smallest_nonzero();
long omax1 = std::min(r.order_max()+l.smallest_nonzero(), l.order_max()+r.smallest_nonzero()); long omax1 = std::min(r.order_max()+l.smallest_nonzero(), l.order_max()+r.smallest_nonzero());
size_t si = omax1-omin1+1; size_t si = omax1-omin1+1;
tail res(l.shape()[0], r.shape()[1], si, omin1);
res.data() =0; tail res(l);
res.data() = 0.0;
res.mask_view() = omax1;
for (long n=res.order_min(); n<=res.order_max(); ++n) { for (long n=res.order_min(); n<=res.order_max(); ++n) {
// sum_{p}^n a_p b_{n-p}. p <= a.n_max, p >= a.n_min and n-p <=b.n_max and n-p >= b.n_min // sum_{p}^n a_p b_{n-p}. p <= a.n_max, p >= a.n_min and n-p <=b.n_max and n-p >= b.n_min
// hence p <= min ( a.n_max, n-b.n_min ) and p >= max ( a.n_min, n- b.n_max) // hence p <= min ( a.n_max, n-b.n_min ) and p >= max ( a.n_min, n- b.n_max)
@ -351,31 +335,25 @@ namespace triqs { namespace gfs { namespace local {
inline tail operator * (tail_view const & r, dcomplex a) { return a*r; } inline tail operator * (tail_view const & r, dcomplex a) { return a*r; }
template<typename T1, typename T2> TYPE_ENABLE_IF(tail,mpl::and_<LocalTail<T1>, LocalTail<T2>>) template<typename T1, typename T2> TYPE_ENABLE_IF(tail,mpl::and_<LocalTail<T1>, LocalTail<T2>>)
operator/ (T1 const & a, T2 const & b) { return a *inverse(b); } operator/ (T1 const & a, T2 const & b) { return a * inverse(b); }
inline tail operator / (tail_view const & r, dcomplex a) { tail res(r); res.data() /=a; return res;} inline tail operator / (tail_view const & r, dcomplex a) { tail res(r); res.data() /=a; return res;}
inline tail operator / (dcomplex a, tail_view const & r) { return a * inverse(r); } inline tail operator / (dcomplex a, tail_view const & r) { return a * inverse(r); }
template<typename T1, typename T2> TYPE_ENABLE_IF(tail,mpl::and_<LocalTail<T1>, LocalTail<T2>>) template<typename T1, typename T2> TYPE_ENABLE_IF(tail,mpl::and_<LocalTail<T1>, LocalTail<T2>>)
operator + (T1 const & l, T2 const& r) { operator + (T1 const & l, T2 const& r) {
using arrays::range; if (l.shape() != r.shape() || l.order_min() != r.order_min()) TRIQS_RUNTIME_ERROR<< "tail addition : shape mismatch";
if (l.shape() != r.shape()) TRIQS_RUNTIME_ERROR<< "tail addition : shape mismatch"; tail res(l.shape());
long omin1 = std::min(l.smallest_nonzero(),r.smallest_nonzero()); res.mask_view() = std::min(l.order_max(), r.order_max());
long omax1 = std::min(l.order_max(),r.order_max());
size_t si = omax1-omin1+1;
tail res(l.shape(), si, omin1);
for (long i = res.order_min(); i<=res.order_max(); ++i) res(i) = l(i) + r(i); for (long i = res.order_min(); i<=res.order_max(); ++i) res(i) = l(i) + r(i);
return res; return res;
} }
template<typename T1, typename T2> TYPE_ENABLE_IF(tail,mpl::and_<LocalTail<T1>, LocalTail<T2>>) template<typename T1, typename T2> TYPE_ENABLE_IF(tail,mpl::and_<LocalTail<T1>, LocalTail<T2>>)
operator - (T1 const & l, T2 const& r) { operator - (T1 const & l, T2 const& r) {
using arrays::range; if (l.shape() != r.shape() || l.order_min() != r.order_min()) TRIQS_RUNTIME_ERROR<< "tail addition : shape mismatch";
if (l.shape() != r.shape()) TRIQS_RUNTIME_ERROR<< "tail substraction : shape mismatch"; tail res(l.shape());
long omin1 = std::min(l.smallest_nonzero(),r.smallest_nonzero()); res.mask_view() = std::min(l.order_max(), r.order_max());
long omax1 = std::min(l.order_max(),r.order_max());
size_t si = omax1-omin1+1;
tail res(l.shape(), si, omin1);
for (long i = res.order_min(); i<=res.order_max(); ++i) res(i) = l(i) - r(i); for (long i = res.order_min(); i<=res.order_max(); ++i) res(i) = l(i) - r(i);
return res; return res;
} }
@ -387,7 +365,6 @@ namespace triqs { namespace gfs { namespace local {
return res; return res;
} }
template<typename T1, typename T2> TYPE_ENABLE_IF(tail,mpl::and_<LocalTail<T1>, is_scalar_or_element<T2>>) template<typename T1, typename T2> TYPE_ENABLE_IF(tail,mpl::and_<LocalTail<T1>, is_scalar_or_element<T2>>)
operator + (T1 const & t, T2 const & a) { return a+t;} operator + (T1 const & t, T2 const & a) { return a+t;}