如何模拟由给定信号驱动的谐振子(不是由正弦波驱动)

发布于 2024-09-16 01:45:39 字数 99 浏览 4 评论 0原文

我有一个值表,告诉我信号电平如何随时间变化,我想模拟由该信号驱动的谐振子。即使模拟不是 100% 准确也没关系。 我知道振荡器的频率。 我找到了很多公式,但它们都使用正弦波作为驱动器。

I've got a table of values telling me how the signal level changes over time and I want to simulate a harmonic oscillator driven by this signal. It does not matter if the simulation is not 100% accurate.
I know the frequency of the oscillator.
I found lots of formulas but they all use a sine wave as driver.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

云柯 2024-09-23 01:45:39

我猜你想执行一些时间离散模拟。众所周知的公式需要分析输入(参见格林函数)。如果您有某个时间点的力表,典型的分析公式不会对您有太大帮助。

这个想法是这样的:对于时间 t0 的每个点,振荡器都有一些给定的加速度、速度等。现在一个力作用在它上 - 根据给定的表格 - 这将改变它的加速度 (F = m * a) 。对于下一个时间步 t1,我们假设加速度保持在该常数,因此我们可以应用简单的牛顿方程< /a> (v = a * dt) 且该时间范围内 dt = (t1-t0)。迭代直到模拟出所需的时间范围。

这个模拟最重要的参数是dt,即计算的细粒度程度。例如,您可能希望每秒 10 步,但这完全取决于您的输入参数。本质上,我们在这里所做的是方程的欧拉积分

当然,这并不是全部 - 这种模拟可能非常复杂,尤其是。在表现不佳的情况下,例如极端加速等。在这些情况下,您需要在一帧内执行数值健全性检查,因为在单个帧中会发生“极端”的情况。此外,一些数值积分可能变得必要,例如 Runge-Kutta 算法 。然而,我想这在这一点上已经很遥远了。

编辑:就在我发布此内容后,有人对原始问题发表了评论,指出“

I guess you want to perform some time-discrete simulation. The well-known formulae require analytic input (see Green's function). If you have a table of forces at some point in time, the typical analytical formulae won't help you too much.

The idea is this: For each point in time t0, the oscillator has some given acceleration, velocity, etc. Now a force acts on it -according to the table you were given- which will change it's acceleration (F = m * a). For the next time step t1, we assume the acceleration stays at that constant, so we can apply simple Newtonian equations (v = a * dt) with dt = (t1-t0) for this time frame. Iterate until the desired range in time is simulated.

The most important parameter of this simulation is dt, that is, how fine-grained the calculation is. For example, you might want to have 10 steps per second, but that completely depends on your input parameters. What we're doing here, in essence, is an Eulerian integration of the equations.

This, of course, isn't all there is - such simulations can be quite complicated, esp. in not-so-well behaved cases where extreme accelerations, etc. In those cases you need to perform numerical sanity checks within a frame, because something 'extreme' happens in a single frame. Also some numerical integration might become necessary, e.g. the Runge-Kutta algorithm. I guess that leads to far at this point, however.

EDIT: Just after I posted this, somebody posted a comment to the original question pointing to the "Verlet Algorithm", which is basically an implementation of what I described above.

酒中人 2024-09-23 01:45:39

好吧,我终于弄清楚了,并编写了一个 GUI 应用程序来测试它,直到它起作用。但我的电脑对每秒执行 1000*44100 次不太满意,即使没有 gui^^

无论如何:这是我的测试代码(效果很好):

double lastTime;  
const double deltaT = 1 / 44100.0;//length of a frame in seconds  
double rFreq;  
private void InitPendulum()  
{  
double freq = 2;//frequency in herz  
rFreq = FToRSpeed(freq);  
damp = Math.Pow(0.8, freq * deltaT);  
}  

private static double FToRSpeed(double p)  
{  
p *= 2;  
p = Math.PI * p;  
return p * p;  
}  
double damp;  
double bHeight;  
double bSpeed;  
double lastchange;  
private void timer1_Tick(object sender, EventArgs e)  
{  
  double now=sw.ElapsedTicks/(double)Stopwatch.Frequency;  
  while (lastTime+deltaT <= now)  
  {  
    bHeight += bSpeed * deltaT;  
    double prevSpeed=bSpeed;  
    bSpeed += (mouseY - bHeight) * (rFreq*deltaT);  
    bSpeed *= damp;  
    if ((bSpeed > 0) != (prevSpeed > 0))  
    {  
      Console.WriteLine(lastTime - lastchange);  
      lastchange = lastTime;  
    }  
    lastTime += deltaT;  
  }  
  Invalidate();//No, i am not using gdi^^  
}

Ok, i finally figured it out and wrote a gui app to test it until it worked. But my pc is not very happy with doing it 1000*44100 times per second, even without gui^^

Whatever: here is my test code (wich worked quite well):

double lastTime;  
const double deltaT = 1 / 44100.0;//length of a frame in seconds  
double rFreq;  
private void InitPendulum()  
{  
double freq = 2;//frequency in herz  
rFreq = FToRSpeed(freq);  
damp = Math.Pow(0.8, freq * deltaT);  
}  

private static double FToRSpeed(double p)  
{  
p *= 2;  
p = Math.PI * p;  
return p * p;  
}  
double damp;  
double bHeight;  
double bSpeed;  
double lastchange;  
private void timer1_Tick(object sender, EventArgs e)  
{  
  double now=sw.ElapsedTicks/(double)Stopwatch.Frequency;  
  while (lastTime+deltaT <= now)  
  {  
    bHeight += bSpeed * deltaT;  
    double prevSpeed=bSpeed;  
    bSpeed += (mouseY - bHeight) * (rFreq*deltaT);  
    bSpeed *= damp;  
    if ((bSpeed > 0) != (prevSpeed > 0))  
    {  
      Console.WriteLine(lastTime - lastchange);  
      lastchange = lastTime;  
    }  
    lastTime += deltaT;  
  }  
  Invalidate();//No, i am not using gdi^^  
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文