/****************************/
/* 倒立振り子の微分方程式 */
/* coded by Y.Suganuma */
/****************************/
#include <stdio.h>
#include <math.h>
void link(double, double *, double *);
double rkg(double, double, double *, double *, double **, int,
void (*)(double,double *,double *));
double a[2][2], b, k1;
int main(void)
{
double end_t = 3.0, g = 9.8, h = 0.01, I, k, l, m, pi, r, time, ut, uti,
x[2], dx[2], **wk;
int i1;
// 領域の確保
wk = new double * [4];
for (i1 = 0; i1 < 4; i1++)
wk[i1] = new double [2];
// 微分方程式の係数の設定
pi = 4.0 * atan(1.0);
ut = pi / 180.0;
uti = 1.0 / ut;
m = 10.0;
l = 1.0;
r = 0.5 * l;
I = l * l / 12.0;
k = m;
k1 = 2.0 * m * r * g;
a[0][0] = 0.0;
a[0][1] = 1.0;
a[1][0] = m * r * g / (I + m * r * r);
a[1][1] = -k / (I + m * r * r);
b = -1.0 / (I + m * r * r);
// 初期設定
time = 0.0;
x[0] = 10.0;
x[1] = 0.0;
// ラジアン単位に変換
x[0] *= ut;
x[1] *= ut;
// 微分方程式を解く
printf("%f %f\n", time, x[0]*uti);
while (time < end_t) {
time = rkg(time, h, x, dx, wk, 2, link);
printf("%f %f\n", time, x[0]*uti);
}
// 領域の解法
for (i1 = 0; i1 < 4; i1++)
delete [] wk[i1];
delete [] wk;
return 0;
}
/****************************/
/* 倒立振り子の運動方程式 */
/* time : 時間 */
/* x : 位置と速度 */
/* dx : xの微分 */
/****************************/
void link(double time, double *x, double *dx)
{
dx[0] = a[0][0] * x[0] + a[0][1] * x[1];
dx[1] = a[1][0] * sin(x[0]) + a[1][1] * x[1] + b * k1 * x[0];
}
/*******************************************/
/* ルンゲ・クッタ法 dx/dt=f(t,x) */
/* time : 現在の時間 */
/* h : 時間刻み幅 */
/* x : 現在の状態 */
/* dx : 微係数(f(t,x):snxで計算する)*/
/* g : 作業域(g[4][n]) */
/* n : 微分方程式の次数 */
/* snx : 微係数を計算する関数の名前 */
/* return : time+h */
/*******************************************/
double rkg(double time, double h, double *x, double *dx, double **g,
int n, void (*sub)(double, double *, double *))
{
int i1;
double h2;
h2 = 0.5 * h;
(*sub)(time, x, dx);
for (i1 = 0; i1 < n; i1++)
g[0][i1] = h * dx[i1];
time += h2;
for (i1 = 0; i1 < n; i1++)
g[1][i1] = x[i1] + 0.5 * g[0][i1];
(*sub)(time, g[1], dx);
for (i1 = 0; i1 < n; i1++)
g[1][i1] = h * dx[i1];
for (i1 = 0; i1 < n; i1++)
g[2][i1] = x[i1] + 0.5 * g[1][i1];
(*sub)(time, g[2], dx);
for (i1 = 0; i1 < n; i1++)
g[2][i1] = h * dx[i1];
time += h2;
for (i1 = 0; i1 < n; i1++)
g[3][i1] = x[i1] + g[2][i1];
(*sub)(time, g[3], dx);
for (i1 = 0; i1 < n; i1++)
g[3][i1] = h * dx[i1];
for (i1 = 0; i1 < n; i1++)
x[i1] = x[i1] + (g[0][i1] + 2.0 * g[1][i1] + 2.0 * g[2][i1] + g[3][i1]) / 6.0;
return time;
}