{"bump-width", required_argument, 0, 'b' },
{"euler", no_argument, 0, 'e' },
{"midpoint", no_argument, 0, 'M' },
+ {"rk4", no_argument, 0, 'r' },
{}
};
-static char *short_options = "t:d:x:y:X:E:Y:m:k:b:eM";
+static char *short_options = "t:d:x:y:X:E:Y:m:k:b:eMr";
/* dynamic system parameters */
typedef struct state_struct {
free(dx_dt);
}
+void rk4_step(state_t *state, system_t *system, double dt)
+{
+ double *x = NULL, *dx_dt = NULL;
+ double *k1 = NULL, *k2 = NULL, *k3 = NULL, *k4 = NULL;
+ size_t i, x_size = sizeof(double) * state->n;
+
+ /* allocate memory */
+ x = malloc(x_size);
+ assert(x); /* check for successful malloc() */
+ dx_dt = malloc(x_size);
+ assert(dx_dt); /* check for successful malloc() */
+ k1 = malloc(x_size);
+ assert(k1); /* check for successful malloc() */
+ k2 = malloc(x_size);
+ assert(k2); /* check for successful malloc() */
+ k3 = malloc(x_size);
+ assert(k3); /* check for successful malloc() */
+ k4 = malloc(x_size);
+ assert(k4); /* check for successful malloc() */
+
+ memcpy((void *)x, (void *)state->x, x_size);
+ /* k1 */
+ (*system->dx_dt_fn)(state, (void *)system, dx_dt);
+ for (i = 0; i < state->n; i++) {
+ k1[i] = dx_dt[i] * dt;
+ state->x[i] = x[i] + 0.5*k1[i];
+ }
+ state->t += dt/2;
+ /* k2 */
+ (*system->dx_dt_fn)(state, (void *)system, dx_dt);
+ for (i = 0; i < state->n; i++) {
+ k2[i] = dx_dt[i] * dt;
+ state->x[i] = x[i] + 0.5*k2[i];
+ }
+ /* k3 */
+ (*system->dx_dt_fn)(state, (void *)system, dx_dt);
+ for (i = 0; i < state->n; i++) {
+ k3[i] = dx_dt[i] * dt;
+ state->x[i] = x[i] + k3[i];
+ }
+ state->t += dt/2;
+ /* k4 */
+ (*system->dx_dt_fn)(state, (void *)system, dx_dt);
+ for (i = 0; i < state->n; i++) {
+ k4[i] = dx_dt[i] * dt;
+ state->x[i] = x[i] + (k1[i] + 2*k2[i] + 2*k3[i] + k4[i])/6.0;
+ }
+
+ /* release memory */
+ free(x);
+ free(dx_dt);
+ free(k1);
+ free(k2);
+ free(k3);
+ free(k4);
+}
+
/* prints "t\tx[0]\tx[1]\t...\tx[n-1]\n"
* If system->energy_fn is defined, also print "\tenergy" before the
* newline.
case 'M':
*step_fn = &midpoint_step;
break;
+ case 'r':
+ *step_fn = &rk4_step;
+ break;
case '?':
exit(EXIT_FAILURE);
default: