- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
我正试图找到一种方法来使这段代码更快。
Nagumo1 是计算两个导数在时间 t 的值的函数。
function x = nagumo(t, y, f)
Iapp = f(t);
e = 0.1;
F = 2/(1+exp(-5*y(1)));
n0 = 0;
x = zeros(2, 1);
z(1) = y(1) - (y(1).^3)/3 - y(2).^2 + Iapp; %z(1) = dV/dt
z(2) = e.*(F + n0 - y(2)); %z(2) = dn/dt
x = [z(1);z(2)];
end
它是一个微分方程组,代表了一个大大简化的神经元模型。 V 表示电位差,n 表示 K+/Na+ channel 的数量,Iapp 是施加到神经元的电流。时间变量 (t) 以毫秒为单位。
我想使用可变步长的欧拉显式方法对微分方程组进行数值求解并绘制解。
function x = EulerExplicit1(V0, n0, tspan, Iapp)
format long;
erreura = 10^-3;
erreurr = 10^-6;
h = 0.1;
to =tspan(1, 1) + h;
temps = tspan(1, 1);
tf = tspan(1, 2);
y = zeros(1,2);
yt1 = zeros(1, 2);
yt2 = zeros(1, 2);
y = [V0, n0];
z = y;
i = 1;
s = zeros(1, 2);
st1 = zeros(1, 2);
while temps<tf
s = nagumo1(to+i*h, y, Iapp);
y = y + h*s;
yt1 = y + (h/2)*s;
st1 = nagumo1(to+(i*h+h/2), yt1, Iapp);
yt2 = yt1 + (h/2)*st1;
if abs(yt2-y)>(erreura+erreurr*abs(y))
test = 0;
elseif h<0.4
h = h*2;
test = 0;
end
while test == 0
if abs(yt2-y)>(erreura+erreurr*abs(y)) & h>0.01
h = h/2;
s = nagumo1(to+i*h, y, Iapp);
y = y + h*s;
yt1 = y + (h/2)*s;
st1 = nagumo1(to+i*h+h/2, yt1, Iapp);
yt2 = yt1 + (h/2)*st1;
else
test = 1;
end
end
z = [ z ; y ];
temps = [temps; temps(i)+h];
i = i+1;
end
x = zeros(size(z));
x = z;
disp('Nombre d iterations:');
disp(i);
plot(temps, x(:, 1:end), 'y');
grid;
end
我没有包含任何评论,因为我认为它很清楚。我只想保持可适应的步骤 h 并使代码更快。理想情况下,我想找到一种方法来初始化 z 和 temps(time),但是当我尝试这样做时,我在绘制解决方案时遇到了问题。请注意,当 erreura(绝对误差)和 erreurr(相对误差)大于 10^-6 时,我的解决方案与 ode45 解决方案(我认为是准确的)相比变化很大。
有什么想法吗?
附言如果你想测试使用值在 -2、V 为 2、n 为 0,1、1、Iapp 为 0.1、1 之间变化(定义函数句柄 @(t))。
最佳答案
在尝试加速解释代码之前,您应该注意获得正确的解决方案。在仅对固定步长有效的时间计算 to+i*h
中仍然存在一些错误是可见的。我将从第一原则解释自适应方法。
使用时间 t
以步长 h
计算的数值解与一阶精确解相关的近似值作为
y(h;t)=y_exact(t) + C*t*h + O(t*h²)
给出半尺寸的一步和两步的进步有错误
y(h;h) = y_exact(h) + C*h² + O(h³)
y(h/2;h) = y_exact(h)+C*h²/2 + O(h³)
因此
y(h;h)-y(h/2;h) = C*h²/2 + O(h³)
是步长 h/2
的局部误差估计量。我们知道一阶局部误差会添加到全局误差中(在更好的近似中,有一些与 Lipschitz 常数的复合作为“年”利率)。因此,在相反的方向上,我们希望得到局部错误是全局错误的 h
大小的一部分。将所有局部误差量除以 h
以获得与全局误差直接比较的值。
现在尝试保留局部误差估计 local_err = norm(y(h;h)-y(h/2;h))/h = norm(C)*h/2
一些走廊 [tol/100, tol]
其中“tol”代表所需的全局误差。因此,当前数据的理想步长计算为
tol = norm(C)*h_ideal/2 = local_err*h_ideal/h
<==>
h_ideal = tol / local_err * h
在算法中,人们会计算这些积分步骤和误差估计,然后接受步骤并在公差范围内推进计算,然后通过上述公式调整步长以进入循环的下一次迭代。除了使用计算出的理想步长之外,还可以在理想步长的方向上通过常数因子修改步长。一般来说,这只会增加被拒绝的步数,以达到理想的步长。
为避免尝试和使用的步长出现振荡和过于突然的变化,引入某种移动平均线,抑制方向1
的变化因子,如
a = tol / (1e-12+local_err);
h = 0.25*(3+a^0.8)*h ;
while t < t_final
if t+1.1*h > t_final
h = t_final - t
force_advance = True
end
s1 = f(t,y)
s05 = f(t+0.5*h, y+0.5*h*s1)
s2 = 0.5*(s1+s05)
localerr = norm(s2-s1)
tol = abstol+norm(y)*reltol
if force_advance | (0.01*tol < localerr & localerr < tol)
y = y + h*s2
t = t + h
sol_y(end+1)=y
sol_t(end+1)=t
force_advance = False
end
a = tol / (1e-19+localerr) )
h = 0.25*(3+a^0.8)*h ;
if h < h_min
h = h_min
force_advance = True
end
if h > h_max
h = h_max
force_advance = True
end
end
该方法的实际应用给出了如下图。
在顶部描绘了解曲线。在弯曲或快速变化的部分可以看到更高的密度,而在解曲线更直的地方可以看到更低的密度。在下部显示了针对最低公差解决方案的错误。差异由解决方案的公差缩放,以便所有共享相同的比例。可以看出,输出密切跟踪输入要求的公差。
关于differential-equations - 具有自适应步长的 Matlab Euler Explicit ode 求解器,有没有办法使代码更快?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49256309/
我正在使用混合效应模型,并且由于我的方法的特殊性我需要解决下面模型的积分,然后制作图表获得的估计值。 换句话说,我需要求解下面的积分: 其中,di^2 是我模型中的 Var3,dh 是混合效应模型对应
我有一个方程组,我想用数值方法求解它。给定起始种子,我想得到一个接近的解决方案。让我解释。 我有一个常量向量,X,值: X <- (c(1,-2,3,4)) 和一个向量 W 的权重: W <- (c(
假设我有以下方程组: a * b = 5 sqrt(a * b^2) = 10 如何求解 R 中 a 和 b 的这些方程? 我想这个问题可以说是一个优化问题,具有以下功能......? fn <- f
我在 R 中有一个简单的通量模型。它归结为两个微分方程,对模型中的两个状态变量进行建模,我们将它们称为 A和 B .它们被计算为四个分量通量的简单差分方程 flux1-flux4 , 5 个参数 p1
R有什么办法吗?求解给定单变量函数的反函数?动机是我以后告诉R使用值向量作为反函数的输入,以便它可以吐出反函数值。 例如,我有函数 y(x) = x^2 ,逆是 y = sqrt(x) .有没有办法R
我在字符串中有以下方程 y = 18774x + 82795 求解x我会这样做:- x = (y-82795) / 18774 我知道y的值 但是方程一直在变化,并且始终采用字符串格式 是否可以简单地
如果我用 diophantine(2*x+3*y-5*z-77) 我收到了这个结果。 {(t_0, -9*t_0 - 5*t_1 + 154, -5*t_0 - 3*t_1 + 77)} 到目前为止还
我正在尝试求解仅限于正解的 ODE,即: dx/dt=f(x) x>=0。 在 MATLAB 中这很容易实现。 R 是否有任何变通方法或包来将解决方案空间限制为仅正值? 这对我来说非常重要,不幸的是没
下面的 ANTLR 文法中的 'expr' 规则显然是相互左递归的。作为一个 ANTLR 新手,我很难解决这个问题。我已经阅读了 ANTLR 引用书中的“解决非 LL(*) 冲突”,但我仍然没有看到解
我有一个关于在 R 中求解函数的可能性的非常基本的问题,但知道答案确实有助于更好地理解 R。 我有以下等式: 0=-100/(1+r)+(100-50)/(1+r)^2+(100-50)/(1+r)^
我正在编写使用递归回溯来解决 8 个皇后问题的代码(将 n 个国际象棋皇后放在 n × n 的棋盘上,这样皇后就不会互相攻击)。 我的任务是创建两个方法:编写一个公共(public)solveQuee
我不知道在以下情况下如何进行,因为最后一个方程没有所有 4 个变量。所以使用了等式下面的代码,但这是错误的......有谁知道如何进行? 方程: 3a + 4b - 5c + d = 10 2a +
假设我们有这个递归关系,它出现在 AVL 树的分析中: F1 = 1 F2 = 2 Fn = Fn - 1 + Fn - 2 + 1(其中 n ≥ 3) 你将如何解决这个递归以获得 F(n) 的封闭形
在Maple中,有谁知道是否存在一个函数来求解变量?例如,我正在尝试求解 r 的 solve4r=(M-x^y)*(r^(-1)) mod (p-1)。所以我知道 M、x、y 和 p 的值,但不知道
我也问过这个here在声音设计论坛上,但问题是沉重的计算机科学/数学,所以它实际上可能属于这个论坛: 因此,通过读取文件中的二进制文件,我能够成功地找到关于 WAV 文件的所有信息,除了 big si
我有以下问题: 设 a 和 b 为 boolean 变量。是否可以设置 a 和 b 的值以使以下表达式的计算结果为 false? b or (((not a) or (not a)) or (a or
我需要用 C 求解这个超越方程: x = 2.0 - 0.5sen(x) 我试过这个: double x, newx, delta; x = 2.0 - 0.5; newx = sin(x); del
我在 Windows 上使用 OpenCV 3.1。 一段代码: RNG rng; // random number generator cv::Mat rVec = (cv::Mat_(3, 1)
我正在尝试求解一个包含 3 个变量和数量可变的方程的方程组。 基本上,系统的长度在 5 到 12 个方程之间,无论有多少个方程,我都试图求解 3 个变量。 看起来像这样: (x-A)**2 + (y-
我正在尝试为有限差分法设计一种算法,但我有点困惑。所讨论的 ODE 是 y''-5y'+10y = 10x,其中 y(0)=0 且 y(1)=100。所以我需要一种方法来以某种方式获得将从关系中乘以“
我是一名优秀的程序员,十分优秀!