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 
> >> 
>

Reply via email to