2016-05-21 12 views
2

私のパッケージのユーザーに関数をより数学的な方法で定義させたいと思っています。マクロが正しい方向だと思います。問題は次のとおりです。このコードでは、ユーザーは特殊なソルバーでPDEを解決するために使用される関数を定義できます。しかし、ソルバを簡単にするために、入力の一部は、通常はそうではないと思わない方法で「行列」です。たとえば、ソルバは関数f(x,t)を取り込むことができますが、は、xx[:,2]と考えると、y(時には3Dです)と考えられます。Julia:ベクトルエイリアシングのマクロ

大きな問題は、PDEが非線形である場合、多くの場合(反応拡散方程式のような)これらのものの名前が付けられたときにすべてをuベクトルに配置することです。したがって、この一般的なケースでは、私は、私のマクロfooの上嗅ぎまでないです

@mathdefine f(RA,RABP,RAR,x,y,t) = RA*RABP + RA*x + RAR*t

を書いて、それが

f(u,x,t) = u[:,1].*u[:,2] + u[:,1].*x[:,1] + u[:,3]*t

に変換持ってできるようにしたいと思いますだから私は誰かが私を始められるようにしたいと思っていた(マクロがこれに近づく正しい方法でないなら、理由を説明してください)。

ユーザーは何に翻訳されているのかを伝える必要がありますが、できるだけ使用するにはきれいであるようにしたいと思っています。だから何とかそれが空間変数にあることを知っています。 uの一部ですが、その後はxの一部です。

答えて

4

マクロ "find/replace"のトリックは、式argsを更新する再帰関数に処理を渡すだけです。あなたの署名はシンボルの束として来るので、コールシグネチャをループし、変数名を列インデックスにマッピングする2つの辞書に追加することができます。その後、変数のいずれかが見えたら、argツリーを再帰的に置き換えます。これはテストされていません:

function replace_vars!(expr::Expr, xd::Dict{Symbol,Int}, ud::Dict{Symbol,Int}) 
    for (i,arg) in enumerate(expr.args) 
    if haskey(xd, arg) 
     expr.arg[i] = :(x[:,$(xd[arg])]) 
    elseif haskey(ud, arg) 
     expr.arg[i] = :(u[:,$(ud[arg])]) 
    elseif isa(arg,Expr) 
     replace_vars!(arg, xd, ud) 
    end 
    end 
end 

macro mathdefine(expr) 
    # todo: loop through function signature (expr.args[1]?) to build xd/ud 
    replace_vars!(expr) 
    expr 
end 

私はあなたのために少し宿題を残しましたが、これはあなたを始めなければなりません。