修改rk4方法的C实现

发布于 2024-11-04 16:44:52 字数 2813 浏览 1 评论 0原文

坦率地说,我的问题是我不确定这是如何运作的。

我需要修改 double f() 函数来解决任意问题 微分方程 d2θ/dt2 = −ω2sinθ,但事实上我不确定如何继续。

我理解 rk4 函数 runge4() 本身;我不明白的是如何 f() 函数返回谐振子的正确值。

有人至少可以解释一下 f() 函数背后的逻辑吗?

原始代码如下。

/* 
************************************************************************
*  rk4.c: 4th order Runge-Kutta solution for harmonic oscillator       *
*                      *
* From: "A SURVEY OF COMPUTATIONAL PHYSICS" 
   by RH Landau, MJ Paez, and CC BORDEIANU 
   Copyright Princeton University Press, Princeton, 2008.
   Electronic Materials copyright: R Landau, Oregon State Univ, 2008;
   MJ Paez, Univ Antioquia, 2008; & CC BORDEIANU, Univ Bucharest, 2008
   Support by National Science Foundation                              
*
************************************************************************
*/

#include <stdio.h>

#define N 2                                   /* number of equations */
#define dist 0.1                              /* stepsize */
#define MIN 0.0                               /* minimum x */
#define MAX 10.0                              /* maximum x */

void runge4(double x, double y[], double step);
double f(double x, double y[], int i);

int main()
{

   double x, y[N];
   int j;

   FILE *output;                              /* save data in rk4.dat */
   output = fopen("rk4.dat","w");

   y[0] = 1.0;                                /* initial position  */
   y[1] = 0.0;                                /* initial velocity  */

   fprintf(output, "%f\t%f\n", x, y[0]);

   for(x = MIN; x <= MAX ; x += dist)
   {
      runge4(x, y, dist);
      fprintf(output, "%f\t%f\n", x, y[0]);   /* position vs. time */
   }
   printf("data stored in rk4.dat\n");
   fclose(output);
}
/*-----------------------end of main program--------------------------*/

/* Runge-Kutta subroutine */
void runge4(double x, double y[], double step)
{
   double h=step/2.0,                         /* the midpoint */
          t1[N], t2[N], t3[N],                /* temporary storage */
          k1[N], k2[N], k3[N],k4[N];          /* for Runge-Kutta  */
   int i;

   for (i=0; i<N; i++) t1[i] = y[i]+0.5*(k1[i]=step*f(x, y, i));
   for (i=0; i<N; i++) t2[i] = y[i]+0.5*(k2[i]=step*f(x+h, t1, i));
   for (i=0; i<N; i++) t3[i] = y[i]+    (k3[i]=step*f(x+h, t2, i));
   for (i=0; i<N; i++) k4[i] =                 step*f(x + step, t3, i);

   for (i=0; i<N; i++) y[i] += (k1[i]+2*k2[i]+2*k3[i]+k4[i])/6.0;
}
/*--------------------------------------------------------------------*/

/* definition of equations - this is the harmonic oscillator */
double  f(double x, double y[], int i)
{
   if (i == 0) return(y[1]);               /* RHS of first equation */
   if (i == 1) return(-y[0]);              /* RHS of second equation */
}

My problem is, frankly, that I'm unsure how this works.

I need to modify the double f() function to solve an arbitrary
differential equation d2θ/dt2 = −ω2sinθ, but as it is I am unsure how to proceed.

The rk4 function runge4() itself I understand; What I don't understand is how the
f() function returns the correct values for the harmonic oscillator.

Would someone please at least explain the logic behind the f() function?

Original code is below.

/* 
************************************************************************
*  rk4.c: 4th order Runge-Kutta solution for harmonic oscillator       *
*                      *
* From: "A SURVEY OF COMPUTATIONAL PHYSICS" 
   by RH Landau, MJ Paez, and CC BORDEIANU 
   Copyright Princeton University Press, Princeton, 2008.
   Electronic Materials copyright: R Landau, Oregon State Univ, 2008;
   MJ Paez, Univ Antioquia, 2008; & CC BORDEIANU, Univ Bucharest, 2008
   Support by National Science Foundation                              
*
************************************************************************
*/

#include <stdio.h>

#define N 2                                   /* number of equations */
#define dist 0.1                              /* stepsize */
#define MIN 0.0                               /* minimum x */
#define MAX 10.0                              /* maximum x */

void runge4(double x, double y[], double step);
double f(double x, double y[], int i);

int main()
{

   double x, y[N];
   int j;

   FILE *output;                              /* save data in rk4.dat */
   output = fopen("rk4.dat","w");

   y[0] = 1.0;                                /* initial position  */
   y[1] = 0.0;                                /* initial velocity  */

   fprintf(output, "%f\t%f\n", x, y[0]);

   for(x = MIN; x <= MAX ; x += dist)
   {
      runge4(x, y, dist);
      fprintf(output, "%f\t%f\n", x, y[0]);   /* position vs. time */
   }
   printf("data stored in rk4.dat\n");
   fclose(output);
}
/*-----------------------end of main program--------------------------*/

/* Runge-Kutta subroutine */
void runge4(double x, double y[], double step)
{
   double h=step/2.0,                         /* the midpoint */
          t1[N], t2[N], t3[N],                /* temporary storage */
          k1[N], k2[N], k3[N],k4[N];          /* for Runge-Kutta  */
   int i;

   for (i=0; i<N; i++) t1[i] = y[i]+0.5*(k1[i]=step*f(x, y, i));
   for (i=0; i<N; i++) t2[i] = y[i]+0.5*(k2[i]=step*f(x+h, t1, i));
   for (i=0; i<N; i++) t3[i] = y[i]+    (k3[i]=step*f(x+h, t2, i));
   for (i=0; i<N; i++) k4[i] =                 step*f(x + step, t3, i);

   for (i=0; i<N; i++) y[i] += (k1[i]+2*k2[i]+2*k3[i]+k4[i])/6.0;
}
/*--------------------------------------------------------------------*/

/* definition of equations - this is the harmonic oscillator */
double  f(double x, double y[], int i)
{
   if (i == 0) return(y[1]);               /* RHS of first equation */
   if (i == 1) return(-y[0]);              /* RHS of second equation */
}

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

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

发布评论

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

评论(2

贱人配狗天长地久 2024-11-11 16:44:52

从胡克定律开始:

F = -kx

将其与牛顿第二定律结合起来,得到线性谐振子的微分方程:

ma = F = -kx
mx'' = -kx
x'' = -k/m x

任意选择我们的单位,使 k/m == 1,方程变为:

x'' = -x

现在,引入一个虚拟变量 y = x',并将这个二阶微分方程写为二维一阶系统:

x' = y
y' = -x

代码中的函数 f 正是这样编码的系统;为了清楚起见,我将更改变量名称:

double  f(double t, double v[], int i)
{
   if (i == 0) return(v[1]);
   if (i == 1) return(-v[0]);
}

v 是来自上面二维系统的向量[x,y]。给定 itv,函数 f 返回相对于 t< 的导数v 的第 i 组件的 /code>。使用这些名称重写二维系统,我们得到:

dv[0]/dt =  v[1]
dv[1]/dt = -v[0]

这正是函数 f 的作用。

Start from Hooke's law:

F = -kx

Combine this with Newton's second law to get the differential equation for a linear harmonic oscillator:

ma = F = -kx
mx'' = -kx
x'' = -k/m x

Arbitrarily chose our units so that k/m == 1, and the equation becomes just:

x'' = -x

Now, introduce a dummy variable y = x', and write this second-order differential equation as a two-dimensional first-order system:

x' = y
y' = -x

The function f in your code encodes exactly this system; I'm going to change the variable names for clarity:

double  f(double t, double v[], int i)
{
   if (i == 0) return(v[1]);
   if (i == 1) return(-v[0]);
}

v is the vector [x,y] from the two dimensional system above. Given i, t, and v, the function f returns the derivative with respect to t of the ith component of v. Re-writing the 2d system using these names, we get:

dv[0]/dt =  v[1]
dv[1]/dt = -v[0]

Which is exactly what the function f does.

屌丝范 2024-11-11 16:44:52

N 被定义为常量 2。这意味着这些循环将进行 2 次迭代,i = 0i = 1

f()如果i == 0,函数将返回传入多项式的第二个元素;如果i == 1,则返回该多项式第一个元素的负数。

我不知道获取谐振子的公式(老实说,这听起来像 Geordi LaForge 所说的需要重新校准之类的东西),但我认为就是这样。

N is defined as a constant 2. This means those loops are going to be doing 2 iterations, i = 0 and i = 1

The f() function will return the second element of the polynomial passed in if i == 0 and the negative of the first element of that polynomial if i == 1.

I don't know the formula for acquiring the harmonic oscillator (it sounds like something Geordi LaForge would say needs recalibrating or something, honestly) but I would assume that's it.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文