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:
parent
d4c96a9d93
commit
f0dfabff38
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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()
|
||||||
|
@ -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()
|
||||||
|
@ -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()
|
||||||
|
@ -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 +
|
||||||
|
@ -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.
@ -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);
|
||||||
|
@ -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++)
|
||||||
|
@ -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;}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user