//////////////////////////////////////////////////////////////////////////// // 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; im * 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; iSetInput(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; }