Because it would imo raise the barrier to use a lot. A new type is sort of
viral in the sense that if you use it, it is likely that you should use the
type everywhere you are using Voigt Tensors.
I want this to be directly usable even if you have written all your FEM
code with Vector{Float64} and just want to use this in a few places.
So I got something now.
I can now for example do:
const SYMIND = [1 6 5;
9 2 4;
8 7 3]
const UNSYMIND = [1 6 5;
6 2 4;
5 4 3]
v_sym = [1,2,3,4,5,6]
v_unsym = [1,2,3,4,5,6,7,8,9]
@v v_sym[1,1] * v_unsym[2,2] + v_unsym[2,3]
# -> 6
However, I think I am doing something wrong when I am appending expressions
to each other. This is the macroexpanded version:
julia> macroexpand(:(@v v_sym[1,1] * v_unsym[2,2] + v_unsym[2,3]))
quote # none, line 12:
begin # none, line 7:
begin # none, line 7:
() # none, line 8:
begin # none, line 10:
if length(v_sym) == 6 # none, line 11:
__Iv_sym = SYMIND
else # none, line 13:
__Iv_sym = UNSYMIND
end
end
end # none, line 8:
begin # none, line 10:
if length(v_unsym) == 6 # none, line 11:
__Iv_unsym = SYMIND
else # none, line 13:
__Iv_unsym = UNSYMIND
end
end
end # none, line 13:
v_sym[__Iv_sym[1,1]] * v_unsym[__Iv_unsym[2,2]] +
v_unsym[__Iv_unsym[2,3]]
end
And here is the code I use. Am I concatenating the expressions correctly?
# Find all the different symbols that gets indexed,
# for example :v and :q in :(v[1] * q[1])
function findsyms(e::Expr, d::Set{Symbol})
if e.head==:ref
push!(d, e.args[1])
else
for a in e.args
findsyms(a, d)
end
end
return d
end
findsyms(a, d) = a
# Creates vector of expression that sets the correct index matrix
# depending on the size
function initiate(e::Expr)
d = Set{Symbol}()
findsyms(e::Expr, d::Set{Symbol})
es = Vector{Expr}()
for sym in d
s = esc(Symbol("__I" * string(sym)))
e = quote
if length($sym) == 6
$s = SYMIND
else
$s = UNSYMIND
end
end
push!(es, e)
end
return es
end
# Changes v[1,2] -> v[Iv[1,2]]
function sub!(e::Expr)
if e.head==:ref
for a in e.args
sub!(a)
end
sym = esc(Symbol("__I" * string(e.args[1])))
newe = :($(e.args[1])[$sym[$(e.args[2:end]...)]])
e.args = newe.args
else
for a in e.args
sub!(a)
end
end
e
end
sub!(s) = s
# Constructs the final expression
function vexp(e::Expr)
exps = initiate(e::Expr)
sub!(e)
f_exp = :()
for exp in exps
f_exp = quote
$f_exp
$exp
end
end
f_exp = quote
$f_exp
$e
end
return f_exp
end
macro v(e)
vexp(e)
end
On Wednesday, September 30, 2015 at 11:30:04 AM UTC+2, Mauro wrote:
>
> I see. Why are you not making a new type to allow getindex overloading?
> That would be more work but maybe cleaner?
>
> On Wed, 2015-09-30 at 11:10, Kristoffer Carlsson <[email protected]
> <javascript:>> wrote:
> > I am not sure that I want Ragged Arrays, In my code I have symmetric 3x3
> > matrices stored as vectors of length 6 and unsymmetric 3x3 matrices
> stored
> > as vectors of length 9.
> >
> > As I know you do some FEM Mauro I can describe my problem more
> > specifically. I am writing a package do more easily deal with Voigt
> tensors
> > and I want to add the option of accessing them just like they where
> > matrices. Since different people use different order of their indices I
> > want the user to be able to set what order the offdiagonal indices will
> be
> > stored in the Voigt vector. I have a global state in my module that maps
> > [i,j] -> k where k is the index in the vector.
> >
> > I will try your macro now! Thanks a lot for the help.
> >
> >
> >
> >
> > On Wednesday, September 30, 2015 at 10:57:14 AM UTC+2, Mauro wrote:
> >>
> >> > Hello everyone,
> >> >
> >> > I am trying to write a macro that transforms an expression like:
> >> >
> >> > @foo v[1,2] + v[1,3]*v[2,4] -> v[I[1,2]] + v[I[1,3]]*v[I[2,4]]
> >> >
> >> > Basically, for each getindex I want to insert a lookup of the index
> in
> >> some
> >> > other variable.
> >> > The reason for this is that I am working with matrices encoded as
> >> vectors
> >> > and I want to still call them like matrices. The "I" vector in the
> code
> >> > is the lookup from two dimensional indexing to one dimensional.
> >> >
> >> > v is just a normal Vector so I cannot extend getindex which is why I
> >> > thought a macro would be the cleanest solution.
> >> >
> >> > I am a bit lost how to start so any help would be appreciated.
> >>
> >> Sounds like you may want to use
> >> https://github.com/mbauman/RaggedArrays.jl (or my more primitive
> >> Ragged.jl)
> >>
> >> If not, this may work:
> >>
> >> function sub!(e::Expr)
> >> if e.head==:ref
> >> for a in e.args
> >> sub!(a)
> >> end
> >> newe = :($(e.args[1])[I[$(e.args[2:end]...)]])
> >> e.args = newe.args
> >> else
> >> for a in e.args
> >> sub!(a)
> >> end
> >> end
> >> e
> >> end
> >> sub!(s) = s
> >>
> >> e = :(v[1,2] + v[1,3]*v[2,4])
> >> sub!(e)
> >> macro foo(e)
> >> sub!(e)
> >> end
> >>
>