Attachment 'main.cpp'

Download

   1 // Calculation of the movement of the launch loop during launch
   2 // By Kristian Andresen
   3 // To do:
   4 // - Conservation of energy
   5 // - Planetary rotation
   6 // - Pressure as function of height
   7 // - Wind loading
   8 // - Spaceship launch
   9 
  10 #include <iostream>
  11 #include <fstream>
  12 #include <stdlib.h>
  13 #include <math.h>
  14 #include <sstream> 
  15 #include <vector>
  16 using namespace std;
  17 
  18 // Utilities
  19 namespace transient {
  20 #define swap(T,a,b) { T buff = b; b = a; a = buff; }
  21 double temp[3]; // Temporary holder of vectors
  22 #define plusMinus(i) for(int i = -1; i <= 1; i = i+2)
  23 #define for2(i) for(int i = 0; i < 2; i++)
  24 #define for3(i) for(int i = 0; i < 3; i++)
  25 #define forN(N,i) for(int i = 0; i < N; i++)
  26 inline double sqr(double x) { return x*x; }
  27 inline double dot(double a[], double b[]) { return a[0]*b[0] + a[1]*b[1] + a[2]*b[2]; }
  28 inline double sqr(double a[]) { return dot(a, a); }
  29 inline double* sub(double res[], double a[], double b[]) { for3(i) res[i] = a[i] - b[i]; return res; }
  30 inline double* sub(double a[], double b[]) { for3(i) temp[i] = a[i] - b[i]; return temp; }
  31 inline void normalize(double a[]) { double length = sqrt(sqr(a)); for3(i) a[i] /= length; } 
  32 inline double dist(double a[], double b[]) { return sqrt(sqr(sub(a, b))); }
  33 inline int wrap(int i) { return i >= 3? i-3 : i; }
  34 inline double abs(double a) { return a < 0? -a : a; } 
  35 inline double* cross(double c[], double a[], double b[]) { for3(i) c[i] = a[wrap(1+i)]*b[wrap(2+i)] - a[wrap(2+i)]*b[wrap(1+i)]; return c; }
  36 int getColor(int r, int g, int b) { return r * 65536 + g * 256 + b; }
  37 const int rotorColor[4] = {getColor(255,0,0), getColor(0,255,0), getColor(255,255,0), getColor(0,255,255)};
  38 }
  39 
  40 // Constants and globals
  41 namespace transient {
  42 // Physical constants
  43 const double earthRadius = 6378100; // [m]
  44 const double earthMassTimesG = 3.98734836e14; // [N*m^2/kg]
  45 const double earthMass = 5.9736e24; // [kg]
  46 const double pi = 3.1415926;
  47 
  48 // Track design parameters
  49 const double distance = 100e3; // [m] Distance between ground stations
  50 const double rotorDensity = 1; // [kg/m] Rotor density at apex
  51 const double apex[3] = {0.0, 0.0, earthRadius + 40e3}; // [x,y,z] 
  52 const double setupApexSpeed = 2000; // [m/s] Speed of rotor at apex during initialization
  53 const double simulationApexSpeed = 2000; // [m/s] Speed of rotor at apex during simulation
  54 const double soundInTrack = 4000; // [m/s] Speed of sound in track
  55 const double specificStrength = 1e5; // [N/(kg/m)] Maximum tensile force in track depends on density
  56 const double trackArea = 0.001; // [m^2] This influences track resistance to bending
  57 const double shearModulus = 60e9; // [Pa] Shear modulus of steel
  58 const double youngModulus = 200e9; // [Pa] Youngs modulus of steel
  59 const int tracks = 4; // Number of tracks
  60 const bool eastbound[4] = {true, false, true, false}; // Direction of each track
  61 const bool helicalTrack = true; // If true, track is initialized as a spiral
  62 const int guyWires = 5; // Number of guy wires attached to each track segment, uneven number for balance
  63 const bool guyWire = (tracks > 1) && helicalTrack; // If true, employ guy wires
  64 const double helixRadius = 1000; // [m]
  65 const double helixes = 7; // Number of twists along the track, need not be integer
  66 const double centrifugalPeriod = distance * 2 / simulationApexSpeed / helixes; // [s]
  67 const double centrifugalAcceleration = 4 * sqr(pi) * helixRadius / sqr(centrifugalPeriod); // [m/s^2]
  68 
  69 // Simulation parameters
  70 const int segments = 200; // Defines the resolution of the calculation, even number
  71 const int timesteps = 20000; // Length of simulation
  72 const int sampling = 200; // Data is sampled after this number of timesteps
  73 const double setupTick = distance / segments / setupApexSpeed; // [s] Duration of one tick during initialization
  74 // If simulationTick is too large, simulation will be numerically unstable, but not for reasons which have to do with physics
  75 const double simulationTick = setupTick / 100; // [s] A method is needed to calculate a suitable simulationTick
  76 
  77 // Globals
  78 double tick; // [s] Duration of one time step
  79 double apexSpeed; // [m/s] Speed of rotor at apex
  80 double trackDensity; // [kg/m]
  81 }
  82 
  83 namespace transient {
  84 
  85 struct Spring; // Forward declaration
  86 
  87 // Main data structure
  88 struct Segment
  89 {
  90   // Segment attributes
  91   double position[3]; // [m]
  92   double velocity[3]; // [m/s]
  93   double rotorMass; // [kg]
  94   double trackMass; // [kg] 
  95   double massRatio; // Ratio between gravitational and inertial mass, used to apply gravity during setup
  96   double direction[3]; // Normalized vector to next track segment
  97 
  98   // Mass and momentum transfer variables
  99   double designSpeed; // [m/s]
 100   double rotorSpeed; // [m/s] Actual speed
 101   double stableSpeed; // [m/s]
 102   double incomingMass; // [kg]
 103   double incomingVelocity[3]; // [m/s]
 104   double incomingPosition[3]; // [m]
 105 
 106   // Spring variables
 107   Spring* shearStress[2][2]; // Springs to model bending stresses [0 is upstream, 1 is downstram][0 is down, 1 is sideways]
 108   Spring* track; // Connection to downstream track segment
 109   Spring* wire[tracks][guyWires]; // Guy wires
 110 
 111   Segment() { 
 112     for2(i) for2(j) shearStress[i][j] = 0;
 113     track = 0;
 114     forN(tracks,d) forN(guyWires,w) wire[d][w] = 0;
 115   };
 116   double mass() { return rotorMass + trackMass; };
 117   double length() { return dist(position, (this+1)->position); };
 118   double speed() { return sqrt(sqr(velocity)); };
 119   double height() { return sqrt(sqr(position)) - earthRadius; }; // Height above ground
 120   void findDirection() { normalize(sub(direction, (this+1)->position, position)); };
 121   void applyGravity();
 122   void handleMomentum() { for3(a) position[a] += velocity[a] * tick; };
 123   void handleArrival();
 124   void activeStabilization();
 125   void handleDeparture();
 126   void connect(Spring** c, Segment* s, double* vector, double length, bool setup);
 127   void connectTrack(Segment* s, bool setup);
 128   void connectWire(Segment* s, int i, int j, int w, bool setup);
 129   void shearForces(bool setup);
 130   double* guyForce();
 131 };
 132 
 133 // Data structure for guy wires, track connections and shear stress, modelled as Kelvin-Voigt materials
 134 struct Spring // Each spring has design length, present length, and old length from previous timestep
 135 {
 136   bool bendable; // True for guy wires, false for track
 137   double designLength; // [m]
 138   double length; // [m] The length can be negative when modelling shear forces with springs
 139   double oldLength; // [m] Used to find damping
 140   double designTension; // [N]
 141   double guyTension; // [N] Only used by guy wires
 142   Segment* end[2]; // Remember that pointers can't handle being copied
 143   double dampingForce; // [N]
 144   double springConstant; // [kg/s^2]
 145   double vector[3]; // [m] Projection of vector from end[0] to end[1] onto spring direction
 146   void contract();
 147   double dampingConstant() { return 2 * sqrt(springConstant * (end[0]->mass() + end[1]->mass())) / 100; }; // [kg/s] Guess
 148   double springForce() { return - springConstant * (length - designLength) - designTension; };
 149   Spring() { guyTension = 0; };
 150 };
 151 
 152 // Data
 153 Segment track[tracks][segments+1];
 154 vector<Spring*> spring;
 155 
 156 // Member functions
 157 void Segment::applyGravity() {
 158   double down[3];
 159   for3(a) down[a] = -position[a];
 160   double g = earthMassTimesG * massRatio / sqr(down);
 161   normalize(down);
 162   for3(a) velocity[a] += down[a] * g * tick;
 163   for3(a) position[a] += down[a] * g * sqr(tick) / 2;
 164 }
 165 void Segment::handleArrival() {
 166   for3(a) velocity[a] = (incomingMass * incomingVelocity[a] + mass() * velocity[a]) / (mass() + incomingMass); 
 167   for3(a) position[a] = (incomingMass * incomingPosition[a] + mass() * position[a]) / (mass() + incomingMass);
 168   rotorMass += incomingMass;
 169 }
 170 void Segment::activeStabilization() { // This doesn't perform much better than simply setting stableSpeed = designSpeed
 171   stableSpeed = mass() * dot(velocity, direction) / rotorMass / sqr(direction); // Minimizing kinetic energy of track
 172   double minMaxSpeed[2]; // Index 0 is not necessarily the minimum
 173   for2(i) { // Alternatively, choose rotor speed such that potential plus kinetic energy of rotor is constant
 174     double g = earthMassTimesG / sqr((this-1+i)->position);
 175     minMaxSpeed[i] = sqrt(sqr((this-1+2*i)->rotorSpeed)
 176       - 2 * (this-1+i)->mass() / (this-1+i)->rotorMass * g * (this->height() - (this-1+2*i)->height()));
 177   }
 178   if ((stableSpeed > minMaxSpeed[0] && stableSpeed < minMaxSpeed[1]) || (stableSpeed < minMaxSpeed[0] && stableSpeed > minMaxSpeed[1])) {
 179 
 180   } else stableSpeed = designSpeed;
 181 }
 182 void Segment::handleDeparture() { 
 183   rotorSpeed = stableSpeed;
 184   // First we find the mass to be moved based on the speed and density
 185   (this+1)->incomingMass = rotorSpeed * rotorMass / length() * tick;
 186   rotorMass -= (this+1)->incomingMass;
 187   // Next, find the outgoing velocity
 188   normalize(sub((this+1)->incomingVelocity, (this+1)->position, position));
 189   for3(a) (this+1)->incomingVelocity[a] *= rotorSpeed;
 190   // Next, conserve momentum
 191   for3(a) velocity[a] = ((mass() + (this+1)->incomingMass) * velocity[a] - (this+1)->incomingMass * (this+1)->incomingVelocity[a]) / mass();
 192   // Lastly, adjust center of mass
 193   for3(a) (this+1)->incomingPosition[a] = (position[a] + (this+1)->position[a]) / 2;
 194   for3(a) position[a] = ((mass() + (this+1)->incomingMass) * position[a] - (this+1)->incomingMass * (this+1)->incomingPosition[a]) / mass();
 195 }
 196 void Segment::connect(Spring** c, Segment* s, double* vector, double length, bool setup) {
 197   if (setup) {
 198     spring.push_back((*c) = new Spring());
 199     (*c)->designLength = length;
 200     (*c)->oldLength = length;
 201     (*c)->end[0] = this;
 202     (*c)->end[1] = s;
 203     (*c)->bendable = false;
 204     (*c)->designTension = 0;
 205   }
 206   for3(a) (*c)->vector[a] = vector[a];
 207   (*c)->length = length;
 208 }
 209 void Segment::connectTrack(Segment* s, bool setup) {
 210   Spring** c = &track;
 211   connect(c, s, sub(s->position, position), dist(s->position, position), setup);
 212   if (setup) {
 213     (*c)->springConstant = sqr(soundInTrack) * trackDensity / (*c)->length;
 214     (*c)->designTension = 1e4; 
 215   } else (*c)->contract();
 216 }
 217 void Segment::connectWire(Segment* s, int i, int j, int w, bool setup) {
 218   Spring** c = &wire[j][w];
 219   connect(c, s, sub(s->position, position), dist(s->position, position), setup);
 220   if (setup) {
 221     (*c)->springConstant = sqr(soundInTrack) * trackDensity / (*c)->length / 10; // Artificially high, active tensioning
 222     (*c)->bendable = true;
 223     (*c)->designTension = 1; // Temporary value
 224     s->wire[i][w] = (*c); // Give opposing segment access to spring data
 225   } else (*c)->contract();
 226 }
 227 void Segment::shearForces(bool setup) {
 228   // First, find guy wire and track direction - these change with time and cannot be cached
 229   double axis[3][3]; // [0 is the track direction, 1 is down, 2 is sideways][x,y,z]
 230   for3(i) for3(j) axis[i][j] = 0;
 231   sub(axis[0], (this+1)->position, (this-1)->position);
 232   if (guyWire) { // Use guy wires to define the local "down" direction - should perhaps also use neighbour segments
 233     forN(tracks,d) forN(guyWires,w) if (wire[d][w]) for3(a) axis[1][a] += (wire[d][w]->end[0] == this? 1 : -1) * wire[d][w]->vector[a];
 234     cross(axis[2], axis[0], axis[1]);
 235   } else { // Use north to define sideways
 236     axis[2][1] = 1;
 237     cross(axis[1], axis[0], axis[2]);
 238     cross(axis[2], axis[0], axis[1]);
 239   }
 240   for3(a) normalize(axis[a]);
 241   // Next, do projections, reducing to one dimensional strains
 242   double projection[3][3]; // Indices are segment and axis 
 243   for3(s) for3(a) projection[s][a] = dot((this-1+s)->position, axis[a]) / sqr(axis[a]);
 244   // Next, find the deflection
 245   double deflection[2]; // [0 is guy wire direction, 1 is sideways]
 246   for2(i) deflection[i] = projection[1][i+1] - (projection[0][i+1] + projection[2][i+1])/2;
 247   // Move the data to the spring
 248   for2(i) for2(j) {
 249     Spring** c = &shearStress[i][j];
 250     connect(c, this+2*i-1, axis[1+j], -deflection[j], setup);
 251     if (setup) (*c)->springConstant = shearModulus * trackArea / length();
 252     else (*c)->contract();
 253   }
 254 }
 255 double* Segment::guyForce() { // Find the combined force of all guy wires
 256   for3(a) temp[a] = 0;
 257   forN(tracks,j) forN(guyWires,w) if (wire[j][w]) {
 258     normalize(wire[j][w]->vector);
 259     for3(a) temp[a] += (wire[j][w]->end[0] == this? -1 : 1) * wire[j][w]->springForce() * wire[j][w]->vector[a];
 260   }
 261   return temp;
 262 }
 263 
 264 void Spring::contract() {
 265   double springSpeed = (length - oldLength) / tick;
 266   oldLength = length;
 267   dampingForce = - dampingConstant() * springSpeed;
 268   normalize(vector); // Get direction of acceleration
 269   double force = springForce() + dampingForce;
 270   if (bendable && force > 0) force = 0; // A bendable spring can only provide a contracting (negative) force, or it buckles
 271   for2(i) for3(a) end[i]->velocity[a] += (2*i-1) * force * tick * vector[a] / end[i]->mass(); // Newtons law
 272 }
 273 
 274 // Initialization
 275 void traceTrack(Segment* t) { 
 276   // Define initial parabola - disperse track segments so the slugs pass by them at constant time intervals
 277   forN(segments+1,s) t[s].rotorMass = rotorDensity * apexSpeed * tick; // Is this balanced right?
 278   Segment* middle = &t[segments/2];
 279   for3(a) middle->position[a] = apex[a];
 280   middle->velocity[0] = apexSpeed;
 281   middle->trackMass = trackDensity * apexSpeed * tick;
 282   middle->massRatio = (middle->trackMass + middle->rotorMass) / middle->rotorMass;
 283   for (int d = -1; d <= 1; d += 2) { // 2 different directions
 284     for3(a) middle->velocity[a] *= -1; // Switch direction
 285     for (int i = 1; i <= segments/2; i++) { 
 286       Segment* s = t + segments/2 + d*i;
 287       for3(a) s->position[a] = (s-d)->position[a] + (s-d)->velocity[a] * tick;
 288       for3(a) s->velocity[a] = (s-d)->velocity[a];
 289       s->trackMass = trackDensity * s->speed() * tick;
 290       s->massRatio = s->mass() / s->rotorMass;
 291       s->applyGravity();
 292     }
 293   }
 294   forN(segments+1,s) t[s].position[1] = (double(rand())/RAND_MAX-0.5)/100; // Centimeter precision in startup
 295 }
 296 void findTrackDensity(Segment* t) {
 297   // Adjust the weight of the track to keep the rotor down
 298   trackDensity = 10 * rotorDensity; // Guess, to be improved upon
 299   for (double adjustment = trackDensity/2; adjustment > 0.01; adjustment /= 2) {
 300     traceTrack(t);
 301     trackDensity += adjustment * (t[0].height() > 0? 1 : -1);
 302   }
 303   cout << "Track density " << trackDensity << endl;
 304   cout << "Rotor speed at ground " << t[0].speed() << endl;
 305 }
 306 void applyHelix(Segment* t, int d)
 307 {
 308   double north[3] = {0,1,0};
 309   double up[segments+1][3];
 310   forN(segments+1,s) {
 311     normalize(cross(up[s], t[s].direction, north));
 312     // Equal time between segments leads to equal periods of centrifugal rotation
 313     for3(a) t[s].position[a] += north[a] * helixRadius * sin(helixes*pi*s/segments + d*2*pi/tracks);
 314     for3(a) t[s].position[a] += up[s][a] * helixRadius * cos(helixes*pi*s/segments + d*2*pi/tracks);
 315   }
 316 }
 317 void handleSprings(bool setup) {
 318   if (guyWire) forN(segments+1,i) forN(tracks,d) forN(tracks,j) forN(guyWires,w) {
 319     int opposite = i + w - (guyWires-1)/2;
 320     if (eastbound[d] != eastbound[j]) opposite = segments - opposite; 
 321     Segment* s = &track[d][i];
 322     if (opposite >= 0 && opposite <= segments && d != j) { // Stay within track, don't connect to self
 323       if ((setup && !s->wire[j][w] && !track[j][opposite].wire[d][w]) // Check that this isn't a repeat
 324         || (!setup && s->wire[j][w] && s->wire[j][w]->end[0] == s)) { // Check that wire exists
 325         s->connectWire(&track[j][opposite], d, j, w, setup);
 326       }
 327     }
 328   }
 329   // Fix guy wire tension so it balances centrifugal force
 330   if (setup && guyWire) forN(segments+1,i) forN(tracks,d) {
 331     Segment* s = &track[d][i];
 332     double* sum = s->guyForce();
 333     double factor = centrifugalAcceleration * s->rotorMass / s->length() * s->designSpeed * tick / 2 / sqrt(sqr(sum));
 334     forN(tracks,j) forN(guyWires,w) if (s->wire[j][w]) s->wire[j][w]->guyTension += factor;
 335   }
 336   if (setup && guyWire) forN(segments+1,s) forN(tracks,i) forN(tracks,j) forN(guyWires,w)
 337     if (track[i][s].wire[j][w]) track[i][s].wire[j][w]->designTension = track[i][s].wire[j][w]->guyTension;
 338   // Track connection
 339   forN(tracks,d) forN(segments,s) track[d][s].connectTrack(&track[d][s+1], setup);
 340   // Shear forces
 341   forN(tracks,d) forN(segments-1,s) track[d][s+1].shearForces(setup);
 342 }
 343 void setupLoop() {
 344   findTrackDensity(track[0]);
 345   forN(tracks,d) forN(segments+1,s) track[d][s] = track[0][s]; // Copy initial parabola
 346   forN(tracks,d) {
 347     forN(segments,s) track[d][s].findDirection();
 348     for3(a) track[d][segments].direction[a] = track[d][segments-1].direction[a]; // This is an approximation
 349     if (helicalTrack) applyHelix(track[d], d);
 350     // The westbound track must move opposite the eastbound track, so we swap
 351     if (!eastbound[d]) forN(segments/2,s) swap(Segment,track[d][s],track[d][segments-s]); 
 352     forN(segments,s) track[d][s].findDirection(); // Direction has changed now
 353     forN(segments+1,s) track[d][s].designSpeed = track[d][s].speed() * (simulationApexSpeed/setupApexSpeed);
 354     forN(segments+1,s) track[d][s].rotorSpeed = track[d][s].designSpeed; 
 355     forN(segments+1,s) for3(a) track[d][s].velocity[a] = track[d][s].designSpeed * track[d][s].direction[a] / track[d][s].massRatio;
 356     forN(segments+1,s) track[d][s].massRatio = 1; 
 357   }
 358   handleSprings(true); // Setup of springs
 359 }
 360 
 361 // Output
 362 void saveToFile(int t) {
 363   ofstream file;
 364   stringstream filename;
 365   filename << "data/t" << 1000000 + t << ".txt"; // Inelegant method for getting alphabetical order
 366   file.open(filename.str());
 367   forN(tracks,d) forN(segments-1,i)  {
 368     Segment* s = &track[d][i+1];
 369     int color = (i + int((timesteps-t) * (simulationApexSpeed/setupApexSpeed) / (setupTick/simulationTick))) % (segments/2);
 370     if (color > segments/4) color = rotorColor[d]; else color = getColor(0,0,0);
 371     if (i == 0) color = getColor(255,255,255); // Invisible jump from eastbound to westbound
 372     file << s->position[0] / 1000 << " ";
 373     file << s->position[1] << " ";
 374     file << s->height() / 1000 << " ";
 375     file << color << " ";
 376     file << log(abs(s->track->springForce())+10e-20) << " ";
 377     file << log(sqrt(sqr(s->guyForce()))+10e-20) << " ";
 378     file << log(s->rotorMass/track[d][i].length()*sqr(s->designSpeed)+10e-20) << "\n";
 379   }
 380   file.close(); 
 381 }
 382 void evaluate() {
 383   // Rotor mass
 384   double maxRotor[4];
 385   for2(i) maxRotor[i] = track[0][0].rotorMass; for2(i) maxRotor[2+i] = 0;
 386   forN(tracks,t) forN(segments,s) for2(i) if (track[t][s].rotorMass * (2*i-1) > (2*i-1) * maxRotor[i]) {
 387     maxRotor[i] = track[t][s].rotorMass;
 388     maxRotor[2+i] = s;
 389   }
 390   cout << "Rotor mass extremum "; for2(i) cout << 100*maxRotor[i]/track[0][0].rotorMass << "% ";
 391   cout << "Index "; for2(i) cout << maxRotor[2+i] << " "; cout << endl;
 392   // Rotor speed
 393   for2(i) maxRotor[i] = 1; for2(i) maxRotor[2+i] = 0;
 394   forN(tracks,t) forN(segments-1,s) for2(i) if (track[t][s+1].rotorSpeed/track[t][s+1].designSpeed * (2*i-1) > (2*i-1) * maxRotor[i]) {
 395     maxRotor[i] = track[t][s+1].rotorSpeed/track[t][s+1].designSpeed;
 396     maxRotor[2+i] = s+1;
 397   }
 398   cout << "Rotor speed extremum "; for2(i) cout << 100*maxRotor[i] << "% ";
 399   cout << "Index "; for2(i) cout << maxRotor[2+i] << " "; cout << endl;
 400 }
 401 
 402 // Simulation
 403 void simulateTrack(Segment* t) {
 404   for (int i = 1; i < segments; i++) t[i].findDirection();
 405   // Handle the injection of new slugs
 406   t[1].incomingMass = t[0].rotorMass / t[0].length() * t[0].designSpeed * tick;
 407   for3(a) t[1].incomingVelocity[a] = t[0].designSpeed * t[0].direction[a];
 408   for3(a) t[1].incomingPosition[a] = (t[0].position[a] + t[1].position[a]) / 2;
 409   // Handle the main track
 410   for (int i = 1; i < segments; i++) t[i].applyGravity();
 411   for (int i = 1; i < segments; i++) t[i].activeStabilization();
 412   for (int i = 1; i < segments; i++) t[i].handleDeparture();
 413   for (int i = 1; i < segments; i++) t[i].handleArrival();
 414   for (int i = 1; i < segments; i++) t[i].handleMomentum();
 415 }
 416 void simulateLoop() {
 417   cout << "Remaining timesteps ";
 418   forN(timesteps+1,t) {
 419     if (t % (timesteps/10) == 0) { cout << 100 - 100*t/timesteps << "%" << endl; if (t > 0) evaluate(); }
 420     else if (t % (timesteps/100) == 0) cout << ".";
 421     forN(tracks,d) simulateTrack(track[d]);
 422     handleSprings(false);
 423     if (t % sampling == 0) saveToFile(t);
 424   }
 425 }
 426 
 427 } // End of namespace
 428 
 429 using namespace transient;
 430 
 431 int main () {
 432   // Initialize
 433   tick = setupTick; 
 434   apexSpeed = setupApexSpeed;
 435   setupLoop();
 436   // Simulate
 437   tick = simulationTick;
 438   apexSpeed = simulationApexSpeed;
 439   simulateLoop();
 440   return 0;
 441 }

Attached Files

To refer to attachments on a page, use attachment:filename, as shown below in the list of files. Do NOT use the URL of the [get] link, since this is subject to change and can break easily.
  • [get | view] (2011-05-24 15:10:38, 1.9 KB) [[attachment:LaunchLoopScript]]
  • [get | view] (2011-05-24 14:43:53, 228.0 KB) [[attachment:NumericalSimulation1]]
  • [get | view] (2011-05-24 15:00:36, 228.0 KB) [[attachment:NumericalSimulation1.gif]]
  • [get | view] (2011-05-24 14:50:37, 557.1 KB) [[attachment:NumericalSimulation2.gif]]
  • [get | view] (2011-05-24 15:06:56, 20.3 KB) [[attachment:main.cpp]]
 All files | Selected Files: delete move to page

You are not allowed to attach a file to this page.