Julia:矢量别名宏
Julia: Macros for vector aliasing
我希望能够让我的包的用户以更数学的方式定义函数,我认为宏是正确的方向。问题如下。该代码允许用户定义函数,然后在专门的求解器中使用这些函数来求解 PDE。但是,为了让求解器更轻松,一些输入 "matrices" 的方式通常不会是您认为的。例如,求解器可以接受函数 f(x,t)
,但 x[:,1]
是您认为的 x
而 x[:,2]
是您认为的 y
(有时是 3D)。
更大的问题是,当 PDE 是非线性的时,我将所有内容都放在一个 u
向量中,而在许多情况下(如反应-扩散方程),这些内容都是被命名的。所以在这种一般情况下,我希望能够写
@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
我对我的 macro-foo 不满意,所以我希望有人能帮助我开始(或者如果宏不是解决这个问题的正确方法,请解释原因)。
如果用户必须提供正在翻译的内容并不太难,但我希望它尽可能干净地使用,所以不知何故知道它是空间变量等等一切之前是 u
的一部分,但之后是 x
.
的一部分
宏 "find/replace" 的技巧只是将处理传递给更新表达式参数的递归函数。您的签名将以一堆符号的形式出现,因此您可以循环调用签名并添加到两个字典,将变量名称映射到列索引。然后在看到任何变量时递归地替换 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
我给你留了一点功课,但这应该能让你入门。
我希望能够让我的包的用户以更数学的方式定义函数,我认为宏是正确的方向。问题如下。该代码允许用户定义函数,然后在专门的求解器中使用这些函数来求解 PDE。但是,为了让求解器更轻松,一些输入 "matrices" 的方式通常不会是您认为的。例如,求解器可以接受函数 f(x,t)
,但 x[:,1]
是您认为的 x
而 x[:,2]
是您认为的 y
(有时是 3D)。
更大的问题是,当 PDE 是非线性的时,我将所有内容都放在一个 u
向量中,而在许多情况下(如反应-扩散方程),这些内容都是被命名的。所以在这种一般情况下,我希望能够写
@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
我对我的 macro-foo 不满意,所以我希望有人能帮助我开始(或者如果宏不是解决这个问题的正确方法,请解释原因)。
如果用户必须提供正在翻译的内容并不太难,但我希望它尽可能干净地使用,所以不知何故知道它是空间变量等等一切之前是 u
的一部分,但之后是 x
.
宏 "find/replace" 的技巧只是将处理传递给更新表达式参数的递归函数。您的签名将以一堆符号的形式出现,因此您可以循环调用签名并添加到两个字典,将变量名称映射到列索引。然后在看到任何变量时递归地替换 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
我给你留了一点功课,但这应该能让你入门。