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); }
static void update_shape(jigglystruct *js) { vertex *vtx = js->shape->vertices; edge *e = js->shape->edges; vector zero; vector_init(zero, 0, 0, 0); /* sum all the vertex-vertex forces */ while(e) { vector f; coord mag; vector_sub(e->left->vtx->v, e->right->vtx->v, f); mag = js->stable_distance - magnitude(f); vector_scale(f, mag); vector_add_to(e->left->vtx->f, f); vector_sub(zero, f, f); vector_add_to(e->right->vtx->f, f); e = e->next; } /* scale back the v-v force and add the spherical force * then add the result to the vertex velocity, damping * if necessary. Finally, move the vertex */ while(vtx) { coord mag; vector to_sphere; vector_scale(vtx->f, js->hold_strength); vector_copy(to_sphere, vtx->v); mag = 1 - magnitude(to_sphere); vector_scale(to_sphere, mag * js->spherify_strength); vector_add_to(vtx->f, to_sphere); vector_add_to(vtx->vel, vtx->f); vector_init(vtx->f, 0, 0, 0); mag = magnitude2(vtx->vel); if(mag > js->damping_velocity) vector_scale(vtx->vel, js->damping_factor); vector_add_to(vtx->v, vtx->vel); vtx = vtx->next; } }
static inline void vertex_calcnormal(vertex *vtx, jigglystruct *js) { hedge *start = vtx->h, *h=start; vector_init(vtx->n, 0, 0, 0); do { vector u, v, norm; vector_sub(h->prev->vtx->v, vtx->v, u); vector_sub(h->next->vtx->v, vtx->v, v); cross(u, v, norm); vector_add_to(vtx->n, norm); h = partner(h)->next; } while(h != start); if(!js->spooky) normalize(vtx->n); else vector_scale(vtx->n, js->spooky); }
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); }