Skip to content

Commit b9a858d

Browse files
authored
Merge pull request #189 from stan-dev/case-study/planet
planetary motion case study.
2 parents bf2c0d5 + ed645a1 commit b9a858d

File tree

10 files changed

+1173
-0
lines changed

10 files changed

+1173
-0
lines changed

knitr/planetary_motion/README.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
2+
# Bayesian Model of Planetary Motion
3+
4+
5+
In this case study, we go through multiple attempts at fitting a model.
6+
Some of these attempts take a long time to run.
7+
To make the compilation of the bookdown faster, we generate and save Stan fit objects ahead of time under `saved_fit`.
8+
To recreate the fit objects, you can uncomment the appropriate code in `planetary_motion.rmd`.
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
2+
functions {
3+
real[] ode (real t,
4+
real[] y,
5+
real[] theta,
6+
real[] x_r, int[] x_i) {
7+
vector[2] q = to_vector({y[1], y[2]});
8+
real r_cube = pow(dot_self(q), 1.5);
9+
vector[2] p = to_vector({y[3], y[4]});
10+
real m = x_r[1];
11+
real k = theta[1];
12+
13+
vector[4] dydt;
14+
dydt[1:2] = p ./ m;
15+
dydt[3:4] = - k * q ./ r_cube;
16+
17+
return to_array_1d(dydt);
18+
}
19+
}
20+
21+
data {
22+
int n;
23+
real q_obs[n, 2];
24+
}
25+
26+
transformed data {
27+
real t0 = 0;
28+
int n_coord = 2;
29+
real q0[n_coord] = {1.0, 0.0};
30+
real p0[n_coord] = {0.0, 1.0};
31+
real y0[n_coord * 2] = append_array(q0, p0);
32+
33+
real m = 1.0;
34+
35+
real t[n];
36+
for (i in 1:n) t[i] = i * 1.0 / 10;
37+
38+
int x_i[0];
39+
40+
real<lower = 0> sigma_x = 0.01;
41+
real<lower = 0> sigma_y = 0.01;
42+
43+
// ODE tuning parameters
44+
real rel_tol = 1e-6; // 1e-12;
45+
real abs_tol = 1e-6; // 1e-12;
46+
int max_steps = 1000; // 1e6
47+
48+
}
49+
50+
parameters {
51+
real<lower = 0> k;
52+
}
53+
54+
transformed parameters {
55+
real y[n, n_coord * 2]
56+
= integrate_ode_bdf(ode, y0, t0, t, {k}, {m}, x_i,
57+
rel_tol, abs_tol, max_steps);
58+
}
59+
60+
model {
61+
k ~ normal(0, 1);
62+
63+
q_obs[, 1] ~ normal(y[, 1], sigma_x);
64+
q_obs[, 2] ~ normal(y[, 2], sigma_y);
65+
}
66+
67+
generated quantities {
68+
real qx_pred[n];
69+
real qy_pred[n];
70+
71+
qx_pred = normal_rng(y[, 1], sigma_x);
72+
qy_pred = normal_rng(y[, 2], sigma_y);
73+
}
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
2+
// It's assumed that the planet orbits a star at position (0, 0),
3+
// and that the mass of the planet is negligable next to that of
4+
// the star (meaning the star doesn't move).
5+
6+
functions {
7+
real[] ode (real t,
8+
real[] y,
9+
real[] theta,
10+
real[] x_r, int[] x_i) {
11+
vector[2] q = to_vector({y[1], y[2]});
12+
real r_cube = pow(dot_self(q), 1.5);
13+
vector[2] p = to_vector({y[3], y[4]});
14+
real m = x_r[1];
15+
real k = x_r[2];
16+
17+
vector[4] dydt;
18+
dydt[1:2] = p ./ m;
19+
dydt[3:4] = - k * q ./ r_cube;
20+
21+
return to_array_1d(dydt);
22+
}
23+
}
24+
25+
data {
26+
int n;
27+
real<lower = 0> sigma_x;
28+
real<lower = 0> sigma_y;
29+
}
30+
31+
transformed data {
32+
// intial state at t = 0
33+
real t0 = 0;
34+
int n_coord = 2;
35+
real q0[n_coord] = {1.0, 0.0};
36+
real p0[n_coord] = {0.0, 1.0};
37+
real y0[n_coord * 2] = append_array(q0, p0);
38+
39+
// model parameters
40+
real m = 1.0;
41+
real k = 1.0;
42+
43+
// exact motion
44+
real t[n];
45+
for (i in 1:n) t[i] = (i * 1.0) / 10;
46+
real x_r[2] = {m, k};
47+
48+
real theta[0];
49+
int x_i[0];
50+
51+
real y[n, n_coord * 2]
52+
= integrate_ode_rk45(ode, y0, t0, t, theta, x_r, x_i);
53+
}
54+
55+
parameters {
56+
real phi;
57+
}
58+
59+
model {
60+
phi ~ normal(0, 1);
61+
}
62+
63+
generated quantities {
64+
real q_obs[n, 2];
65+
66+
q_obs[, 1] = normal_rng(y[, 1], sigma_x);
67+
q_obs[, 2] = normal_rng(y[, 2], sigma_y);
68+
}
Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
2+
// fixes a calculation error in planetary_motion_star.stan.
3+
4+
functions {
5+
real[] ode (real t,
6+
real[] y,
7+
real[] theta,
8+
real[] x_r, int[] x_i) {
9+
vector[2] q = to_vector({y[1], y[2]});
10+
vector[2] s = to_vector({theta[2], theta[3]});
11+
12+
real r_cube = pow(dot_self(q - s), 1.5);
13+
vector[2] p = to_vector({y[3], y[4]});
14+
real m = x_r[1];
15+
real k = theta[1];
16+
17+
vector[4] dydt;
18+
dydt[1:2] = p ./ m;
19+
dydt[3:4] = - k * (q - s) ./ r_cube;
20+
21+
return to_array_1d(dydt);
22+
}
23+
}
24+
25+
data {
26+
int n;
27+
real q_obs[n, 2];
28+
real time[n];
29+
30+
real<lower = 0> sigma;
31+
}
32+
33+
transformed data {
34+
real t0 = 0;
35+
int n_coord = 2;
36+
real m = 1.0;
37+
int x_i[0];
38+
39+
real<lower = 0> sigma_x = sigma;
40+
real<lower = 0> sigma_y = sigma;
41+
42+
// ODE tuning parameters
43+
real rel_tol = 1e-6;
44+
real abs_tol = 1e-6;
45+
int max_steps = 1000;
46+
47+
}
48+
49+
parameters {
50+
real<lower = 0> k;
51+
real q0[n_coord];
52+
real p0[n_coord];
53+
real star[n_coord];
54+
}
55+
56+
transformed parameters {
57+
real y0[n_coord * 2] = append_array(q0, p0);
58+
real theta[n_coord + 1] = append_array({k}, star);
59+
60+
real y[n, n_coord * 2]
61+
= integrate_ode_rk45(ode, y0, t0, time, theta, {m}, x_i,
62+
rel_tol, abs_tol, max_steps);
63+
}
64+
65+
model {
66+
k ~ normal(1, 0.001); // prior derive based on solar system
67+
// (still pretty uninformative)
68+
69+
p0[1] ~ normal(0, 1);
70+
p0[2] ~ lognormal(0, 1); // impose p0 to be positive.
71+
q0 ~ normal(0, 1);
72+
star ~ normal(0, 0.5);
73+
74+
q_obs[, 1] ~ normal(y[, 1], sigma_x);
75+
q_obs[, 2] ~ normal(y[, 2], sigma_y);
76+
}
77+
78+
generated quantities {
79+
real qx_pred[n];
80+
real qy_pred[n];
81+
82+
qx_pred = normal_rng(y[, 1], sigma_x);
83+
qy_pred = normal_rng(y[, 2], sigma_y);
84+
}

0 commit comments

Comments
 (0)