Matlab Euler 显式 ode 求解器具有自适应步骤,有没有办法使代码更快?

2023-12-09

我正在尝试找到一种方法来使此代码更快。

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+神经管的数量,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、2(V)、0,1、1(n)、0.1、1(Iapp)之间的变化值(定义了一个函数句柄@(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³)

and thus

y(h;h)-y(h/2;h) = C*h²/2 + O(h³)

是步长下局部误差的估计h/2。我们知道,一阶局部误差会增加全局误差(在更好的近似中,存在与利普希茨常数作为“年”利率的复合)。因此,在相反的方向上,我们希望得到局部误差是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

该方法的实际应用如下图所示。

enter image description here

顶部描绘了解决方案曲线。人们会在弯曲或快速变化的部分看到较高的密度,而在解曲线更直的地方看到较低的密度。在下部显示相对于最低公差解的误差。差异按解决方案的容差进行缩放,以便所有的都具有相同的比例。正如我们所看到的,输出密切跟踪输入所需的容差。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Matlab Euler 显式 ode 求解器具有自适应步骤,有没有办法使代码更快? 的相关文章

  • 使用到达时间差对信号进行三边测量

    我在寻找或实现寻找信号源的算法时遇到一些麻烦 我的工作目标是找到声音发射器的位置 为了实现这一点 我使用了三个麦克风 我正在使用的技术是多点定位这是基于到达时间差 The 到达时间差使用发现每个麦克风之间互相关接收到的信号 我已经实现了算法
  • 更新:随机将行添加到矩阵中,但遵循严格的规则

    以下是一个更大的矩阵的一部分 0 1 0000 1 0000 77 0000 100 0000 0 0 2500 0 1 0000 1 0000 72 0000 100 0000 0 2500 0 2500 0 1 0000 1 0000
  • 帮助我理解FFT函数(Matlab)

    1 除了负频率之外 FFT 函数提供的最小频率是多少 是零吗 2 如果它为零 我们如何在对数刻度上绘制零 3 结果总是对称的 或者只是看起来是对称的 4 如果我使用abs fft y 来比较2个信号 我是否会失去一些准确性 1 除了负频率之
  • 如何使用 python 有效地找到两个大文件的交集?

    我有两个大文件 它们的内容如下所示 134430513125296589151963957125296589 该文件包含未排序的 id 列表 某些 id 可能会在单个文件中出现多次 现在我想找到路口两个文件的一部分 这就是两个文件中都出现的
  • 如何从 Trie 中检索给定长度的随机单词

    我有一个简单的 Trie 用来存储大约 80k 长度为 2 15 的单词 它非常适合检查字符串是否是单词 但是 现在我需要一种获取给定长度的随机单词的方法 换句话说 我需要 getRandomWord 5 来返回 5 个字母的单词 所有 5
  • 像matlab一样在python中连接数组而不知道输出数组的大小

    我正在尝试在 python 中连接数组 类似于 matlab array1 zeros 3 500 array2 ones 3 700 array array1 array2 我在 python 中做了以下操作 array1 np zero
  • 考虑预分配速度[重复]

    这个问题在这里已经有答案了 我正在做以下事情 for i 1 m index 0 for j 1 n index index values i j 2 j 1 if j 1 symbol chip chip values index 1 e
  • 优化重叠矩形的绘制

    我有很多矩形 有些与其他矩形重叠 每个矩形都有一个绝对 z 顺序和一个colour 每个 矩形 实际上是粒子效果 网格或纹理的轴对齐边界框 并且可能是半透明的 但只要您不尝试剔除其他矩形后面的矩形 就更容易抽象地思考彩色矩形 所以我将在问题
  • 布隆过滤器的使用

    我正在努力理解布隆过滤器的用处 我了解了它的底层逻辑 空间压缩 快速查找 误报等 我只是不能将这个概念应用到现实生活中 因为它是有益的 一种常见的应用是在 Web 缓存中使用布隆过滤器 我们使用布隆过滤器来确定给定的 URL 是否在缓存中
  • 在 Pari-GP 中嵌套特定递归

    每个人 我最初在 Stackexchange 上发布了类似的问题 它已移至此处 可以在链接中找到 在 Matlab 中声明函数递归序列 https stackoverflow com questions 67146061 declaring
  • 融合元组以查找等价类

    假设我们有一个包含 k 个元素的有限域 D d1 dk 我们认为 S 是 D n 的子集 即一组 形式的元组 其中 ai 在 D 中 我们希望使用 S 2 D n 的子集 即一组 形式的元组 其中 Ai 是 D 的子集 来 紧凑地 表示它
  • 如何提高洪水填充例程的性能?

    我正在我的应用程序中实现四路洪水填充 伪代码如下 Flood fill node target color replacement color 1 If the color of node is not equal to target co
  • 测量数组的“无序”程度

    给定一个值数组 我想找到总 分数 其中每个元素的分数是数组中出现在其之前的具有较小值的元素的数量 e g values 4 1 3 2 5 scores 0 0 1 1 4 total score 6 O n 2 算法很简单 但我怀疑可以通
  • 寻找局部最小值

    下面的代码正确地找到了数组的局部最大值 但未能找到局部最小值 我已经进行了网络搜索 以找到找到最小值的最佳方法 并且根据这些搜索 我认为我正在使用下面的正确方法 但是 在几天的时间里多次检查每一行之后 下面的代码中有一些我仍然没有看到的错误
  • 寻找簇的中心

    我有以下问题 进行抽象以找出关键问题 我有 10 个点 每个点与其他点有一定距离 我想要 能够找到簇的中心 即与其他点的成对距离最小的点 令 p j p k 表示点 j 和 k 之间的成对距离p i 是簇的中心点 iff p i s t m
  • 如何在Matlab中将图像从笛卡尔坐标更改为极坐标?

    我正在尝试将图像的像素从 x y 坐标转换为极坐标 但我遇到了问题 因为我想自己编写该函数 这是我到目前为止所做的代码 function newImage PolarCartRot read and show the image image
  • matlab中优先级队列的实现方法

    matlab中有没有提供minpriorityqueue功能的库 import java util PriorityQueue import java util public class MyQueue Comparator
  • 如何在matlab中使矩阵图平滑

    就像上图一样 怎样才能让画面更流畅呢 或者缩小y轴的范围 数据来自二维矩阵 然后我用plot data 请随意提出任何想法 平滑线条的一种方法涉及样本点之间数据的非线性插值 当你这样做时plot x y o http www mathwor
  • 为什么Python中pop()的大O与pop(0)不同[重复]

    这个问题在这里已经有答案了 他们不应该都是O 1 因为从 Python 列表中的任何位置弹出一个元素涉及销毁该列表并在新的内存位置创建一个元素 蟒蛇的list实现使用动态调整大小的 Carray在引擎盖下 删除元素usually要求您移动后
  • 为什么我们需要检测链表中的循环

    我看到很多关于如何检测链表中的循环的问答 但我想了解的是我们为什么要这样做 换句话说 检测链表中的循环的实际用例是什么 在现实生活中 您可能永远不需要检测链表中的循环 但是执行此操作的算法很重要 我在现实生活中多次使用它们 例如 我经常会递

随机推荐