////////////////////////////////////////////////////////////////////////////
// druzice.cc -- použití knihovny SIMLIB pro spojitou simulaci 3D
//
// (c) PerPet 1997
#include "simlib.h"
#include "simlib3D.h"
typedef Value3D Position, Speed, Force; // pojmenování typů
const double gravity_constant = 6.67e-11; // gravitační konstanta
const double m0 = 1000; // hmotnost družice
const double m1 = 5.983e24; // hmotnost Země
const double m2 = 7.374e22; // hmotnost Měsíce
const Position p0(36.0e6, 0, 0); // poloha družice
const Position p2(384.405e6, 0, 0); // poloha Měsíce
const Speed v0(0, 4200, 1600); // počáteční rychlost družice
const Speed v2(0, 1022, 0); // oběžná rychlost Měsíce
const double MAXTime=3.6e7; // doba simulace
Constant3D Zero3D(0,0,0); // pomocný objekt
// abstrakce "hmotný bod"
struct MassPoint {
double m; // hmotnost
Expression3D inforce; // vstupní síla
Integrator3D v; // rychlost
Integrator3D p; // poloha
MassPoint(const double mass, Position p0, Speed v0=Speed(0,0,0)) :
m(mass),
inforce(Zero3D),
v(inforce/m, v0),
p(v,p0) {}
void SetInput(Input3D i) { inforce.SetInput(i); }
};
// abstrakce "digitální svět"
struct MyWorld {
enum { MAX=10 };
MassPoint *m[MAX];
unsigned n;
MyWorld();
Position Mcenter() { // výpočet těžiště systému
Position p = Value3D(0,0,0);
double sum = 0;
for(int i=0; i<n; i++) {
p = p + m[i]->m * m[i]->p.Value();
sum += m[i]->m;
}
return p/sum;
}
};
MyWorld *w; // svět vznikne až později :-)
// gravitační síla pusobící na hmotný bod p
class GravityForce : public aContiBlock3D {
MassPoint *p;
MyWorld *w;
public:
GravityForce(MassPoint *_p, MyWorld *_w) : p(_p), w(_w) {}
Force Value() {
Force f(0,0,0); // gravitační síla
for(int i=0; i < w->n; i++) {
MassPoint *m = w->m[i];
if (m == p) continue;
Value3D distance = m->p.Value() - p->p.Value();
double d = abs(distance); // vzdálenost
f = f + (distance * gravity_constant * p->m * m->m / (d*d*d)) ;
}
return f;
}
};
// pohyblivé planety
typedef MassPoint Planet, Satelite;
MyWorld::MyWorld() { // vytvoříme digitální svět
n=0;
m[n++] = new Planet(m1,Position(0,0,0),Speed(0,0,0));
m[n++] = new Planet(m2,p2,v2);
m[n++] = new Satelite(m0,p0,v0);
for(int i=0; i<n; i++) // zapneme silové působení
m[i]->SetInput(new GravityForce(m[i],this));
}
// sledování stavu modelu ...
void Sample();
Sampler s(Sample,3600); // vzorkování stavu modelu
void Sample() {
Position t = w->Mcenter(); // těžiště systému
Position p = (w->m[2])->p.Value() - t; // pozice měsíce
Position p1 = (w->m[1])->p.Value() - t; // pozice družice
Print("%g ", Time);
Print("%g %g %g ", p1.x()/1e6, p1.y()/1e6, p1.z()/1e6);
Print("%g %g %g ", p.x()/1e6, p.y()/1e6, p.z()/1e6);
Print("\n");
}
// popis experimentu ...
int main()
{
SetOutput("druzice.dat");
w = new MyWorld; // vytvoříme "digitální svět"
Print("# Model oběhu družice kolem soustavy Země-Měsíc \n");
Init(0, MAXTime); // inicializace experimentu
SetMethod("abm4"); // je vhodná vícekroková metoda
SetAccuracy(1e-7); // potřebujeme vysokou přesnost
Run(); // simulace
return 0;
}
syntax highlighted by Code2HTML, v. 0.9.1