duffing_lyap.c
/*------------------------------------------------------------------------------------
ダフィング方程式のリアプノフスペクトラムの計算
calculating the Lyapunov spectrum of the Duffing equations
dx/dt = y
dy/dt = -x^3 - K * y + B * sin(z)
dz/dt = 1.0
duffing_lyap.c
------------------------------------------------------------------------------------*/
#include "duffing_lyap.h"
int main(void)
{
int i;
int j;
int t;
double total_T;
double d2;
double lyap_dim;
double sum_lyap;
double v[DIM]; /* 変数 variables */
double lyap[DIM]; /* リアプノフ指数 Lyapunov exponent */
double u[DIM][DIM];
double e[DIM][DIM];
/*------------------------------------------------------------------*/
// 初期値の設定
// set the initial values
// v[0]: x v[1]: y v[2]: z
v[0] = X0;
v[1] = Y0;
v[2] = Z0;
/*------------------------------------------------------------------*/
// 直交化した長さ1のベクトル(単位行列)uの作成
// create orthogonalized vectors u with length 1 (unit matrix)
for ( i = 0; i < DIM; i++ ) {
for ( j = 0; j < DIM; j++ ) {
u[i][j] = ( i == j ? 1.0 : 0.0 );
// printf("%lf ", u[i][j]);
}
// printf("\n");
lyap[i] = 0.0;
}
/*------------------------------------------------------------------*/
for( t = 0; t < SKIPS; t++ ){
// ダフィング方程式の値とヤコビ行列の計算
// calculate the Duffing equations and the Jacobian matrix
solve_duffing_eqs_using_RK4( v, u );
// output the data, v[0]: x, v[1]: y, v[2]: z
// printf("%.10lf %.10lf %.10lf\n", v[0], v[1], v[2] );
}
/*------------------------------------------------------------------*/
// uの再設定
// reset vector u
for ( i = 0; i < DIM; i++ ) {
for ( j = 0; j < DIM; j++ ) {
u[i][j] = ( i == j ? 1.0 : 0.0 );
}
}
/*------------------------------------------------------------------*/
for( t = 0; t < ITERATION; t++ ){
// ダフィング方程式の値とヤコビ行列の計算
// calculate the Duffing equations and the Jacobian matrix
solve_duffing_eqs_using_RK4( v, u );
// output the data, v[0]: x, v[1]: y, v[2]: z
// printf("%.10lf %.10lf %.10lf\n", v[0], v[1], v[2] );
// グラム・シュミットの正規直交化法
// Gram-Schmidt orthogonalisation
gram_schmidt_orth( u, e );
for ( j = 0; j < DIM; j++ ) {
d2 = 0.0;
for ( i = 0; i < DIM; i++ ) {
d2 += e[i][j] * e[i][j];
}
lyap[j] += log( sqrt( d2 ) );
// lyap[j] += log2( sqrt( d2 ) );
// printf( "%.10lf ", lyap[j]/(double)(t+1) );
}
// printf("\n");
}
/*------------------------------------------------------------------*/
// リアプノフ指数の計算
// calculate the Lyapunov exponents
sum_lyap = 0.0;
total_T = ITERATION * DELTA_T;
for ( i = 0; i < DIM; i++ ) {
lyap[i] = lyap[i]/(double)total_T;
sum_lyap += lyap[i];
}
// リアプノフ指数を大きい順に並べ替える
// sort Lyapunov exponents in ascending order
quick_sort( (int)DIM, lyap );
// リアプノフ次元の計算
// calculate the Lyapunov dimension
lyap_dim = calc_lyap_dim( lyap );
/*------------------------------------------------------------------*/
printf("#---------------------------------------------------\n" );
printf("# ITERATION: %d\n", (int)ITERATION);
printf("# SKIPS: %d\n", (int)SKIPS);
printf("# DELTA_T: %g\n", (double)DELTA_T);
printf("# TOTAL_TIME: %g\n", total_T);
printf("#---------------------------------------------------\n" );
printf("# initial condition\n");
printf("# x0: %#g\n", (double)X0);
printf("# y0: %#g\n", (double)Y0);
printf("# z0: %#g\n", (double)Z0);
printf("#---------------------------------------------------\n" );
printf("# B = %g, K = %g\n", (double)B, (double)K );
printf("#---------------------------------------------------\n" );
printf("# Lyapunov Spectrum (log with base-e)\n" );
// printf("# Lyapunov Spectrum (log with base-2)\n" );
printf("# lyap[1]: %lf\n", lyap[0] );
printf("# lyap[2]: %lf\n", lyap[1] );
printf("# lyap[3]: %lf\n", lyap[2] );
printf("# Lyapunov Dimension: %lf\n", lyap_dim );
printf("#---------------------------------------------------\n" );
printf("# lyap[1]+lyap[2]+lyap[3]: %lf\n", sum_lyap);
printf("# diagonal elements of the jacobian: %lf\n", -K );
printf("#---------------------------------------------------\n" );
return 0;
}
/*----------------------------------------------------------------------------*/
double log2( double x )
{
return log(x)/(double)log(2.0);
}
/*----------------------------------------------------------------------------*/
// リアプノフ次元の計算
// calculate Lyapunov dimension
double calc_lyap_dim( double lyap[DIM] )
{
int i;
double sum;
double lyap_dim = (double)DIM;
sum = 0.0;
for ( i = 0; i < (int)DIM; i++ ) {
sum += lyap[i];
if ( sum < 0.0 ) {
lyap_dim = i + (sum - lyap[i])/(double)fabs( lyap[i] );
break;
}
}
return lyap_dim;
}
/*----------------------------------------------------------------------------*/
void quick_sort( int n, double x[DIM] )
{
int i, j;
double pivot, t;
if (n < 2) {
return; /* no need for sorting */
}
pivot = x[0];
i = 0;
j = n-1; /* lower and upper bounds */
while (i <= j) {
while (x[i] > pivot){
i++; /* search for x[i] >= pivot */
}
while (x[j] < pivot){
j--; /* search for x[j] <= pivot */
}
if (i <= j) { /* swap x[i] and x[j] */
t = x[i];
x[i] = x[j];
x[j] = t;
i++;
j--;
}
}
quick_sort(j+1, x); /* recursive call for smaller half */
quick_sort(n-i, x+i); /* recursive call for larger half */
}