2939 |
if isinstance(arg,numarray.NumArray): |
if isinstance(arg,numarray.NumArray): |
2940 |
sh=arg.shape |
sh=arg.shape |
2941 |
if len(sh)<2: |
if len(sh)<2: |
2942 |
raise ValueError,"trace: rank of argument must be greater than 1" |
raise ValueError,"rank of argument must be greater than 1" |
2943 |
if axis_offset<0 or axis_offset>len(sh)-2: |
if axis_offset<0 or axis_offset>len(sh)-2: |
2944 |
raise ValueError,"trace: axis_offset must be between 0 and %s"%len(sh)-2 |
raise ValueError,"axis_offset must be between 0 and %s"%len(sh)-2 |
2945 |
s1=1 |
s1=1 |
2946 |
for i in range(axis_offset): s1*=sh[i] |
for i in range(axis_offset): s1*=sh[i] |
2947 |
s2=1 |
s2=1 |
2948 |
for i in range(axis_offset+2,len(sh)): s2*=sh[i] |
for i in range(axis_offset+2,len(sh)): s2*=sh[i] |
2949 |
if not sh[axis_offset] == sh[axis_offset+1]: |
if not sh[axis_offset] == sh[axis_offset+1]: |
2950 |
raise ValueError,"trace: dimensions of component %s and %s must match."%(axis_offset.axis_offset+1) |
raise ValueError,"dimensions of component %s and %s must match."%(axis_offset.axis_offset+1) |
2951 |
arg_reshaped=numarray.reshape(arg,(s1,sh[axis_offset],sh[axis_offset],s2)) |
arg_reshaped=numarray.reshape(arg,(s1,sh[axis_offset],sh[axis_offset],s2)) |
2952 |
out=numarray.zeros([s1,s2],numarray.Float64) |
out=numarray.zeros([s1,s2],numarray.Float64) |
2953 |
for i1 in range(s1): |
for i1 in range(s1): |
2956 |
out.resize(sh[:axis_offset]+sh[axis_offset+2:]) |
out.resize(sh[:axis_offset]+sh[axis_offset+2:]) |
2957 |
return out |
return out |
2958 |
elif isinstance(arg,escript.Data): |
elif isinstance(arg,escript.Data): |
2959 |
return escript_trace(arg,axis_offset) |
if arg.getRank()<2: |
2960 |
|
raise ValueError,"rank of argument must be greater than 1" |
2961 |
|
if axis_offset<0 or axis_offset>arg.getRank()-2: |
2962 |
|
raise ValueError,"axis_offset must be between 0 and %s"%arg.getRank()-2 |
2963 |
|
s=list(arg.getShape()) |
2964 |
|
if not s[axis_offset] == s[axis_offset+1]: |
2965 |
|
raise ValueError,"dimensions of component %s and %s must match."%(axis_offset.axis_offset+1) |
2966 |
|
return arg._matrixtrace(axis_offset) |
2967 |
elif isinstance(arg,float): |
elif isinstance(arg,float): |
2968 |
raise TypeError,"trace: illegal argument type float." |
raise TypeError,"illegal argument type float." |
2969 |
elif isinstance(arg,int): |
elif isinstance(arg,int): |
2970 |
raise TypeError,"trace: illegal argument type int." |
raise TypeError,"illegal argument type int." |
2971 |
elif isinstance(arg,Symbol): |
elif isinstance(arg,Symbol): |
2972 |
return Trace_Symbol(arg,axis_offset) |
return Trace_Symbol(arg,axis_offset) |
2973 |
else: |
else: |
2974 |
raise TypeError,"trace: Unknown argument type." |
raise TypeError,"Unknown argument type." |
2975 |
|
|
|
def escript_trace(arg,axis_offset): |
|
|
"arg is a Data object" |
|
|
if arg.getRank()<2: |
|
|
raise ValueError,"escript_trace: rank of argument must be greater than 1" |
|
|
if axis_offset<0 or axis_offset>arg.getRank()-2: |
|
|
raise ValueError,"escript_trace: axis_offset must be between 0 and %s"%arg.getRank()-2 |
|
|
s=list(arg.getShape()) |
|
|
if not s[axis_offset] == s[axis_offset+1]: |
|
|
raise ValueError,"escript_trace: dimensions of component %s and %s must match."%(axis_offset.axis_offset+1) |
|
|
out=arg._matrixtrace(axis_offset) |
|
|
return out |
|
2976 |
class Trace_Symbol(DependendSymbol): |
class Trace_Symbol(DependendSymbol): |
2977 |
""" |
""" |
2978 |
L{Symbol} representing the result of the trace function |
L{Symbol} representing the result of the trace function |
2987 |
@type axis_offset: C{int} |
@type axis_offset: C{int} |
2988 |
""" |
""" |
2989 |
if arg.getRank()<2: |
if arg.getRank()<2: |
2990 |
raise ValueError,"Trace_Symbol: rank of argument must be greater than 1" |
raise ValueError,"rank of argument must be greater than 1" |
2991 |
if axis_offset<0 or axis_offset>arg.getRank()-2: |
if axis_offset<0 or axis_offset>arg.getRank()-2: |
2992 |
raise ValueError,"Trace_Symbol: axis_offset must be between 0 and %s"%arg.getRank()-2 |
raise ValueError,"axis_offset must be between 0 and %s"%arg.getRank()-2 |
2993 |
s=list(arg.getShape()) |
s=list(arg.getShape()) |
2994 |
if not s[axis_offset] == s[axis_offset+1]: |
if not s[axis_offset] == s[axis_offset+1]: |
2995 |
raise ValueError,"Trace_Symbol: dimensions of component %s and %s must match."%(axis_offset.axis_offset+1) |
raise ValueError,"dimensions of component %s and %s must match."%(axis_offset.axis_offset+1) |
2996 |
super(Trace_Symbol,self).__init__(args=[arg,axis_offset],shape=tuple(s[0:axis_offset]+s[axis_offset+2:]),dim=arg.getDim()) |
super(Trace_Symbol,self).__init__(args=[arg,axis_offset],shape=tuple(s[0:axis_offset]+s[axis_offset+2:]),dim=arg.getDim()) |
2997 |
|
|
2998 |
def getMyCode(self,argstrs,format="escript"): |
def getMyCode(self,argstrs,format="escript"): |
3063 |
if axis_offset==None: axis_offset=int(arg.rank/2) |
if axis_offset==None: axis_offset=int(arg.rank/2) |
3064 |
return numarray.transpose(arg,axes=range(axis_offset,arg.rank)+range(0,axis_offset)) |
return numarray.transpose(arg,axes=range(axis_offset,arg.rank)+range(0,axis_offset)) |
3065 |
elif isinstance(arg,escript.Data): |
elif isinstance(arg,escript.Data): |
3066 |
if axis_offset==None: axis_offset=int(arg.getRank()/2) |
r=arg.getRank() |
3067 |
return escript_transpose(arg,axis_offset) |
if axis_offset==None: axis_offset=int(r/2) |
3068 |
|
if axis_offset<0 or axis_offset>r: |
3069 |
|
raise ValueError,"axis_offset must be between 0 and %s"%r |
3070 |
|
return arg._transpose(axis_offset) |
3071 |
elif isinstance(arg,float): |
elif isinstance(arg,float): |
3072 |
if not ( axis_offset==0 or axis_offset==None): |
if not ( axis_offset==0 or axis_offset==None): |
3073 |
raise ValueError,"transpose: axis_offset must be 0 for float argument" |
raise ValueError,"axis_offset must be 0 for float argument" |
3074 |
return arg |
return arg |
3075 |
elif isinstance(arg,int): |
elif isinstance(arg,int): |
3076 |
if not ( axis_offset==0 or axis_offset==None): |
if not ( axis_offset==0 or axis_offset==None): |
3077 |
raise ValueError,"transpose: axis_offset must be 0 for int argument" |
raise ValueError,"axis_offset must be 0 for int argument" |
3078 |
return float(arg) |
return float(arg) |
3079 |
elif isinstance(arg,Symbol): |
elif isinstance(arg,Symbol): |
3080 |
if axis_offset==None: axis_offset=int(arg.getRank()/2) |
if axis_offset==None: axis_offset=int(arg.getRank()/2) |
3081 |
return Transpose_Symbol(arg,axis_offset) |
return Transpose_Symbol(arg,axis_offset) |
3082 |
else: |
else: |
3083 |
raise TypeError,"transpose: Unknown argument type." |
raise TypeError,"Unknown argument type." |
3084 |
|
|
|
def escript_transpose(arg,axis_offset): |
|
|
"arg is a Data object" |
|
|
r=arg.getRank() |
|
|
if axis_offset<0 or axis_offset>r: |
|
|
raise ValueError,"escript_transpose: axis_offset must be between 0 and %s"%r |
|
|
out=arg._transpose(axis_offset) |
|
|
return out |
|
3085 |
class Transpose_Symbol(DependendSymbol): |
class Transpose_Symbol(DependendSymbol): |
3086 |
""" |
""" |
3087 |
L{Symbol} representing the result of the transpose function |
L{Symbol} representing the result of the transpose function |
3098 |
""" |
""" |
3099 |
if axis_offset==None: axis_offset=int(arg.getRank()/2) |
if axis_offset==None: axis_offset=int(arg.getRank()/2) |
3100 |
if axis_offset<0 or axis_offset>arg.getRank(): |
if axis_offset<0 or axis_offset>arg.getRank(): |
3101 |
raise ValueError,"escript_transpose: axis_offset must be between 0 and %s"%r |
raise ValueError,"axis_offset must be between 0 and %s"%r |
3102 |
s=arg.getShape() |
s=arg.getShape() |
3103 |
super(Transpose_Symbol,self).__init__(args=[arg,axis_offset],shape=s[axis_offset:]+s[:axis_offset],dim=arg.getDim()) |
super(Transpose_Symbol,self).__init__(args=[arg,axis_offset],shape=s[axis_offset:]+s[:axis_offset],dim=arg.getDim()) |
3104 |
|
|
3165 |
if isinstance(arg,numarray.NumArray): |
if isinstance(arg,numarray.NumArray): |
3166 |
if arg.rank==2: |
if arg.rank==2: |
3167 |
if not (arg.shape[0]==arg.shape[1]): |
if not (arg.shape[0]==arg.shape[1]): |
3168 |
raise ValueError,"symmetric: argument must be square." |
raise ValueError,"argument must be square." |
3169 |
elif arg.rank==4: |
elif arg.rank==4: |
3170 |
if not (arg.shape[0]==arg.shape[2] and arg.shape[1]==arg.shape[3]): |
if not (arg.shape[0]==arg.shape[2] and arg.shape[1]==arg.shape[3]): |
3171 |
raise ValueError,"symmetric: argument must be square." |
raise ValueError,"argument must be square." |
3172 |
else: |
else: |
3173 |
raise ValueError,"symmetric: rank 2 or 4 is required." |
raise ValueError,"rank 2 or 4 is required." |
3174 |
return (arg+transpose(arg))/2 |
return (arg+transpose(arg))/2 |
3175 |
elif isinstance(arg,escript.Data): |
elif isinstance(arg,escript.Data): |
3176 |
return escript_symmetric(arg) |
if arg.getRank()==2: |
3177 |
|
if not (arg.getShape()[0]==arg.getShape()[1]): |
3178 |
|
raise ValueError,"argument must be square." |
3179 |
|
return arg._symmetric() |
3180 |
|
elif arg.getRank()==4: |
3181 |
|
if not (arg.getShape()[0]==arg.getShape()[2] and arg.getShape()[1]==arg.getShape()[3]): |
3182 |
|
raise ValueError,"argument must be square." |
3183 |
|
return arg._symmetric() |
3184 |
|
else: |
3185 |
|
raise ValueError,"rank 2 or 4 is required." |
3186 |
elif isinstance(arg,float): |
elif isinstance(arg,float): |
3187 |
return arg |
return arg |
3188 |
elif isinstance(arg,int): |
elif isinstance(arg,int): |
3190 |
elif isinstance(arg,Symbol): |
elif isinstance(arg,Symbol): |
3191 |
if arg.getRank()==2: |
if arg.getRank()==2: |
3192 |
if not (arg.getShape()[0]==arg.getShape()[1]): |
if not (arg.getShape()[0]==arg.getShape()[1]): |
3193 |
raise ValueError,"symmetric: argument must be square." |
raise ValueError,"argument must be square." |
3194 |
elif arg.getRank()==4: |
elif arg.getRank()==4: |
3195 |
if not (arg.getShape()[0]==arg.getShape()[2] and arg.getShape()[1]==arg.getShape()[3]): |
if not (arg.getShape()[0]==arg.getShape()[2] and arg.getShape()[1]==arg.getShape()[3]): |
3196 |
raise ValueError,"symmetric: argument must be square." |
raise ValueError,"argument must be square." |
3197 |
else: |
else: |
3198 |
raise ValueError,"symmetric: rank 2 or 4 is required." |
raise ValueError,"rank 2 or 4 is required." |
3199 |
return (arg+transpose(arg))/2 |
return (arg+transpose(arg))/2 |
3200 |
else: |
else: |
3201 |
raise TypeError,"symmetric: Unknown argument type." |
raise TypeError,"symmetric: Unknown argument type." |
3202 |
|
|
|
def escript_symmetric(arg): |
|
|
if arg.getRank()==2: |
|
|
if not (arg.getShape()[0]==arg.getShape()[1]): |
|
|
raise ValueError,"escript_symmetric: argument must be square." |
|
|
out=arg._symmetric() |
|
|
elif arg.getRank()==4: |
|
|
if not (arg.getShape()[0]==arg.getShape()[2] and arg.getShape()[1]==arg.getShape()[3]): |
|
|
raise ValueError,"escript_symmetric: argument must be square." |
|
|
out=arg._symmetric() |
|
|
else: |
|
|
raise ValueError,"escript_symmetric: rank 2 or 4 is required." |
|
|
return out |
|
|
|
|
3203 |
def nonsymmetric(arg): |
def nonsymmetric(arg): |
3204 |
""" |
""" |
3205 |
returns the nonsymmetric part of the square matrix arg. This is (arg-transpose(arg))/2 |
returns the nonsymmetric part of the square matrix arg. This is (arg-transpose(arg))/2 |
3220 |
raise ValueError,"nonsymmetric: rank 2 or 4 is required." |
raise ValueError,"nonsymmetric: rank 2 or 4 is required." |
3221 |
return (arg-transpose(arg))/2 |
return (arg-transpose(arg))/2 |
3222 |
elif isinstance(arg,escript.Data): |
elif isinstance(arg,escript.Data): |
3223 |
return escript_nonsymmetric(arg) |
if arg.getRank()==2: |
3224 |
|
if not (arg.getShape()[0]==arg.getShape()[1]): |
3225 |
|
raise ValueError,"argument must be square." |
3226 |
|
return arg._nonsymmetric() |
3227 |
|
elif arg.getRank()==4: |
3228 |
|
if not (arg.getShape()[0]==arg.getShape()[2] and arg.getShape()[1]==arg.getShape()[3]): |
3229 |
|
raise ValueError,"argument must be square." |
3230 |
|
return arg._nonsymmetric() |
3231 |
|
else: |
3232 |
|
raise ValueError,"rank 2 or 4 is required." |
3233 |
elif isinstance(arg,float): |
elif isinstance(arg,float): |
3234 |
return arg |
return arg |
3235 |
elif isinstance(arg,int): |
elif isinstance(arg,int): |
3247 |
else: |
else: |
3248 |
raise TypeError,"nonsymmetric: Unknown argument type." |
raise TypeError,"nonsymmetric: Unknown argument type." |
3249 |
|
|
|
def escript_nonsymmetric(arg): # this should be implemented in c++ |
|
|
if arg.getRank()==2: |
|
|
if not (arg.getShape()[0]==arg.getShape()[1]): |
|
|
raise ValueError,"escript_nonsymmetric: argument must be square." |
|
|
out=arg._nonsymmetric() |
|
|
elif arg.getRank()==4: |
|
|
if not (arg.getShape()[0]==arg.getShape()[2] and arg.getShape()[1]==arg.getShape()[3]): |
|
|
raise ValueError,"escript_nonsymmetric: argument must be square." |
|
|
out=arg._nonsymmetric() |
|
|
else: |
|
|
raise ValueError,"escript_nonsymmetric: rank 2 or 4 is required." |
|
|
return out |
|
|
|
|
|
|
|
3250 |
def inverse(arg): |
def inverse(arg): |
3251 |
""" |
""" |
3252 |
returns the inverse of the square matrix arg. |
returns the inverse of the square matrix arg. |
3390 |
if arg==self: |
if arg==self: |
3391 |
return identity(self.getShape()) |
return identity(self.getShape()) |
3392 |
else: |
else: |
3393 |
return -matrixmult(matrixmult(self,self.getDifferentiatedArguments(arg)[0]),self) |
return -matrix_mult(matrix_mult(self,self.getDifferentiatedArguments(arg)[0]),self) |
3394 |
|
|
3395 |
def eigenvalues(arg): |
def eigenvalues(arg): |
3396 |
""" |
""" |
3978 |
raise ValueError,"inner: shape of arguments does not match" |
raise ValueError,"inner: shape of arguments does not match" |
3979 |
return generalTensorProduct(arg0,arg1,axis_offset=len(sh0)) |
return generalTensorProduct(arg0,arg1,axis_offset=len(sh0)) |
3980 |
|
|
3981 |
def matrixmult(arg0,arg1): |
def outer(arg0,arg1): |
3982 |
|
""" |
3983 |
|
the outer product of the two argument: |
3984 |
|
|
3985 |
|
out[t,s]=arg0[t]*arg1[s] |
3986 |
|
|
3987 |
|
where |
3988 |
|
|
3989 |
|
- s runs through arg0.Shape |
3990 |
|
- t runs through arg1.Shape |
3991 |
|
|
3992 |
|
@param arg0: first argument |
3993 |
|
@type arg0: L{numarray.NumArray}, L{escript.Data}, L{Symbol}, C{float}, C{int} |
3994 |
|
@param arg1: second argument |
3995 |
|
@type arg1: L{numarray.NumArray}, L{escript.Data}, L{Symbol}, C{float}, C{int} |
3996 |
|
@return: the outer product of arg0 and arg1 at each data point |
3997 |
|
@rtype: L{numarray.NumArray}, L{escript.Data}, L{Symbol} depending on the input |
3998 |
|
""" |
3999 |
|
return generalTensorProduct(arg0,arg1,axis_offset=0) |
4000 |
|
|
4001 |
|
def matrixmul(arg0,arg1): |
4002 |
|
""" |
4003 |
|
see L{matrix_mult} |
4004 |
|
""" |
4005 |
|
return matrix_mult(arg0,arg1) |
4006 |
|
|
4007 |
|
def matrix_mult(arg0,arg1): |
4008 |
""" |
""" |
4009 |
matrix-matrix or matrix-vector product of the two argument: |
matrix-matrix or matrix-vector product of the two argument: |
4010 |
|
|
4014 |
|
|
4015 |
out[s0,s1]=S{Sigma}_{r0} arg0[s0,r0]*arg1[r0,s1] |
out[s0,s1]=S{Sigma}_{r0} arg0[s0,r0]*arg1[r0,s1] |
4016 |
|
|
4017 |
The second dimension of arg0 and the length of arg1 must match. |
The second dimension of arg0 and the first dimension of arg1 must match. |
4018 |
|
|
4019 |
@param arg0: first argument of rank 2 |
@param arg0: first argument of rank 2 |
4020 |
@type arg0: L{numarray.NumArray}, L{escript.Data}, L{Symbol} |
@type arg0: L{numarray.NumArray}, L{escript.Data}, L{Symbol} |
4032 |
raise ValueError,"second argument must have rank 1 or 2" |
raise ValueError,"second argument must have rank 1 or 2" |
4033 |
return generalTensorProduct(arg0,arg1,axis_offset=1) |
return generalTensorProduct(arg0,arg1,axis_offset=1) |
4034 |
|
|
4035 |
def outer(arg0,arg1): |
def tensormult(arg0,arg1): |
4036 |
""" |
""" |
4037 |
the outer product of the two argument: |
use L{tensor_mult} |
|
|
|
|
out[t,s]=arg0[t]*arg1[s] |
|
|
|
|
|
where |
|
|
|
|
|
- s runs through arg0.Shape |
|
|
- t runs through arg1.Shape |
|
|
|
|
|
@param arg0: first argument |
|
|
@type arg0: L{numarray.NumArray}, L{escript.Data}, L{Symbol}, C{float}, C{int} |
|
|
@param arg1: second argument |
|
|
@type arg1: L{numarray.NumArray}, L{escript.Data}, L{Symbol}, C{float}, C{int} |
|
|
@return: the outer product of arg0 and arg1 at each data point |
|
|
@rtype: L{numarray.NumArray}, L{escript.Data}, L{Symbol} depending on the input |
|
4038 |
""" |
""" |
4039 |
return generalTensorProduct(arg0,arg1,axis_offset=0) |
return tensor_mult(arg0,arg1) |
|
|
|
4040 |
|
|
4041 |
def tensormult(arg0,arg1): |
def tensor_mult(arg0,arg1): |
4042 |
""" |
""" |
4043 |
the tensor product of the two argument: |
the tensor product of the two argument: |
4044 |
|
|
4063 |
|
|
4064 |
out[s0,s1]=S{Sigma}_{r0,r1} arg0[s0,s1,r0,r1]*arg1[r0,r1] |
out[s0,s1]=S{Sigma}_{r0,r1} arg0[s0,s1,r0,r1]*arg1[r0,r1] |
4065 |
|
|
4066 |
In the first case the the second dimension of arg0 and the length of arg1 must match and |
In the first case the the second dimension of arg0 and the last dimension of arg1 must match and |
4067 |
in the second case the two last dimensions of arg0 must match the shape of arg1. |
in the second case the two last dimensions of arg0 must match the two first dimensions of arg1. |
4068 |
|
|
4069 |
@param arg0: first argument of rank 2 or 4 |
@param arg0: first argument of rank 2 or 4 |
4070 |
@type arg0: L{numarray.NumArray}, L{escript.Data}, L{Symbol} |
@type arg0: L{numarray.NumArray}, L{escript.Data}, L{Symbol} |
4080 |
elif len(sh0)==4 and (len(sh1)==2 or len(sh1)==3 or len(sh1)==4): |
elif len(sh0)==4 and (len(sh1)==2 or len(sh1)==3 or len(sh1)==4): |
4081 |
return generalTensorProduct(arg0,arg1,axis_offset=2) |
return generalTensorProduct(arg0,arg1,axis_offset=2) |
4082 |
else: |
else: |
4083 |
raise ValueError,"tensormult: first argument must have rank 2 or 4" |
raise ValueError,"tensor_mult: first argument must have rank 2 or 4" |
4084 |
|
|
4085 |
def generalTensorProduct(arg0,arg1,axis_offset=0): |
def generalTensorProduct(arg0,arg1,axis_offset=0): |
4086 |
""" |
""" |
4094 |
- r runs trough arg0.Shape[:axis_offset] |
- r runs trough arg0.Shape[:axis_offset] |
4095 |
- t runs through arg1.Shape[axis_offset:] |
- t runs through arg1.Shape[axis_offset:] |
4096 |
|
|
|
In the first case the the second dimension of arg0 and the length of arg1 must match and |
|
|
in the second case the two last dimensions of arg0 must match the shape of arg1. |
|
|
|
|
4097 |
@param arg0: first argument |
@param arg0: first argument |
4098 |
@type arg0: L{numarray.NumArray}, L{escript.Data}, L{Symbol}, C{float}, C{int} |
@type arg0: L{numarray.NumArray}, L{escript.Data}, L{Symbol}, C{float}, C{int} |
4099 |
@param arg1: second argument of shape greater of 1 or 2 depending on rank of arg0 |
@param arg1: second argument |
4100 |
@type arg1: L{numarray.NumArray}, L{escript.Data}, L{Symbol}, C{float}, C{int} |
@type arg1: L{numarray.NumArray}, L{escript.Data}, L{Symbol}, C{float}, C{int} |
4101 |
@return: the general tensor product of arg0 and arg1 at each data point. |
@return: the general tensor product of arg0 and arg1 at each data point. |
4102 |
@rtype: L{numarray.NumArray}, L{escript.Data}, L{Symbol} depending on the input |
@rtype: L{numarray.NumArray}, L{escript.Data}, L{Symbol} depending on the input |
4109 |
return GeneralTensorProduct_Symbol(arg0,arg1,axis_offset) |
return GeneralTensorProduct_Symbol(arg0,arg1,axis_offset) |
4110 |
else: |
else: |
4111 |
if not arg0.shape[arg0.rank-axis_offset:]==arg1.shape[:axis_offset]: |
if not arg0.shape[arg0.rank-axis_offset:]==arg1.shape[:axis_offset]: |
4112 |
raise ValueError,"generalTensorProduct: dimensions of last %s components in left argument don't match the first %s components in the right argument."%(axis_offset,axis_offset) |
raise ValueError,"dimensions of last %s components in left argument don't match the first %s components in the right argument."%(axis_offset,axis_offset) |
4113 |
arg0_c=arg0.copy() |
arg0_c=arg0.copy() |
4114 |
arg1_c=arg1.copy() |
arg1_c=arg1.copy() |
4115 |
sh0,sh1=arg0.shape,arg1.shape |
sh0,sh1=arg0.shape,arg1.shape |
4135 |
|
|
4136 |
class GeneralTensorProduct_Symbol(DependendSymbol): |
class GeneralTensorProduct_Symbol(DependendSymbol): |
4137 |
""" |
""" |
4138 |
Symbol representing the quotient of two arguments. |
Symbol representing the general tensor product of two arguments |
4139 |
""" |
""" |
4140 |
def __init__(self,arg0,arg1,axis_offset=0): |
def __init__(self,arg0,arg1,axis_offset=0): |
4141 |
""" |
""" |
4142 |
initialization of L{Symbol} representing the quotient of two arguments |
initialization of L{Symbol} representing the general tensor product of two arguments. |
4143 |
|
|
4144 |
@param arg0: numerator |
@param arg0: first argument |
4145 |
@type arg0: L{escript.Symbol}, C{float}, L{escript.Data}, L{numarray.NumArray}. |
@type arg0: L{escript.Symbol}, C{float}, L{escript.Data}, L{numarray.NumArray}. |
4146 |
@param arg1: denominator |
@param arg1: second argument |
4147 |
@type arg1: L{escript.Symbol}, C{float}, L{escript.Data}, L{numarray.NumArray}. |
@type arg1: L{escript.Symbol}, C{float}, L{escript.Data}, L{numarray.NumArray}. |
4148 |
@raise ValueError: if both arguments do not have the same shape. |
@raise ValueError: illegal dimension |
4149 |
@note: if both arguments have a spatial dimension, they must equal. |
@note: if both arguments have a spatial dimension, they must equal. |
4150 |
""" |
""" |
4151 |
sh_arg0=pokeShape(arg0) |
sh_arg0=pokeShape(arg0) |
4238 |
out.__setitem__(tuple(i0+i1),s) |
out.__setitem__(tuple(i0+i1),s) |
4239 |
return out |
return out |
4240 |
|
|
4241 |
|
|
4242 |
|
def transposed_matrix_mult(arg0,arg1): |
4243 |
|
""" |
4244 |
|
transposed(matrix)-matrix or transposed(matrix)-vector product of the two argument: |
4245 |
|
|
4246 |
|
out[s0]=S{Sigma}_{r0} arg0[r0,s0]*arg1[r0] |
4247 |
|
|
4248 |
|
or |
4249 |
|
|
4250 |
|
out[s0,s1]=S{Sigma}_{r0} arg0[r0,s0]*arg1[r0,s1] |
4251 |
|
|
4252 |
|
The function call transposed_matrix_mult(arg0,arg1) is equivalent to matrix_mult(transpose(arg0),arg1). |
4253 |
|
|
4254 |
|
The first dimension of arg0 and arg1 must match. |
4255 |
|
|
4256 |
|
@param arg0: first argument of rank 2 |
4257 |
|
@type arg0: L{numarray.NumArray}, L{escript.Data}, L{Symbol} |
4258 |
|
@param arg1: second argument of at least rank 1 |
4259 |
|
@type arg1: L{numarray.NumArray}, L{escript.Data}, L{Symbol} |
4260 |
|
@return: the product of the transposed of arg0 and arg1 at each data point |
4261 |
|
@rtype: L{numarray.NumArray}, L{escript.Data}, L{Symbol} depending on the input |
4262 |
|
@raise ValueError: if the shapes of the arguments are not appropriate |
4263 |
|
""" |
4264 |
|
sh0=pokeShape(arg0) |
4265 |
|
sh1=pokeShape(arg1) |
4266 |
|
if not len(sh0)==2 : |
4267 |
|
raise ValueError,"first argument must have rank 2" |
4268 |
|
if not len(sh1)==2 and not len(sh1)==1: |
4269 |
|
raise ValueError,"second argument must have rank 1 or 2" |
4270 |
|
return generalTransposedTensorProduct(arg0,arg1,axis_offset=1) |
4271 |
|
|
4272 |
|
def transposed_tensor_mult(arg0,arg1): |
4273 |
|
""" |
4274 |
|
the tensor product of the transposed of the first and the second argument |
4275 |
|
|
4276 |
|
for arg0 of rank 2 this is |
4277 |
|
|
4278 |
|
out[s0]=S{Sigma}_{r0} arg0[r0,s0]*arg1[r0] |
4279 |
|
|
4280 |
|
or |
4281 |
|
|
4282 |
|
out[s0,s1]=S{Sigma}_{r0} arg0[r0,s0]*arg1[r0,s1] |
4283 |
|
|
4284 |
|
|
4285 |
|
and for arg0 of rank 4 this is |
4286 |
|
|
4287 |
|
out[s0,s1,s2,s3]=S{Sigma}_{r0,r1} arg0[r0,r1,s0,s1]*arg1[r0,r1,s2,s3] |
4288 |
|
|
4289 |
|
or |
4290 |
|
|
4291 |
|
out[s0,s1,s2]=S{Sigma}_{r0,r1} arg0[r0,r1,s0,s1]*arg1[r0,r1,s2] |
4292 |
|
|
4293 |
|
or |
4294 |
|
|
4295 |
|
out[s0,s1]=S{Sigma}_{r0,r1} arg0[r0,r1,s0,s1]*arg1[r0,r1] |
4296 |
|
|
4297 |
|
In the first case the the first dimension of arg0 and the first dimension of arg1 must match and |
4298 |
|
in the second case the two first dimensions of arg0 must match the two first dimension of arg1. |
4299 |
|
|
4300 |
|
The function call transposed_tensor_mult(arg0,arg1) is equivalent to tensor_mult(transpose(arg0),arg1). |
4301 |
|
|
4302 |
|
@param arg0: first argument of rank 2 or 4 |
4303 |
|
@type arg0: L{numarray.NumArray}, L{escript.Data}, L{Symbol} |
4304 |
|
@param arg1: second argument of shape greater of 1 or 2 depending on rank of arg0 |
4305 |
|
@type arg1: L{numarray.NumArray}, L{escript.Data}, L{Symbol} |
4306 |
|
@return: the tensor product of tarnsposed of arg0 and arg1 at each data point |
4307 |
|
@rtype: L{numarray.NumArray}, L{escript.Data}, L{Symbol} depending on the input |
4308 |
|
""" |
4309 |
|
sh0=pokeShape(arg0) |
4310 |
|
sh1=pokeShape(arg1) |
4311 |
|
if len(sh0)==2 and ( len(sh1)==2 or len(sh1)==1 ): |
4312 |
|
return generalTransposedTensorProduct(arg0,arg1,axis_offset=1) |
4313 |
|
elif len(sh0)==4 and (len(sh1)==2 or len(sh1)==3 or len(sh1)==4): |
4314 |
|
return generalTransposedTensorProduct(arg0,arg1,axis_offset=2) |
4315 |
|
else: |
4316 |
|
raise ValueError,"first argument must have rank 2 or 4" |
4317 |
|
|
4318 |
|
def generalTransposedTensorProduct(arg0,arg1,axis_offset=0): |
4319 |
|
""" |
4320 |
|
generalized tensor product of transposed of arg0 and arg1: |
4321 |
|
|
4322 |
|
out[s,t]=S{Sigma}_r arg0[r,s]*arg1[r,t] |
4323 |
|
|
4324 |
|
where |
4325 |
|
|
4326 |
|
- s runs through arg0.Shape[axis_offset:] |
4327 |
|
- r runs trough arg0.Shape[:axis_offset] |
4328 |
|
- t runs through arg1.Shape[axis_offset:] |
4329 |
|
|
4330 |
|
The function call generalTransposedTensorProduct(arg0,arg1,axis_offset) is equivalent |
4331 |
|
to generalTensorProduct(transpose(arg0,arg0.rank-axis_offset),arg1,axis_offset). |
4332 |
|
|
4333 |
|
@param arg0: first argument |
4334 |
|
@type arg0: L{numarray.NumArray}, L{escript.Data}, L{Symbol}, C{float}, C{int} |
4335 |
|
@param arg1: second argument |
4336 |
|
@type arg1: L{numarray.NumArray}, L{escript.Data}, L{Symbol}, C{float}, C{int} |
4337 |
|
@return: the general tensor product of transposed(arg0) and arg1 at each data point. |
4338 |
|
@rtype: L{numarray.NumArray}, L{escript.Data}, L{Symbol} depending on the input |
4339 |
|
""" |
4340 |
|
if isinstance(arg0,float) and isinstance(arg1,float): return arg1*arg0 |
4341 |
|
arg0,arg1=matchType(arg0,arg1) |
4342 |
|
# at this stage arg0 and arg0 are both numarray.NumArray or escript.Data or Symbols |
4343 |
|
if isinstance(arg0,numarray.NumArray): |
4344 |
|
if isinstance(arg1,Symbol): |
4345 |
|
return GeneralTransposedTensorProduct_Symbol(arg0,arg1,axis_offset) |
4346 |
|
else: |
4347 |
|
if not arg0.shape[:axis_offset]==arg1.shape[:axis_offset]: |
4348 |
|
raise ValueError,"dimensions of last %s components in left argument don't match the first %s components in the right argument."%(axis_offset,axis_offset) |
4349 |
|
arg0_c=arg0.copy() |
4350 |
|
arg1_c=arg1.copy() |
4351 |
|
sh0,sh1=arg0.shape,arg1.shape |
4352 |
|
d0,d1,d01=1,1,1 |
4353 |
|
for i in sh0[axis_offset:]: d0*=i |
4354 |
|
for i in sh1[axis_offset:]: d1*=i |
4355 |
|
for i in sh0[:axis_offset]: d01*=i |
4356 |
|
arg0_c.resize((d01,d0)) |
4357 |
|
arg1_c.resize((d01,d1)) |
4358 |
|
out=numarray.zeros((d0,d1),numarray.Float64) |
4359 |
|
for i0 in range(d0): |
4360 |
|
for i1 in range(d1): |
4361 |
|
out[i0,i1]=numarray.sum(arg0_c[:,i0]*arg1_c[:,i1]) |
4362 |
|
out.resize(sh0[axis_offset:]+sh1[axis_offset:]) |
4363 |
|
return out |
4364 |
|
elif isinstance(arg0,escript.Data): |
4365 |
|
if isinstance(arg1,Symbol): |
4366 |
|
return GeneralTransposedTensorProduct_Symbol(arg0,arg1,axis_offset) |
4367 |
|
else: |
4368 |
|
return escript_generalTransposedTensorProduct(arg0,arg1,axis_offset) # this calls has to be replaced by escript._generalTensorProduct(arg0,arg1,axis_offset) |
4369 |
|
else: |
4370 |
|
return GeneralTransposedTensorProduct_Symbol(arg0,arg1,axis_offset) |
4371 |
|
|
4372 |
|
class GeneralTransposedTensorProduct_Symbol(DependendSymbol): |
4373 |
|
""" |
4374 |
|
Symbol representing the general tensor product of the transposed of arg0 and arg1 |
4375 |
|
""" |
4376 |
|
def __init__(self,arg0,arg1,axis_offset=0): |
4377 |
|
""" |
4378 |
|
initialization of L{Symbol} representing tensor product of the transposed of arg0 and arg1 |
4379 |
|
|
4380 |
|
@param arg0: first argument |
4381 |
|
@type arg0: L{escript.Symbol}, C{float}, L{escript.Data}, L{numarray.NumArray}. |
4382 |
|
@param arg1: second argument |
4383 |
|
@type arg1: L{escript.Symbol}, C{float}, L{escript.Data}, L{numarray.NumArray}. |
4384 |
|
@raise ValueError: inconsistent dimensions of arguments. |
4385 |
|
@note: if both arguments have a spatial dimension, they must equal. |
4386 |
|
""" |
4387 |
|
sh_arg0=pokeShape(arg0) |
4388 |
|
sh_arg1=pokeShape(arg1) |
4389 |
|
sh01=sh_arg0[:axis_offset] |
4390 |
|
sh10=sh_arg1[:axis_offset] |
4391 |
|
sh0=sh_arg0[axis_offset:] |
4392 |
|
sh1=sh_arg1[axis_offset:] |
4393 |
|
if not sh01==sh10: |
4394 |
|
raise ValueError,"dimensions of last %s components in left argument don't match the first %s components in the right argument."%(axis_offset,axis_offset) |
4395 |
|
DependendSymbol.__init__(self,dim=commonDim(arg0,arg1),shape=sh0+sh1,args=[arg0,arg1,axis_offset]) |
4396 |
|
|
4397 |
|
def getMyCode(self,argstrs,format="escript"): |
4398 |
|
""" |
4399 |
|
returns a program code that can be used to evaluate the symbol. |
4400 |
|
|
4401 |
|
@param argstrs: gives for each argument a string representing the argument for the evaluation. |
4402 |
|
@type argstrs: C{list} of length 2 of C{str}. |
4403 |
|
@param format: specifies the format to be used. At the moment only "escript", "str" and "text" are supported. |
4404 |
|
@type format: C{str} |
4405 |
|
@return: a piece of program code which can be used to evaluate the expression assuming the values for the arguments are available. |
4406 |
|
@rtype: C{str} |
4407 |
|
@raise NotImplementedError: if the requested format is not available |
4408 |
|
""" |
4409 |
|
if format=="escript" or format=="str" or format=="text": |
4410 |
|
return "generalTransposedTensorProduct(%s,%s,axis_offset=%s)"%(argstrs[0],argstrs[1],argstrs[2]) |
4411 |
|
else: |
4412 |
|
raise NotImplementedError,"%s does not provide program code for format %s."%(str(self),format) |
4413 |
|
|
4414 |
|
def substitute(self,argvals): |
4415 |
|
""" |
4416 |
|
assigns new values to symbols in the definition of the symbol. |
4417 |
|
The method replaces the L{Symbol} u by argvals[u] in the expression defining this object. |
4418 |
|
|
4419 |
|
@param argvals: new values assigned to symbols |
4420 |
|
@type argvals: C{dict} with keywords of type L{Symbol}. |
4421 |
|
@return: result of the substitution process. Operations are executed as much as possible. |
4422 |
|
@rtype: L{escript.Symbol}, C{float}, L{escript.Data}, L{numarray.NumArray} depending on the degree of substitution |
4423 |
|
@raise TypeError: if a value for a L{Symbol} cannot be substituted. |
4424 |
|
""" |
4425 |
|
if argvals.has_key(self): |
4426 |
|
arg=argvals[self] |
4427 |
|
if self.isAppropriateValue(arg): |
4428 |
|
return arg |
4429 |
|
else: |
4430 |
|
raise TypeError,"%s: new value is not appropriate."%str(self) |
4431 |
|
else: |
4432 |
|
args=self.getSubstitutedArguments(argvals) |
4433 |
|
return generalTransposedTensorProduct(args[0],args[1],args[2]) |
4434 |
|
|
4435 |
|
def escript_generalTransposedTensorProduct(arg0,arg1,axis_offset): # this should be escript._generalTransposedTensorProduct |
4436 |
|
"arg0 and arg1 are both Data objects but not neccesrily on the same function space. they could be identical!!!" |
4437 |
|
# calculate the return shape: |
4438 |
|
shape01=arg0.getShape()[:axis_offset] |
4439 |
|
shape10=arg1.getShape()[:axis_offset] |
4440 |
|
shape0=arg0.getShape()[axis_offset:] |
4441 |
|
shape1=arg1.getShape()[axis_offset:] |
4442 |
|
if not shape01==shape10: |
4443 |
|
raise ValueError,"dimensions of first %s components in left argument don't match the first %s components in the right argument."%(axis_offset,axis_offset) |
4444 |
|
|
4445 |
|
# whatr function space should be used? (this here is not good!) |
4446 |
|
fs=(escript.Scalar(0.,arg0.getFunctionSpace())+escript.Scalar(0.,arg1.getFunctionSpace())).getFunctionSpace() |
4447 |
|
# create return value: |
4448 |
|
out=escript.Data(0.,tuple(shape0+shape1),fs) |
4449 |
|
# |
4450 |
|
s0=[[]] |
4451 |
|
for k in shape0: |
4452 |
|
s=[] |
4453 |
|
for j in s0: |
4454 |
|
for i in range(k): s.append(j+[slice(i,i)]) |
4455 |
|
s0=s |
4456 |
|
s1=[[]] |
4457 |
|
for k in shape1: |
4458 |
|
s=[] |
4459 |
|
for j in s1: |
4460 |
|
for i in range(k): s.append(j+[slice(i,i)]) |
4461 |
|
s1=s |
4462 |
|
s01=[[]] |
4463 |
|
for k in shape01: |
4464 |
|
s=[] |
4465 |
|
for j in s01: |
4466 |
|
for i in range(k): s.append(j+[slice(i,i)]) |
4467 |
|
s01=s |
4468 |
|
|
4469 |
|
for i0 in s0: |
4470 |
|
for i1 in s1: |
4471 |
|
s=escript.Scalar(0.,fs) |
4472 |
|
for i01 in s01: |
4473 |
|
s+=arg0.__getitem__(tuple(i01+i0))*arg1.__getitem__(tuple(i01+i1)) |
4474 |
|
out.__setitem__(tuple(i0+i1),s) |
4475 |
|
return out |
4476 |
|
|
4477 |
|
|
4478 |
|
def matrix_transposed_mult(arg0,arg1): |
4479 |
|
""" |
4480 |
|
matrix-transposed(matrix) product of the two argument: |
4481 |
|
|
4482 |
|
out[s0,s1]=S{Sigma}_{r0} arg0[s0,r0]*arg1[s1,r0] |
4483 |
|
|
4484 |
|
The function call matrix_transposed_mult(arg0,arg1) is equivalent to matrix_mult(arg0,transpose(arg1)). |
4485 |
|
|
4486 |
|
The last dimensions of arg0 and arg1 must match. |
4487 |
|
|
4488 |
|
@param arg0: first argument of rank 2 |
4489 |
|
@type arg0: L{numarray.NumArray}, L{escript.Data}, L{Symbol} |
4490 |
|
@param arg1: second argument of rank 2 |
4491 |
|
@type arg1: L{numarray.NumArray}, L{escript.Data}, L{Symbol} |
4492 |
|
@return: the product of arg0 and the transposed of arg1 at each data point |
4493 |
|
@rtype: L{numarray.NumArray}, L{escript.Data}, L{Symbol} depending on the input |
4494 |
|
@raise ValueError: if the shapes of the arguments are not appropriate |
4495 |
|
""" |
4496 |
|
sh0=pokeShape(arg0) |
4497 |
|
sh1=pokeShape(arg1) |
4498 |
|
if not len(sh0)==2 : |
4499 |
|
raise ValueError,"first argument must have rank 2" |
4500 |
|
if not len(sh1)==2 and not len(sh1)==1: |
4501 |
|
raise ValueError,"second argument must have rank 1 or 2" |
4502 |
|
return generalTensorTransposedProduct(arg0,arg1,axis_offset=1) |
4503 |
|
|
4504 |
|
def tensor_transposed_mult(arg0,arg1): |
4505 |
|
""" |
4506 |
|
the tensor product of the first and the transpose of the second argument |
4507 |
|
|
4508 |
|
for arg0 of rank 2 this is |
4509 |
|
|
4510 |
|
out[s0,s1]=S{Sigma}_{r0} arg0[s0,r0]*arg1[s1,r0] |
4511 |
|
|
4512 |
|
and for arg0 of rank 4 this is |
4513 |
|
|
4514 |
|
out[s0,s1,s2,s3]=S{Sigma}_{r0,r1} arg0[s0,s1,r0,r1]*arg1[s2,s3,r0,r1] |
4515 |
|
|
4516 |
|
or |
4517 |
|
|
4518 |
|
out[s0,s1,s2]=S{Sigma}_{r0,r1} arg0[s0,s1,r0,r1]*arg1[s2,r0,r1] |
4519 |
|
|
4520 |
|
In the first case the the second dimension of arg0 and arg1 must match and |
4521 |
|
in the second case the two last dimensions of arg0 must match the two last dimension of arg1. |
4522 |
|
|
4523 |
|
The function call tensor_transpose_mult(arg0,arg1) is equivalent to tensor_mult(arg0,transpose(arg1)). |
4524 |
|
|
4525 |
|
@param arg0: first argument of rank 2 or 4 |
4526 |
|
@type arg0: L{numarray.NumArray}, L{escript.Data}, L{Symbol} |
4527 |
|
@param arg1: second argument of shape greater of 1 or 2 depending on rank of arg0 |
4528 |
|
@type arg1: L{numarray.NumArray}, L{escript.Data}, L{Symbol} |
4529 |
|
@return: the tensor product of tarnsposed of arg0 and arg1 at each data point |
4530 |
|
@rtype: L{numarray.NumArray}, L{escript.Data}, L{Symbol} depending on the input |
4531 |
|
""" |
4532 |
|
sh0=pokeShape(arg0) |
4533 |
|
sh1=pokeShape(arg1) |
4534 |
|
if len(sh0)==2 and ( len(sh1)==2 or len(sh1)==1 ): |
4535 |
|
return generalTensorTransposedProduct(arg0,arg1,axis_offset=1) |
4536 |
|
elif len(sh0)==4 and (len(sh1)==2 or len(sh1)==3 or len(sh1)==4): |
4537 |
|
return generalTensorTransposedProduct(arg0,arg1,axis_offset=2) |
4538 |
|
else: |
4539 |
|
raise ValueError,"first argument must have rank 2 or 4" |
4540 |
|
|
4541 |
|
def generalTensorTransposedProduct(arg0,arg1,axis_offset=0): |
4542 |
|
""" |
4543 |
|
generalized tensor product of transposed of arg0 and arg1: |
4544 |
|
|
4545 |
|
out[s,t]=S{Sigma}_r arg0[s,r]*arg1[t,r] |
4546 |
|
|
4547 |
|
where |
4548 |
|
|
4549 |
|
- s runs through arg0.Shape[:arg0.Rank-axis_offset] |
4550 |
|
- r runs trough arg0.Shape[arg1.Rank-axis_offset:] |
4551 |
|
- t runs through arg1.Shape[arg1.Rank-axis_offset:] |
4552 |
|
|
4553 |
|
The function call generalTensorTransposedProduct(arg0,arg1,axis_offset) is equivalent |
4554 |
|
to generalTensorProduct(arg0,transpose(arg1,arg1.Rank-axis_offset),axis_offset). |
4555 |
|
|
4556 |
|
@param arg0: first argument |
4557 |
|
@type arg0: L{numarray.NumArray}, L{escript.Data}, L{Symbol}, C{float}, C{int} |
4558 |
|
@param arg1: second argument |
4559 |
|
@type arg1: L{numarray.NumArray}, L{escript.Data}, L{Symbol}, C{float}, C{int} |
4560 |
|
@return: the general tensor product of transposed(arg0) and arg1 at each data point. |
4561 |
|
@rtype: L{numarray.NumArray}, L{escript.Data}, L{Symbol} depending on the input |
4562 |
|
""" |
4563 |
|
if isinstance(arg0,float) and isinstance(arg1,float): return arg1*arg0 |
4564 |
|
arg0,arg1=matchType(arg0,arg1) |
4565 |
|
# at this stage arg0 and arg0 are both numarray.NumArray or escript.Data or Symbols |
4566 |
|
if isinstance(arg0,numarray.NumArray): |
4567 |
|
if isinstance(arg1,Symbol): |
4568 |
|
return GeneralTensorTransposedProduct_Symbol(arg0,arg1,axis_offset) |
4569 |
|
else: |
4570 |
|
if not arg0.shape[arg0.rank-axis_offset:]==arg1.shape[arg1.rank-axis_offset:]: |
4571 |
|
raise ValueError,"dimensions of last %s components in left argument don't match the first %s components in the right argument."%(axis_offset,axis_offset) |
4572 |
|
arg0_c=arg0.copy() |
4573 |
|
arg1_c=arg1.copy() |
4574 |
|
sh0,sh1=arg0.shape,arg1.shape |
4575 |
|
d0,d1,d01=1,1,1 |
4576 |
|
for i in sh0[:arg0.rank-axis_offset]: d0*=i |
4577 |
|
for i in sh1[:arg1.rank-axis_offset]: d1*=i |
4578 |
|
for i in sh1[arg1.rank-axis_offset:]: d01*=i |
4579 |
|
arg0_c.resize((d0,d01)) |
4580 |
|
arg1_c.resize((d1,d01)) |
4581 |
|
out=numarray.zeros((d0,d1),numarray.Float64) |
4582 |
|
for i0 in range(d0): |
4583 |
|
for i1 in range(d1): |
4584 |
|
out[i0,i1]=numarray.sum(arg0_c[i0,:]*arg1_c[i1,:]) |
4585 |
|
out.resize(sh0[:arg0.rank-axis_offset]+sh1[:arg1.rank-axis_offset]) |
4586 |
|
return out |
4587 |
|
elif isinstance(arg0,escript.Data): |
4588 |
|
if isinstance(arg1,Symbol): |
4589 |
|
return GeneralTensorTransposedProduct_Symbol(arg0,arg1,axis_offset) |
4590 |
|
else: |
4591 |
|
return escript_generalTensorTransposedProduct(arg0,arg1,axis_offset) # this calls has to be replaced by escript._generalTensorProduct(arg0,arg1,axis_offset) |
4592 |
|
else: |
4593 |
|
return GeneralTensorTransposedProduct_Symbol(arg0,arg1,axis_offset) |
4594 |
|
|
4595 |
|
class GeneralTensorTransposedProduct_Symbol(DependendSymbol): |
4596 |
|
""" |
4597 |
|
Symbol representing the general tensor product of arg0 and the transpose of arg1 |
4598 |
|
""" |
4599 |
|
def __init__(self,arg0,arg1,axis_offset=0): |
4600 |
|
""" |
4601 |
|
initialization of L{Symbol} representing the general tensor product of arg0 and the transpose of arg1 |
4602 |
|
|
4603 |
|
@param arg0: first argument |
4604 |
|
@type arg0: L{escript.Symbol}, C{float}, L{escript.Data}, L{numarray.NumArray}. |
4605 |
|
@param arg1: second argument |
4606 |
|
@type arg1: L{escript.Symbol}, C{float}, L{escript.Data}, L{numarray.NumArray}. |
4607 |
|
@raise ValueError: inconsistent dimensions of arguments. |
4608 |
|
@note: if both arguments have a spatial dimension, they must equal. |
4609 |
|
""" |
4610 |
|
sh_arg0=pokeShape(arg0) |
4611 |
|
sh_arg1=pokeShape(arg1) |
4612 |
|
sh0=sh_arg0[:len(sh_arg0)-axis_offset] |
4613 |
|
sh01=sh_arg0[len(sh_arg0)-axis_offset:] |
4614 |
|
sh10=sh_arg1[len(sh_arg1)-axis_offset:] |
4615 |
|
sh1=sh_arg1[:len(sh_arg1)-axis_offset] |
4616 |
|
if not sh01==sh10: |
4617 |
|
raise ValueError,"dimensions of last %s components in left argument don't match the last %s components in the right argument."%(axis_offset,axis_offset) |
4618 |
|
DependendSymbol.__init__(self,dim=commonDim(arg0,arg1),shape=sh0+sh1,args=[arg0,arg1,axis_offset]) |
4619 |
|
|
4620 |
|
def getMyCode(self,argstrs,format="escript"): |
4621 |
|
""" |
4622 |
|
returns a program code that can be used to evaluate the symbol. |
4623 |
|
|
4624 |
|
@param argstrs: gives for each argument a string representing the argument for the evaluation. |
4625 |
|
@type argstrs: C{list} of length 2 of C{str}. |
4626 |
|
@param format: specifies the format to be used. At the moment only "escript", "str" and "text" are supported. |
4627 |
|
@type format: C{str} |
4628 |
|
@return: a piece of program code which can be used to evaluate the expression assuming the values for the arguments are available. |
4629 |
|
@rtype: C{str} |
4630 |
|
@raise NotImplementedError: if the requested format is not available |
4631 |
|
""" |
4632 |
|
if format=="escript" or format=="str" or format=="text": |
4633 |
|
return "generalTensorTransposedProduct(%s,%s,axis_offset=%s)"%(argstrs[0],argstrs[1],argstrs[2]) |
4634 |
|
else: |
4635 |
|
raise NotImplementedError,"%s does not provide program code for format %s."%(str(self),format) |
4636 |
|
|
4637 |
|
def substitute(self,argvals): |
4638 |
|
""" |
4639 |
|
assigns new values to symbols in the definition of the symbol. |
4640 |
|
The method replaces the L{Symbol} u by argvals[u] in the expression defining this object. |
4641 |
|
|
4642 |
|
@param argvals: new values assigned to symbols |
4643 |
|
@type argvals: C{dict} with keywords of type L{Symbol}. |
4644 |
|
@return: result of the substitution process. Operations are executed as much as possible. |
4645 |
|
@rtype: L{escript.Symbol}, C{float}, L{escript.Data}, L{numarray.NumArray} depending on the degree of substitution |
4646 |
|
@raise TypeError: if a value for a L{Symbol} cannot be substituted. |
4647 |
|
""" |
4648 |
|
if argvals.has_key(self): |
4649 |
|
arg=argvals[self] |
4650 |
|
if self.isAppropriateValue(arg): |
4651 |
|
return arg |
4652 |
|
else: |
4653 |
|
raise TypeError,"%s: new value is not appropriate."%str(self) |
4654 |
|
else: |
4655 |
|
args=self.getSubstitutedArguments(argvals) |
4656 |
|
return generalTensorTransposedProduct(args[0],args[1],args[2]) |
4657 |
|
|
4658 |
|
def escript_generalTensorTransposedProduct(arg0,arg1,axis_offset): # this should be escript._generalTensorTransposedProduct |
4659 |
|
"arg0 and arg1 are both Data objects but not neccesrily on the same function space. they could be identical!!!" |
4660 |
|
# calculate the return shape: |
4661 |
|
shape01=arg0.getShape()[arg0.getRank()-axis_offset:] |
4662 |
|
shape0=arg0.getShape()[:arg0.getRank()-axis_offset] |
4663 |
|
shape10=arg1.getShape()[arg1.getRank()-axis_offset:] |
4664 |
|
shape1=arg1.getShape()[:arg1.getRank()-axis_offset] |
4665 |
|
if not shape01==shape10: |
4666 |
|
raise ValueError,"dimensions of first %s components in left argument don't match the first %s components in the right argument."%(axis_offset,axis_offset) |
4667 |
|
|
4668 |
|
# whatr function space should be used? (this here is not good!) |
4669 |
|
fs=(escript.Scalar(0.,arg0.getFunctionSpace())+escript.Scalar(0.,arg1.getFunctionSpace())).getFunctionSpace() |
4670 |
|
# create return value: |
4671 |
|
out=escript.Data(0.,tuple(shape0+shape1),fs) |
4672 |
|
# |
4673 |
|
s0=[[]] |
4674 |
|
for k in shape0: |
4675 |
|
s=[] |
4676 |
|
for j in s0: |
4677 |
|
for i in range(k): s.append(j+[slice(i,i)]) |
4678 |
|
s0=s |
4679 |
|
s1=[[]] |
4680 |
|
for k in shape1: |
4681 |
|
s=[] |
4682 |
|
for j in s1: |
4683 |
|
for i in range(k): s.append(j+[slice(i,i)]) |
4684 |
|
s1=s |
4685 |
|
s01=[[]] |
4686 |
|
for k in shape01: |
4687 |
|
s=[] |
4688 |
|
for j in s01: |
4689 |
|
for i in range(k): s.append(j+[slice(i,i)]) |
4690 |
|
s01=s |
4691 |
|
|
4692 |
|
for i0 in s0: |
4693 |
|
for i1 in s1: |
4694 |
|
s=escript.Scalar(0.,fs) |
4695 |
|
for i01 in s01: |
4696 |
|
s+=arg0.__getitem__(tuple(i0+i01))*arg1.__getitem__(tuple(i1+i01)) |
4697 |
|
out.__setitem__(tuple(i0+i1),s) |
4698 |
|
return out |
4699 |
|
|
4700 |
|
|
4701 |
#========================================================= |
#========================================================= |
4702 |
# functions dealing with spatial dependency |
# functions dealing with spatial dependency |