[gelöst] Mittelwertbildung



  • Guten Abend,

    ich habe mal wieder eine Frage.

    Ich arbeite mit der Monte Carlo Methode, d.h. ich bin gezwungen mein Programm sehr oft laufen zu lasen, um die Ergebnisse am Ende zu mitteln.
    Allerdings würde ich auch gerne zu verschiedenen Zeitpunkten gemittelte Ergebnisse (Datensätze) abspeichern, um sie graphisch darzustellen.

    Also wenn ich z.B. das Programm n = 100 mal laufen lassen möchte bis zur Zeiteinheit 50 (hochgezählt in 0.1er), so sieht das bisher so aus.

    int n = 100;
    
    for(int i = 0; i < n; i++)
    {
      double actual_time = 0;
      double final_time = 50;
      double time_step = 0.1;
    
      while(actual_time < final_time)
      {
        // do something
    
        actual_time = actual_time + time_step;
      }
    }
    

    Jetzt möchte ich z.B. zählen wie viele Elemente die Energie x zwischen 0 und 100 haben mit einer Genauigkeit von 1.
    D.h. ich bastle mir einen Array mit 100 Einträgen.

    double energy[100] = { 0 };
    

    Wenn dann im Code ein Element mit der Energie x erzeugt wird, so runde ich das ganze durch Verwandlung in ein int in eine ganze Zahl und habe direkt den Eintrag für meinen Array, also z.B.

    double energy = 37.83;
    int counter = energy; // counter besitzt jetzt den Wert 37
    energy[counter]++;
    

    Und am Ende müsste ich jedes Element von energy[100] durch die Anzahl der Durchläufe teilen.

    double energy[100] = { 0 };
    
    int n = 100;
    
    for(int i = 0; i < n; i++)
    {
      double actual_time = 0;
      double final_time = 50;
      double time_step = 0.1;
    
      while(actual_time < final_time)
      {
        // do something
        double energy x;
        int counter = x;
        energy[counter]++; 
    
        actual_time = actual_time + time_step;
      }
    }
    
    for(int i = 0; i < n; i++)
    {
      energy[i] = energy[i] / n;
    }
    
    // mittels fstream energy[100] in eine Datei schreiben
    

    So, ich denke es ist nicht besonders hübsch, aber so würde ich es momentan machen und das sollte auch funktionieren. Hoffe ich.

    Jetzt würde ich nur gerne auch zwischendrin Datensätze abfangen. Also z.B. nach der Zeiteinheit 15. Ich könnte das z.B. durch das Kriterium

    if(actual_time % 15 == 0);
    

    abfangen.

    Wie könnte ich das machen?
    Ich könnte einen energy15[100] Array erzeugen, für den gilt

    if(acutal_time % 15 == 0)
    {
      for(int i = 0; i < n; i++)
      {
        energy15[i] = energy[i];
      }
    }
    

    Und den müsste ich nach jedem Durchlauf aktualisieren, also nachdem wie while - Schleife beendet ist.

    for(int i = 0; i < n; i++)
    {
      energy15[i] = energy15[i] + (energy15[i] / n);
    }
    

    Das kommt mir aber alles wieder so gepfrimelt vor. Ich hatte auch schon daran gedacht einen Container aus der STL zu nehmen, nachdem mit der Liste schon so gute Erfahrung gemacht habe.

    Versteht ihr was ich meine und könnt mir weiterhelfen?

    Gruß,
    Klaus.


  • Mod

    Trenne Simulation und Messung. Schreib dir einfach zu allen Zeitpunkten die dich interessieren die Energien raus. Du wirst schließlich in den seltensten Fällen nur die Energieverteilung für die Auswertung brauchen.

    Du kannst natürlich trotzdem Zwischenauswertungen machen. Dafür empfehle ich dir aber, von deinem jetzigen Design aus nochmals ganz gewaltig zu abstrahieren. Biete in deiner Simulation ein abstraktes Interface für Messungen an. Die Messungen sind dann eigene Klassen, die dieses Interface nutzen und ihre eigenen Daten verwalten. Da kannst du dann eine Messklasse machen, die ein Histogramm alle N Schritte erstellt und erstellst davon dann zwei Instanzen, eine mit N=1 und eine mit N=15. Die Messungen werden von einem der Simulation und der Messung übergestellten Hauptprogramm verwaltet und bei jedem Messschritt werden alle Messungen auf die Simulation losgelassen und kommunizieren mit dieser über die bereitgestellte Schnittstelle.

    Ich hoffe, diese Beschreibung in Worten ist für dich verständlich. Ich fürchte nämlich, selbst ein stark abgespecktes Beispiel würde locker ein paar hundert Zeilen haben und wäre auch nicht mal eben her zu entwickeln. Außer, ich nähme meinen eigenen fertigen Code als Grundlage und kürzte diesen, aber das möchte ich nicht. Aber immerhin kann ich dir so aus eigener Erfahrung sagen, dass dieses Design recht brauchbar ist.



  • SeppJ schrieb:

    Du kannst natürlich trotzdem Zwischenauswertungen machen. Dafür empfehle ich dir aber, von deinem jetzigen Design aus nochmals ganz gewaltig zu abstrahieren. Biete in deiner Simulation ein abstraktes Interface für Messungen an. Die Messungen sind dann eigene Klassen, die dieses Interface nutzen und ihre eigenen Daten verwalten. Da kannst du dann eine Messklasse machen, die ein Histogramm alle N Schritte erstellt und erstellst davon dann zwei Instanzen, eine mit N=1 und eine mit N=15. Die Messungen werden von einem der Simulation und der Messung übergestellten Hauptprogramm verwaltet und bei jedem Messschritt werden alle Messungen auf die Simulation losgelassen und kommunizieren mit dieser über die bereitgestellte Schnittstelle.

    Ich hoffe, diese Beschreibung in Worten ist für dich verständlich.

    Es geht so, ich muss einfach mehr und intensiver C++ lernen. 😡

    Und ich dachte schon Physik alleine wäre anstrengend ...

    Gruß,
    Klaus.


  • Mod

    Das ist eigentlich nicht C++-spezifisch, sondern sehr allgemeine Überlegungen, insbesondere zu objektorientiertem Design, insbesondere "separation of concerns" (k.A. wie man das auf Deutsch sagt). Das einzige, was ein bisschen C++-spezifisch an meinem Beitrag ist, ist das Konzept der "Klasse", welches in der objektorientierten Programmierung nur optional (aber nützlich!) ist und von C++ direkt unterstützt wird. Die Überlegungen kann man natürlich ziemlich 1:1 nach C++ übersetzen, aber prinzipiell gilt das in jeder Sprache, die Objektorientierung ermöglicht.



  • Klaus82 schrieb:

    Und ich dachte schon Physik alleine wäre anstrengend ...

    Ist alles Ansichtssache, vor allem kommts drauf an, um welchen Teilbereich der Physik es geht. Wenns um theoretische Physik geht muss ich dir ab nem gewissen Level recht geben - dagegen ist C++ dann schon ein netter Zeitvertreib 😉


Anmelden zum Antworten