/* fallingclimber : calculates how a climber falling from a space elevator will hit the earth. Copyright (C) 2003 Blaise Gassend This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include #include #define STEP (1) #define MAXITERS (1000000) #define RK2 #define EARTH_PULSATION (2 * M_PI / 86164.1) #define EARTH_R (40e6 / (2 * M_PI)) #define EARTH_GM (9.81 * EARTH_R * EARTH_R) typedef struct { double t; double x; double y; double xd; double yd; } state; int dispflag = 0; void getder(state *s, state *ds); void update(state *dst, state *src, state *ds, double step); double deg(double r) { return r * 180 / M_PI; } void simul(double r0) { int i; state s, ts, ds; s.x = 0; s.y = r0; s.xd = r0 * EARTH_PULSATION; s.yd = 0; s.t = 0; for (i = 0; i < MAXITERS; i++) { double step = STEP; double r; double theta; double longitude; double vtheta; double v; double vx; double vy; #ifdef EULER getder(&s, &ds); update(&s, &s, &ds, step); #else // EULER #ifdef RK2 getder(&s, &ds); update(&ts, &s, &ds, step / 2); getder(&ts, &ds); update(&s, &s, &ds, step); #else // RK2 #ifdef RK4 #error RK4 not defined yet #else // RK4 #error No integration algorithm specified #endif // RK4 #endif // RK2 #endif // EULER r = sqrt(s.x * s.x + s.y * s.y); theta = atan2(-s.x, -s.y) + M_PI; longitude = theta - s.t * EARTH_PULSATION; vx = s.xd - EARTH_PULSATION * s.y; vy = s.yd + EARTH_PULSATION * s.x; v = sqrt(vx * vx + vy * vy); vtheta = atan2(-vx, -vy) + M_PI / 2; if (dispflag == 1) { printf("%f %f %f %f\n", s.t, r, theta, longitude); fflush(stdout); } if (r < EARTH_R) { if (dispflag == 2) { printf("%f %f %f %f %f %f\n", r0 - EARTH_R, s.t, deg(theta), deg(longitude), v, deg(vtheta - theta)); fflush(stdout); } printf("#too low %f < %f\n", r, EARTH_R); return; } if (theta > M_PI) { printf("#timed out\n\n"); return; } } } void getder(state *s, state *ds) { double r3 = pow(s->x * s->x + s->y * s->y, 1.5); ds->x = s->xd; ds->y = s->yd; ds->xd = -EARTH_GM / r3 * s->x; ds->yd = -EARTH_GM / r3 * s->y; ds->t = 1; } void update(state *dst, state *src, state *ds, double step) { dst->x = src->x + ds->x * step; dst->y = src->y + ds->y * step; dst->xd = src->xd + ds->xd * step; dst->yd = src->yd + ds->yd * step; dst->t = src->t + ds->t * step; } int main() { double r0; dispflag = 2; for (r0 = EARTH_R; r0 < 30e6; r0+=r0 < 2.9e7 ? 1e5 : 1e3) simul(r0); return 0; }