【问题标题】:ODE solver from Lagrangian/Variational Methods in C++来自 C++ 中的拉格朗日/变分方法的 ODE 求解器
【发布时间】:2015-09-24 15:15:02
【问题描述】:

我有一个一般性问题,我将在更具体的情况下提出这个问题。

如果想找到双摆的动力学,可以用数学方法推导出运动方程,将 ODE 重写为对数值计算有用的特殊形式,然后使用 C++ 中的 odeint 求解 ODE(参见堆栈溢出的示例https://stackoverflow.com/a/30582741)。

现在假设我们想对 n 个耦合摆(n 在运行时已知)做同样的事情。这需要我们写出所谓的拉格朗日(动能-势能),这个函数的不同导数将是我们需要求解的 ODE。此外,这些 ODE 必须以适合 odeint 的形式重写。这对于一般 n 来说很难手工完成。

在像 Mathematica 和 Maple 这样的程序中,这实际上很容易。可以从拉格朗日函数中显式推导出所需的常微分方程,而常微分方程求解器不需要我们将方程置于任何特殊形式(请参阅此处的数学示例https://mathematica.stackexchange.com/a/84279)。

有没有可能在c++中做这样的事情而不会遇到太多麻烦?

可能的方法:

一种可能的方法是使用 c++ 包ginac。这可以帮助我们分析推导 ODE。但我不知道如何将来自 ginac 的表达式重写为适合 odeint 中数值计算的形式。有什么想法吗?

【问题讨论】:

  • 对于仅在运行时知道的 n,恐怕您面临着几乎不可能的困难。如果您在编译时知道 n,我认为您可以基于自动微分和表达式模板来实现这样的计算。从我对 ginac 的(表面)检查来看,我认为这个库也是基于表达式模板的,因此在编译时需要 n。
  • @mariomulansky 非常感谢您的评论。现在,如果我能在编译时做到这一点,我会很高兴。如何使用表达式模板将 ginac 输出转换为 odeint 可以理解的形式?是否存在一些简单的标准方法?
  • 我没有使用 GiNaC 的经验,所以帮不上什么忙。然而,通过他们的教程阅读更多内容,我想到你可以在运行时构造一个表达式,区分它并评估结果。所以我上面的第一条评论可能是不正确的。尝试将 Langragian 写成 GiNaC 表达式、区分它并在 rhs 中使用生成的表达式来表示 odeint 声音听起来确实是一种可行的方法。如果你真的让它运行​​,我会对代码非常感兴趣。或许你可以在 odeint 的 github 上分享:github.com/headmyshoulder/odeint-v2
  • 您也可以将 Lagrange 系统视为 index-3 DAE 系统,并使用通常用于约束动力学的 BDF 或 RADAU 求解器。或者手动对约束方程进行两次微分,并通过 ODE 函数中的牛顿对二阶导数的所得非线性系统进行数值求解。
  • @mariomulansky 是的,似乎可以直接评估表达式,这应该足以将其放入 odeint。当我有时间时,我会尝试实现它,我很乐意分享代码。对于这种更具体的情况(n-pendula),可能有一种更简单的方法。如果我使用普通笛卡尔坐标并使用拉格朗日乘数实现摆约束,则哈密顿量的形式为 H=T(p) + V(q)(q 之间的乘数)。也许从那里可以直接使用 odeint 的辛积分器?

标签: c++ simulation physics symbolic-math odeint


【解决方案1】:

在您只需要计算 dV/dq 而不需要计算 dT/dp 的意义上,微不足道的 intertia 项很有帮助。 odeint 提供了一个辛积分器版本,它只期望 dV/dq 并假设 dT/dp 在您的情况下是微不足道的。但是,您仍然需要获得一个导数。

【讨论】:

    猜你喜欢
    • 2022-08-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多