void euler_cromer(const data* dat, output_function output)
{
  int i;
  double dt = dat->eta * delta_t_factor;
  vector *a    = (vector*) malloc((dat->N)*sizeof(vector)),
         *a_1 = (vector*) malloc((dat->N)*sizeof(vector)),
         *r    = init_r(dat),
         *v    = init_v(dat);

  double time = 0;
  output(time, dt, dat, r, v);

  while (time < dat->t_max)
  {
    accelerations(dat, r, a);
    adots(dat, r, v, a_1);
    for (i = 0; i < dat->N; i++)
    {
      vector v_neu = vector_add(v[i], scalar_mult(dt, a[i])),
             r_neu = vector_add(r[i], scalar_mult(0.5 * dt, vector_add(v[i], v_neu)));
      r[i] = r_neu;
      v[i] = v_neu;
    }
    dt = delta_t(dat, a, a_1);
    time += dt;
    output(time, dt, dat, r, v);
  }
  free(a); free(r); free(v);
}
void verlet(const data* dat, output_function output)
{
  int i;
  const double dt = dat->eta * delta_t_factor; // konstant

  vector *a    = (vector*) malloc((dat->N)*sizeof(vector)),
         *a_1 = (vector*) malloc((dat->N)*sizeof(vector)),
         *r_p  = (vector*) malloc((dat->N)*sizeof(vector)), // r_(n-1), not initialized
         *r    = init_r(dat),                               // r_(n)
         *r_n  = (vector*) malloc((dat->N)*sizeof(vector)), // r_(n+1), not initialized
         *v    = init_v(dat);                               // v_(n)

  double time = 0;
  output(time, dt, dat, r, v);

  // set initial data
  accelerations(dat, r, a); // a_0
  adots(dat, r, v, a_1);
  for (i = 0; i < dat->N; i++)
  {
    // set r_(-1)
    r_p[i] = vector_add(r[i],
             vector_add(scalar_mult(dt, v[i]),
                        scalar_mult(0.5 * dt * dt, a[i])));
    // set r_1
    r_n[i] = vector_add(scalar_mult(2, r[i]),
             vector_add(scalar_mult(-1, r_p[i]),
                        scalar_mult(dt * dt, a[i])));
  }
  //time += dt;

  // regular timesteps
  while (time < dat->t_max)
  {
    accelerations(dat, r_n, a); // a_n+1 (gets shifted to a_n)
    for (i = 0; i < dat->N; i++)
    {
      // shift indexes n+1 -> n
      r_p[i] = r[i];
      r[i]   = r_n[i];
      r_n[i] = vector_add(scalar_mult(2, r[i]),
               vector_add(scalar_mult(-1, r_p[i]),
                          scalar_mult(dt * dt, a[i])));
      v[i] = scalar_mult(0.5 / dt, vector_diff(r_n[i], r_p[i]));
    }
    adots(dat, r, v, a_1);
    time += dt;
    output(time, dt, dat, r, v);
  }
  free(a); free(r_p); free(r); free(r_n); free(v);
}
void leap_frog(const data* dat, output_function output)
{
  int i;
  double dt = dat->eta * delta_t_factor;

  vector *a    = (vector*) malloc((dat->N)*sizeof(vector)),
         *a_1 = (vector*) malloc((dat->N)*sizeof(vector)),
         *r_p  = (vector*) malloc((dat->N)*sizeof(vector)), // r_(n+1/2), not initialized
         *r    = init_r(dat),                               // r_(n+1)
         *r_n  = (vector*) malloc((dat->N)*sizeof(vector)), // r_(n+3/2), not initialized
         *v    = init_v(dat);                               // v_(n+1)

  double time = 0;
  output(time, dt, dat, r, v);

  // initial step
  for (i = 0; i < dat->N; i++)
    // set r_(1/2)
    r_n[i] = vector_add(r[i], scalar_mult(0.5 * dt, v[i]));

  // regular timesteps
  while (time < dat->t_max)
  {
    // a_(n+1/2)
    accelerations(dat, r_n, a);
    adots(dat, r_n, v, a_1);
    for (i = 0; i < dat->N; i++)
    {
      // store previous values as r_(n+1/2)
      r_p[i] = r_n[i];
      // v_(n+1)
      vector_add_to(&v[i], scalar_mult(dt, a[i]));
      // r_(n+3/2)
      vector_add_to(&r_n[i], scalar_mult(dt, v[i]));
      // build r_(n+1)
      r[i] = scalar_mult(0.5, vector_add(r_p[i], r_n[i]));
    }
    dt = delta_t(dat, a, a_1);
    time += dt;
    output(time, dt, dat, r, v);
  }
  free(a); free(r_p); free(r); free(r_n); free(v);
}
Exemple #4
0
int main(void)
{
    /* Local scalars */
    char job, job_i;
    char side, side_i;
    lapack_int n, n_i;
    lapack_int ilo, ilo_i;
    lapack_int ihi, ihi_i;
    lapack_int m, m_i;
    lapack_int ldv, ldv_i;
    lapack_int ldv_r;
    lapack_int info, info_i;
    lapack_int i;
    int failed;

    /* Local arrays */
    float *scale = NULL, *scale_i = NULL;
    lapack_complex_float *v = NULL, *v_i = NULL;
    lapack_complex_float *v_save = NULL;
    lapack_complex_float *v_r = NULL;

    /* Iniitialize the scalar parameters */
    init_scalars_cgebak( &job, &side, &n, &ilo, &ihi, &m, &ldv );
    ldv_r = m+2;
    job_i = job;
    side_i = side;
    n_i = n;
    ilo_i = ilo;
    ihi_i = ihi;
    m_i = m;
    ldv_i = ldv;

    /* Allocate memory for the LAPACK routine arrays */
    scale = (float *)LAPACKE_malloc( n * sizeof(float) );
    v = (lapack_complex_float *)
        LAPACKE_malloc( ldv*m * sizeof(lapack_complex_float) );

    /* Allocate memory for the C interface function arrays */
    scale_i = (float *)LAPACKE_malloc( n * sizeof(float) );
    v_i = (lapack_complex_float *)
        LAPACKE_malloc( ldv*m * sizeof(lapack_complex_float) );

    /* Allocate memory for the backup arrays */
    v_save = (lapack_complex_float *)
        LAPACKE_malloc( ldv*m * sizeof(lapack_complex_float) );

    /* Allocate memory for the row-major arrays */
    v_r = (lapack_complex_float *)
        LAPACKE_malloc( n*(m+2) * sizeof(lapack_complex_float) );

    /* Initialize input arrays */
    init_scale( n, scale );
    init_v( ldv*m, v );

    /* Backup the ouptut arrays */
    for( i = 0; i < ldv*m; i++ ) {
        v_save[i] = v[i];
    }

    /* Call the LAPACK routine */
    cgebak_( &job, &side, &n, &ilo, &ihi, scale, &m, v, &ldv, &info );

    /* Initialize input data, call the column-major middle-level
     * interface to LAPACK routine and check the results */
    for( i = 0; i < n; i++ ) {
        scale_i[i] = scale[i];
    }
    for( i = 0; i < ldv*m; i++ ) {
        v_i[i] = v_save[i];
    }
    info_i = LAPACKE_cgebak_work( LAPACK_COL_MAJOR, job_i, side_i, n_i, ilo_i,
                                  ihi_i, scale_i, m_i, v_i, ldv_i );

    failed = compare_cgebak( v, v_i, info, info_i, ldv, m );
    if( failed == 0 ) {
        printf( "PASSED: column-major middle-level interface to cgebak\n" );
    } else {
        printf( "FAILED: column-major middle-level interface to cgebak\n" );
    }

    /* Initialize input data, call the column-major high-level
     * interface to LAPACK routine and check the results */
    for( i = 0; i < n; i++ ) {
        scale_i[i] = scale[i];
    }
    for( i = 0; i < ldv*m; i++ ) {
        v_i[i] = v_save[i];
    }
    info_i = LAPACKE_cgebak( LAPACK_COL_MAJOR, job_i, side_i, n_i, ilo_i, ihi_i,
                             scale_i, m_i, v_i, ldv_i );

    failed = compare_cgebak( v, v_i, info, info_i, ldv, m );
    if( failed == 0 ) {
        printf( "PASSED: column-major high-level interface to cgebak\n" );
    } else {
        printf( "FAILED: column-major high-level interface to cgebak\n" );
    }

    /* Initialize input data, call the row-major middle-level
     * interface to LAPACK routine and check the results */
    for( i = 0; i < n; i++ ) {
        scale_i[i] = scale[i];
    }
    for( i = 0; i < ldv*m; i++ ) {
        v_i[i] = v_save[i];
    }

    LAPACKE_cge_trans( LAPACK_COL_MAJOR, n, m, v_i, ldv, v_r, m+2 );
    info_i = LAPACKE_cgebak_work( LAPACK_ROW_MAJOR, job_i, side_i, n_i, ilo_i,
                                  ihi_i, scale_i, m_i, v_r, ldv_r );

    LAPACKE_cge_trans( LAPACK_ROW_MAJOR, n, m, v_r, m+2, v_i, ldv );

    failed = compare_cgebak( v, v_i, info, info_i, ldv, m );
    if( failed == 0 ) {
        printf( "PASSED: row-major middle-level interface to cgebak\n" );
    } else {
        printf( "FAILED: row-major middle-level interface to cgebak\n" );
    }

    /* Initialize input data, call the row-major high-level
     * interface to LAPACK routine and check the results */
    for( i = 0; i < n; i++ ) {
        scale_i[i] = scale[i];
    }
    for( i = 0; i < ldv*m; i++ ) {
        v_i[i] = v_save[i];
    }

    /* Init row_major arrays */
    LAPACKE_cge_trans( LAPACK_COL_MAJOR, n, m, v_i, ldv, v_r, m+2 );
    info_i = LAPACKE_cgebak( LAPACK_ROW_MAJOR, job_i, side_i, n_i, ilo_i, ihi_i,
                             scale_i, m_i, v_r, ldv_r );

    LAPACKE_cge_trans( LAPACK_ROW_MAJOR, n, m, v_r, m+2, v_i, ldv );

    failed = compare_cgebak( v, v_i, info, info_i, ldv, m );
    if( failed == 0 ) {
        printf( "PASSED: row-major high-level interface to cgebak\n" );
    } else {
        printf( "FAILED: row-major high-level interface to cgebak\n" );
    }

    /* Release memory */
    if( scale != NULL ) {
        LAPACKE_free( scale );
    }
    if( scale_i != NULL ) {
        LAPACKE_free( scale_i );
    }
    if( v != NULL ) {
        LAPACKE_free( v );
    }
    if( v_i != NULL ) {
        LAPACKE_free( v_i );
    }
    if( v_r != NULL ) {
        LAPACKE_free( v_r );
    }
    if( v_save != NULL ) {
        LAPACKE_free( v_save );
    }

    return 0;
}
Exemple #5
0
int main (int argc, char ** argv)
{
	double h = 0,
	       L = 0,
	       a = 0,
	       t = 0.1;

	int N = 100,
	    p = 4,
	    tryrac = 1,
	    n = 0,
	    g = 3,
	    d = 0,
	    T = 100,
	    D = 8,
	    y = 0,
	    e = 0,
	    I = 0,
	    A = 0,
	    v = 0,
	    arg;

	char * dat = NULL;

	opterr = 1;

	while ((arg = getopt (argc, argv, "h:L:a:t:N:F:D:p:n:T:I:o:g:v:lAdey")) != -1)
	{
		switch (arg)
		{
			case 'h':
				h = atof (optarg);
				break;
			case 'L':
				L = atof (optarg);
				break;
			case 'a':
				a = atof (optarg);
				break;
			case 't':
				t = atof (optarg);
				break;
			case 'N':
				N = atoi (optarg);
				break;
			case 'F':
				tryrac = atoi (optarg);
				break;
			case 'p':
				p = atoi (optarg);
				break;
			case 'n':
				n = atoi (optarg);
				break;
			case 'T':
				T = atoi (optarg);
				break;
			case 'o':
				dat = (char *) malloc (15 * sizeof (char));
				strcpy (dat, optarg);
				break;
			case 'd':
				d = 1;
				break;
			case 'y':
				y = 1;
				break;
			case 'g':
				g = atoi (optarg);
				break;
			case 'e':
				e = 1;
				break;
			case 'I':
				I = atoi (optarg);
				break;
			case 'A':
				A = 1;
				break;
			case 'D':
				D = atoi (optarg);
				break;
			case 'v':
				v = atoi (optarg);
				break;
			case 'l':
				printf ("List of valid commands:\n\n");
				printf ("[-l] prints this list and exit\n");
				printf ("[-t] (0.1) time step\n");
				printf ("[-h] (0.01) space step\n");
				printf ("[-L] (0.0) lambda\n");
				printf ("[-a] (0.0) f(x - a)\n");
				printf ("[-N] (100) matrix rank\n");
				printf ("[-F] (1) precision test\n");
				printf ("[-T] (100) time iterations\n");
				printf ("[-p] (4) order of 2nd derivative prec.\n");
				printf ("[-g] (0.001) threshold for good eigenvalue\n");
				printf ("[-n] (0) phi_n (x)\n");
				printf ("[-A] (no) get the best possible h for given N\n");
				printf ("[-I] (no) for calibration -- h (N)\n");
				printf ("[-v] (0) get the good eigenvalues with increment\n");
				printf ("[-y] (no) save the output -- 'yes'\n");
				printf ("[-D] (8) duration of the animation in s\n");
				printf ("[-o] (format) output filename\n");
				printf ("[-e] (no) output the Energies\n");
				printf ("[-d] animation set to 'yes'\n");
				exit (EXIT_SUCCESS);
			default:
				abort ();
		}
	}

	if (v != 0)
	{
		if (dat == NULL)
		{
			dat = (char *) malloc (40*sizeof(char));
			sprintf (dat, "ratio-L%d.txt", (int) (100 * L));
		}

		vozi (L, a, t, g, N, p, d, tryrac, n, T, dat, v);
		printf ("Written in %s\n", dat);
		
		char * command = (char *) malloc (55 * sizeof (char));
		sprintf (command, "./plot2.sh %d %s %d", 1, dat, y);
		
		system (command);

		free (dat);
		free (command);

		exit (EXIT_SUCCESS);
	}

	// optimiziran h
	if (h == 0)
		h = 1.78850/(pow (N, 0.614827)) - N * 3.28275e-6;

	// we initialize the program
	hod * u = (hod *) malloc (sizeof (hod));
	init (u, h, L, a, t, g, N, p, d, tryrac, n, T, dat);

	if (I == 0)
	{
		// we now diagonalize the matrix
		if (A == 0)
			diag_MRRR (u);
		else if (A == 1)
			autoh (u);
	
		if (e == 0)
		{
			rotate (u);
			init_v (u);
	
			if (u->d == 1)
			{
				char * animation = (char *) malloc (40 * sizeof (char));
				sprintf (animation, "./anime.sh %s %d %d", u->dat, y, D);
				create_frames (u);
				system (animation);
			}
		
			else
			{
				char * savenplot = (char *) malloc (40 * sizeof (char));
				sprintf (savenplot, "./plot.sh %s %d", u->dat, y);
				one_big_txt (u);
				system (savenplot);
			}
		}
	
		else
		{
			eigen_output (u);
			count_harmonic (u);
			if (y == 1)
				eigen_dump (u);
		}
	}

	else if (I != 0)
	{
		test_suite (u, I);
		printf ("Written in file h-of-N.txt\n");
		char * command = (char *) malloc (40 * sizeof (char));
		sprintf (command, "./plot2.sh 0 0 %d", y);

		system (command);
		free (command);
	}
	destroy (u);

	return 0;
}
void runge_kutta(const data* dat, output_function output)
{
  int i;
  double dt = dat->eta * delta_t_factor;

  vector *r   = init_r(dat),
         *v   = init_v(dat),
         *a   = (vector*) malloc((dat->N)*sizeof(vector)),
         *a_1 = (vector*) malloc((dat->N)*sizeof(vector));

  // temporary r vector for acceleration calculations
  vector *rt = (vector*) malloc((dat->N)*sizeof(vector));

  vector *a1 = (vector*) malloc((dat->N)*sizeof(vector)),
         *a2 = (vector*) malloc((dat->N)*sizeof(vector)),
         *a3 = (vector*) malloc((dat->N)*sizeof(vector)),
         *a4 = (vector*) malloc((dat->N)*sizeof(vector));

  vector *r1 = (vector*) malloc((dat->N)*sizeof(vector)),
         *r2 = (vector*) malloc((dat->N)*sizeof(vector)),
         *r3 = (vector*) malloc((dat->N)*sizeof(vector)),
         *r4 = (vector*) malloc((dat->N)*sizeof(vector));

  vector *v1 = (vector*) malloc((dat->N)*sizeof(vector)),
         *v2 = (vector*) malloc((dat->N)*sizeof(vector)),
         *v3 = (vector*) malloc((dat->N)*sizeof(vector)),
         *v4 = (vector*) malloc((dat->N)*sizeof(vector));

  double time = 0;
  while (time < dat->t_max)
  {
    accelerations(dat, r, a1);
    for (i = 0; i < dat->N; i++)
    {
      v1[i] = scalar_mult(dt, a1[i]);
      r1[i] = scalar_mult(dt, v[i]);
      // temp r for a2
      rt[i] = vector_add(r[i], scalar_mult(0.5, r1[i]));
    }
    accelerations(dat, rt, a2);
    for (i = 0; i < dat->N; i++)
    {
      v2[i] = scalar_mult(dt, a2[i]);
      r2[i] = scalar_mult(dt, vector_add(v[i], scalar_mult(0.5, v1[i])));
      // temp r for a3
      rt[i] = vector_add(r[i], scalar_mult(0.5, r2[i]));
    }
    accelerations(dat, rt, a3);
    for (i = 0; i < dat->N; i++)
    {
      v3[i] = scalar_mult(dt, a3[i]);
      r3[i] = scalar_mult(dt, vector_add(v[i], scalar_mult(0.5, v2[i])));
      // temp r for a3
      rt[i] = vector_add(r[i], scalar_mult(0.5, r3[i]));
    }
    accelerations(dat, rt, a4);
    for (i = 0; i < dat->N; i++)
    {
      v4[i] = scalar_mult(dt, a4[i]);
      r4[i] = scalar_mult(dt, vector_add(v[i], v3[i]));
      // calculate v_(n+1) and r_(n+1)
      vector_add_to(&v[i], vector_add(scalar_mult(1.0/6.0, v1[i]),
                           vector_add(scalar_mult(1.0/3.0, v2[i]),
                           vector_add(scalar_mult(1.0/3.0, v3[i]),
                                      scalar_mult(1.0/6.0, v4[i])))));
      vector_add_to(&r[i], vector_add(scalar_mult(1.0/6.0, r1[i]),
                           vector_add(scalar_mult(1.0/3.0, r2[i]),
                           vector_add(scalar_mult(1.0/3.0, r3[i]),
                                      scalar_mult(1.0/6.0, r4[i])))));
    }
    // increase time
    adots(dat, r, v, a_1);
    dt = delta_t(dat, a1, a_1); // a1 = a(t_n), a_1 = a'(t_n)
    time += dt;
    output(time, dt, dat, r, v);
  }
  free(r);  free(v);  free(a);  free(a_1);
  free(rt);
  free(r1); free(r2); free(r3); free(r4);
  free(v1); free(v2); free(v3); free(v4);
  free(a1); free(a2); free(a3); free(a4);
}
void hermite_iterated(const data* dat, output_function output, int iterations)
{
  int i,j;
  double dt = dat->eta * delta_t_factor;

  vector *a      = (vector*) malloc((dat->N)*sizeof(vector)), // a_n,          not initialized
         *a_p    = (vector*) malloc((dat->N)*sizeof(vector)), // a_(n+1)^p,    not initialized
         *a_1   = (vector*) malloc((dat->N)*sizeof(vector)), // a_1_n,       not initialized
         *a_1_p = (vector*) malloc((dat->N)*sizeof(vector)), // a_1_(n+1)^p, not initialized
         *r      = init_r(dat),                               // r_n
         *r_p    = (vector*) malloc((dat->N)*sizeof(vector)), // r_(n+1)^p,    not initialized
         *v      = init_v(dat),                               // v_n
         *v_p    = (vector*) malloc((dat->N)*sizeof(vector)); // v_(n+1)^p,    not initialized

  double time = 0;

  accelerations(dat, r, a);
  adots(dat, r, v, a_1);
  dt = delta_t(dat, a, a_1);

  output(time, dt, dat, r, v);

  while (time < dat->t_max)
  {
    // prediction step
    for (i = 0; i < dat->N; i++)
    {
      v_p[i] = vector_add(v[i],
               vector_add(scalar_mult(dt, a[i]),
                          scalar_mult(0.5 * dt * dt, a_1[i])));
      r_p[i] = vector_add(r[i],
               vector_add(scalar_mult(dt, v[i]),
               vector_add(scalar_mult(0.5 * dt * dt, a[i]),
                          scalar_mult(dt * dt * dt / 6.0, a_1[i]))));
    }
    // iteration of correction step
    for (j = 0; j < iterations; j++)
    {
      // predict a, a_1
      accelerations(dat, r_p, a_p);
      adots(dat, r_p, v_p, a_1_p);
      for (i = 0; i < dat->N; i++)
      {
        // correction steps -> overwrite "prediction" variables for convenience,
        // will get written in r,v after iteration is done
        v_p[i] = vector_add(v[i],
               vector_add(scalar_mult(dt / 2.0, vector_add(a_p[i], a[i])),
                          scalar_mult(dt * dt / 12.0, vector_diff(a_1_p[i], a_1[i]))));
        r_p[i] = vector_add(r[i],
                 vector_add(scalar_mult(dt / 2.0, vector_add(v_p[i], v[i])),
                            scalar_mult(dt * dt / 12.0, vector_diff(a_p[i], a[i]))));
      }
    }
    // apply iterated correction steps
    for (i = 0; i < dat->N; i++)
    {
      r[i] = r_p[i];
      v[i] = v_p[i];
    }
    time += dt;
    // a/a_1 values for next step
    accelerations(dat, r, a);
    adots(dat, r, v, a_1);
    // new dt
    dt = delta_t(dat, a, a_1);
    output(time, dt, dat, r, v);
  }

  free(a);   free(a_p);
  free(a_1); free(a_1_p);
  free(r);   free(r_p);
  free(v);   free(v_p);
}
void hermite(const data* dat, output_function output)
{
  int i;
  double dt = dat->eta * delta_t_factor;

  vector *a      = (vector*) malloc((dat->N)*sizeof(vector)), // a_n,          not initialized
         *a_p    = (vector*) malloc((dat->N)*sizeof(vector)), // a_(n+1)^p,    not initialized
         *a_1   = (vector*) malloc((dat->N)*sizeof(vector)), // a_1_n,       not initialized
         *a_1_p = (vector*) malloc((dat->N)*sizeof(vector)), // a_1_(n+1)^p, not initialized
         *a_2    = (vector*) malloc((dat->N)*sizeof(vector)), // a_(n+1)^(2),  not initialized
         *a_3    = (vector*) malloc((dat->N)*sizeof(vector)), // a_(n+1)^(3),  not initialized
         *r      = init_r(dat),                               // r_n
         *r_p    = (vector*) malloc((dat->N)*sizeof(vector)), // r_(n+1)^p,    not initialized
         *v      = init_v(dat),                               // v_n
         *v_p    = (vector*) malloc((dat->N)*sizeof(vector)); // v_(n+1)^p,    not initialized

  double time = 0;

  accelerations(dat, r, a);
  adots(dat, r, v, a_1);
  dt = delta_t(dat, a, a_1);

  output(time, dt, dat, r, v);

  while (time < dat->t_max)
  {
    // prediction step
    for (i = 0; i < dat->N; i++)
    {
      v_p[i] = vector_add(v[i],
               vector_add(scalar_mult(dt, a[i]),
                          scalar_mult(0.5 * dt * dt, a_1[i])));
      r_p[i] = vector_add(r[i],
               vector_add(scalar_mult(dt, v[i]),
               vector_add(scalar_mult(0.5 * dt * dt, a[i]),
                          scalar_mult(dt * dt * dt / 6.0, a_1[i]))));
    }
    // predict a^p, a_1^p
    accelerations(dat, r_p, a_p);
    adots(dat, r_p, v_p, a_1_p);
    for (i = 0; i < dat->N; i++)
    {
      // predict 2nd and 3rd derivations
      a_2[i] = vector_add(scalar_mult(2 * (-3) / dt / dt, vector_diff(a[i], a_p[i])),
                          scalar_mult(2 * (-1) / dt, vector_add(scalar_mult(2, a_1[i]), a_1_p[i])));
      a_3[i] = vector_add(scalar_mult(6 * 2 / dt / dt / dt, vector_diff(a[i], a_p[i])),
                          scalar_mult(6 / dt / dt, vector_add(a_1[i], a_1_p[i])));
      // correction steps
      v[i] = vector_add(v_p[i],
             vector_add(scalar_mult(dt * dt * dt / 6.0, a_2[i]),
                        scalar_mult(dt * dt * dt / 24.0, a_3[i])));
      r[i] = vector_add(r_p[i],
             vector_add(scalar_mult(dt * dt * dt * dt / 24.0, a_2[i]),
                        scalar_mult(dt * dt * dt * dt * dt / 120.0, a_3[i])));
    }
    time += dt;
    // a/a_1 values for next step
    accelerations(dat, r, a);
    adots(dat, r, v, a_1);
    // new dt
    dt = delta_t_(dat, a, a_1, a_2, a_3);
    output(time, dt, dat, r, v);
  }

  free(a);    free(a_p);
  free(a_1); free(a_1_p);
  free(r);    free(r_p);
  free(v);    free(v_p);
}