Benutzer-Werkzeuge

Webseiten-Werkzeuge


ss16:physiksimulation_doc_cpp

Unterschiede

Hier werden die Unterschiede zwischen zwei Versionen gezeigt.

Link zu dieser Vergleichsansicht

Beide Seiten der vorigen Revision Vorhergehende Überarbeitung
Nächste Überarbeitung
Vorhergehende Überarbeitung
ss16:physiksimulation_doc_cpp [2016/08/13 18:05]
markumnus object.cpp hinzugefügt
ss16:physiksimulation_doc_cpp [2016/08/14 22:11] (aktuell)
markumnus
Zeile 3: Zeile 3:
 </​a></​center></​html>​ </​a></​center></​html>​
  
-<- [[ss16:​Physiksimulation_doc_components|zurück zur Liste der Komponenten]] +**[[ss16:​Physiksimulation|Physiksimulation]]/​[[ss16:​Physiksimulation_Doc_Main|Dokumentation]]/​[[ss16:​Physiksimulation_doc_components|Komponenten]]/** 
- +=====C++-Teil=====
-=====Physiksimulation | C++-Teil=====+
 **INFO**: Soweit nicht anders angegeben, sind die Code-Bestandteile auf dieser Seite aus den jeweiligen Header-Dateien. **INFO**: Soweit nicht anders angegeben, sind die Code-Bestandteile auf dieser Seite aus den jeweiligen Header-Dateien.
  
Zeile 106: Zeile 105:
 }; };
 </​code>​ </​code>​
 +
 +
 +====universe.cpp====
 +Unser Universe dient als Container für Objects. Im Prinzip funktioniert es wie ein std::vector mit besseren Zugriffsmöglichkeiten.
 +<code cpp>
 +#include "​object.hpp"​
 +
 +class Universe
 +{
 +    private:
 +    // DEKLARATION DER ATTRIBUTE
 +        std::vector <​Object*>​ objects;
 +        ​
 +    public:
 +    // KONSTRUKTOREN
 +        Universe ();
 +        ​
 +    // DESTRUKTOR
 +        ~Universe ();
 +            ​
 +    // GETTER
 +        std::vector <​Object*>​ getObjects() const;
 +        Object* getObject (std::​string) const;
 +
 +    // SONSTIGE FUNKTIONEN
 +        void add (Object*);
 +        unsigned int size() const;
 +        void remove (Object*);
 +        std::string asString ();
 +};
 +</​code>​
 +Die //​size()//​-Methode gibt die Anzahl der //Object//s zurück, die sich aktuell in diesem Universe befinden.
 +
 +
 +====simulation.cpp====
 +Die Simulation ist das Herzstück des C++-Teils. Hier laufen die Berechnungen ab, deren Ergebnisse später angezeigt werden.\\
 +Hier sind das Euler- und das Runge-Kutta-Verfahren implementiert,​ wobei wir aktuell nur letzteres tatsächlich nutzen.
 +<code cpp>
 +#include "​universe.hpp"​
 +
 +class Simulation
 +{
 +    private:
 +    // DEKLARATION DER ATTRIBUTE
 +        double dt;
 +        const double stdG = 0.0002958935421;​
 +        double G;
 +        ​
 +        Universe* unvrs;
 +            ​
 +    public:
 +    // KONSTRUKTOR
 +        Simulation (Universe*);​
 +        Simulation (Universe*, double);
 +
 +    // FUNKTIONEN
 +        void setG (double);
 +        void setDT (double);
 +        void simulate ();
 +        void simulate (unsigned int); // simuliert n Schritte
 +        void simulate_rk4 ();
 +        void simulate_rk4 (unsigned int); // simuliert n Schritte
 +
 +        // Euler-Verfahren
 +        Vector3D updateForce (unsigned int) const;
 +        void updateAcc ();
 +        void updateVel ();
 +        void updatePos ();
 +        ​
 +        // Runge-Kutta-Verfahren
 +        void updateVel_rk4 ();
 +        void updatePos_rk4 ();
 +};
 +</​code>​
 +Die Hauptmethode ist //​simulate_rk4()//​. Hier werden die Beschleunigungen (und Kräfte) berechnet, daraus die Geschwindigkeiten und daraus die Positionen.\\
 +Dazu ein paar Ausschnitte aus der simulation.cpp:​
 +<code cpp>
 +void Simulation::​simulate_rk4 ()
 +{
 +    updateAcc();​
 +    updateVel_rk4();​
 +    updatePos_rk4();​
 +}
 +
 +</​code>​
 +Bei der Berechnung der Beschleunigungen ist die Berechnung der Kräfte mit eingebunden,​ denn aus\\
 +//F=m*a//\\
 +folgt\\
 +//a = F/m//\\
 +<code cpp>
 +void Simulation::​updateAcc ()
 +{
 +    Vector3D newAcc = Vector3D(0.,​0.,​0.);​
 +    for (unsigned int i = 0; i < unvrs->​size();​ i++)
 +    {
 +        newAcc = (updateForce(i)/​unvrs->​getObjects().at(i)->​getMass());​
 +        unvrs->​getObjects().at(i)->​setAcc(newAcc);​
 +    }
 +}
 +</​code>​
 +Die Kräfte werden nach [[https://​wikimedia.org/​api/​rest_v1/​media/​math/​render/​svg/​46315ddb85d544f9eee7bbde7798f6dae9829428|dieser]] Formel in updateForce() berechnet.
 +<code cpp>
 +Vector3D Simulation::​updateForce (unsigned int a) const // a ist der Index des Object im Universe
 +{
 +    ​
 +    std::​vector<​Object*>​ objects = unvrs->​getObjects();​
 +    std::​vector<​Vector3D>​ forces (objects.size(),​ Vector3D (0.,​0.,​0.));​
 +    for (unsigned int i = 0; i < objects.size();​ i++)
 +    {
 +        if (i != a) // Object wirkt keine Kraft auf sich selbst aus
 +        {
 +            Vector3D abstand_vec (objects.at(a)->​getPos() - objects.at(i)->​getPos());​
 +            double abstand = objects.at(a)->​getPos().abstand(objects.at(i)->​getPos());​
 +            ​
 +            forces.at(a) = forces.at(a) + (abstand_vec * ((objects.at(a)->​getMass() * objects.at(i)->​getMass())/​(abstand*abstand*abstand))* -G);
 +        }
 +    }
 +    ​
 +    return forces.at(a);​
 +}
 +
 +</​code>​
 +Mit den berechneten Beschleunigungen kann man nun mithilfe des Runge-Kutta-Verfahrens die Geschwindigkeiten und analog dazu die Positionen berechnen:
 +<code cpp>
 +void Simulation::​updateVel_rk4 ()
 +{
 +    std::​vector<​Object*>​ objects = unvrs->​getObjects();​
 +    Vector3D newVel = Vector3D(0.,​0.,​0.);​
 +    for (unsigned int i = 0; i < objects.size();​ i++)
 +    {
 +        Vector3D k1 = (objects.at(i)->​getAcc()) * dt;
 +        Vector3D k2 = (objects.at(i)->​getAcc() + (k1*0.5)) * dt;
 +        Vector3D k3 = (objects.at(i)->​getAcc() + (k2*0.5)) * dt;
 +        Vector3D k4 = (objects.at(i)->​getAcc() + (k3)) * dt;
 +        ​
 +        newVel = objects.at(i)->​getVel() + ((k1 + k2*2 + k3*2 + k4)/6);
 +        ​
 +        objects.at(i)->​setVel(newVel);​
 +    }
 +}
 +
 +</​code>​
 +
 +
 +====auswertung.cpp====
 +Die Auswertung-Klasse dient dem Sammeln von Daten über das Universum. Hier werden zum Beispiel auch die Positionsdaten der //Object//s in die Ergebnis-Textdatei geschrieben. Dazu dienen die folgenden Funktionen:
 +<code cpp>
 +#include "​simulation.hpp"​
 +
 +class Auswertung
 +{
 +    private:
 +    // DEKLARATION DER ATTRIBUTE
 +        Universe* unvrs;
 +        std::vector <​std::​string>​ results;
 +
 +    public:
 +    // KONSTRUKTOR
 +        Auswertung(Universe*);​
 +        ​
 +    // ANDERE METHODEN
 +        void clear();
 +        std::string currentState() const;
 +        void writeToBuffer();​
 +        void writeToFile();​
 +};
 +</​code>​
 +Die Funktionalität ist einfach: In jedem Zeitschritt werden die Positionsdaten in den Buffer (hier ein std::​vector<​std::​string>​) geschrieben,​ um das Textdokument nicht permanent öffnen und wieder schließen zu müssen. Sobald eine bestimmte Anzahl an Elementen im Buffer sind (bei uns 50), wird der Inhalt in die Textdatei geschrieben und der Buffer geleert.
 +
 +
 +====interface.cpp====
 +Diese Klasse ist dazu da, eine Schnittstelle zum C++-Teil zur Verfügung zu stellen. Mithilfe der Methoden des Interfaces kann man alle relevanten Funktionen des C++-Teils steuern:
 +<code cpp>
 +#include "​auswertung.hpp"​
 +
 +class Interface
 +{
 +    private:
 +    // DEKLARATION DER ATTRIBUTE
 +        Universe* ​  u;
 +        Simulation* s;
 +        Auswertung* a;
 +    ​
 +    public:
 +    // KONSTRUKTOR
 +        Interface();​
 +        Interface (double G);
 +    ​
 +    // METHODEN
 +        void add(std::​string,​ double, double, double, double, double, double, double);
 +        void modify (std::​string,​ double, double, double, double, double, double, double);
 +        void run (unsigned int);
 +        std::string step ();
 +        void setG (double);
 +        void setDT (double);
 +};
 +</​code>​
 +Wie man sieht, sind vor allem die add()- und modify()-Methode sehr unübersichtlich. Deshalb werden wir später, im [[ss16:​Physiksimulation_Doc_cython|Cython-Teil]],​ eine besser benutzbare Version davon erstellen. Hier an dieser Stelle vereinfacht es die Benutzung sogar, eine Methode zu haben, die beispielsweise ein Objekt nur im Ganzen hinzufügt.\\
 +//setG()// und //setDT()// stellen die Parameter für die Berechnung ein: G ist die Gravitationskonstante und DT die Genauigkeit bei der Berechnung.\\
 +//step()// führt einen Berechnungsschritt aus, //run()// so viele, wie angegeben.
ss16/physiksimulation_doc_cpp.1471104334.txt.gz · Zuletzt geändert: 2016/08/13 18:05 von markumnus