Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/asp.net-mvc/16.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Julia中微分方程的循环生成函数_Julia_Differentialequations.jl - Fatal编程技术网

Julia中微分方程的循环生成函数

Julia中微分方程的循环生成函数,julia,differentialequations.jl,Julia,Differentialequations.jl,以洛伦兹为例() 如果我必须在循环中生成方程,我会尝试在循环中串联字符串,然后将它们转换为函数。在Matlab中,这是可行的()。有了朱莉娅,我迷路了(这实际上是我在朱莉娅身上尝试的第一件事)。 我的第一次尝试是: function lorenz(t,u,du) Ex = :(du[1] = 10.0*(u[2]-u[1])) eval(ex) du[2] = u[1]*(28.0-u[3]) - u[2] du[3] = u[1]*u[2] - (8/3)*u[

以洛伦兹为例()

如果我必须在循环中生成方程,我会尝试在循环中串联字符串,然后将它们转换为函数。在Matlab中,这是可行的()。有了朱莉娅,我迷路了(这实际上是我在朱莉娅身上尝试的第一件事)。 我的第一次尝试是:

function lorenz(t,u,du)
    Ex = :(du[1] = 10.0*(u[2]-u[1]))
    eval(ex)
    du[2] = u[1]*(28.0-u[3]) - u[2]
    du[3] = u[1]*u[2] - (8/3)*u[3]
end
不工作(u未定义;后面是可能由于在
prob=ODEProblem(lorenz,u0,tspan)中使用此函数而产生的错误行)
谁能给我指一下正确的方向吗。 第一个问题是,当函数进入
ODEProblem
时,我无法找到函数发生了什么。请有人告诉我在哪里可以找到函数的真正含义。

EDIT1

我刚试过

ex = quote
function lorenz(t,u,du)
    du[1] = 10.0*(u[2]-u[1])
    du[2] = u[1]*(28.0-u[3]) - u[2]
    du[3] = u[1]*u[2] - (8/3)*u[3]
end
end
eval(ex)
这是可行的。所以我知道一种可行的方法。但我担心我可能偶然发现了“一种方法”;而不是首选的方法。请更熟悉
Julia
的人发表评论


EDIT2

需要求解的方程组示例:

du[1] = u[1] + v[1] + U
dv[1] = v[1] + U

du[2] = u[2] + v[2] + U
dv[2] = v[2] + U

...

这里的
U
U[i]
的和(我从1到
M
;应该可以在变量中设置
M
的值)。

在MATLAB中,你应该尝试避免循环。在Julia中,这种上下文中的循环是优化的,因此没有理由避免它。编写此函数的简单方法是:

function f(t,u,du)
  U = sum(u)
  for i in eachindex(u)
    du[i] = u[i] + v[i] + U
    dv[i] = v[i] + U
  end
end
请注意,这甚至不需要对长度的引用,因此它将适用于任何大小的
u
du
。因此创建
ODEProblem(f,u0,tspan)
其中
u0
是您的大小
M
数组,您会很好

我们可以使用一些性能宏来进一步优化它。
@inbounds
关闭边界检查,所以这样做很好

function f(t,u,du)
  U = sum(u)
  @inbounds for i in eachindex(u)
    du[i] = u[i] + v[i] + U
    dv[i] = v[i] + U
  end
end
在某些情况下,如果循环足够长,我们可能需要对其强制执行
@simd

function f(t,u,du)
  U = sum(u)
  @simd for i in eachindex(u)
    @inbounds du[i] = u[i] + v[i] + U
    @inbounds dv[i] = v[i] + U
  end
end
或者,如果它真的很长,则对其进行多线程处理:

function f(t,u,du)
  U = sum(u)
  Threads.@threads for i in eachindex(u)
    @inbounds du[i] = u[i] + v[i] + U
    @inbounds dv[i] = v[i] + U
  end
end

(当然也要确保你自己)。

如果不需要,你真的应该避免使用
eval
。你这里的问题是:(A)eval在全球范围内,(B)你不能将变量转义到表达式中。但这绝对不是解决问题的正确方法。你能解释一下你想做什么,这样我们才能给出一个更合适的解决方案吗?我猜你可以这样做,但你只考虑这样做,因为有一个MATLAB大脑,有一个更简单的方法你没有尝试过的方法。我正在求解一个2N个方程组的系统,每个方程组都有很长的表达式,但结构相似,可以通过for循环得到……N可能会根据需要的精度而改变。使用for循环,我不必重写方程组。为什么不在函数中循环?方程组的数量应该ld具有
2N=长度(u)
所以你可以在函数中使用它。对,每个方程中都有一个求和项,需要我在u上循环。这一点也不错。Julia中的循环在性能上类似于C。除了一些编译器优化(如果你展开整个方程,理论上可能会发生)之外,循环会给你full性能(事实上,编译器也会对循环进行许多优化)。你不应该不必要地避免这种情况。但是如果你真的想避免这种情况,那么在
Val{N}上调度的生成函数上使用闭包
可以,但我强烈建议先编写循环。避免在MATLAB中使用循环,但不要在Julia中使用循环!
function f(t,u,du)
  U = sum(u)
  Threads.@threads for i in eachindex(u)
    @inbounds du[i] = u[i] + v[i] + U
    @inbounds dv[i] = v[i] + U
  end
end