Probleme bei der Implementierung der Lattice-Boltzmann-Methode

Ich möchte eine grundlegende 2D-Implementierung der Lattice Boltzmann-Methode (in Javascript) erstellen, um den Gas-/Flüssigkeitsfluss zu simulieren, aber ich bin auf einige Probleme gestoßen und kann die Ursache dafür anscheinend nicht finden.

Das Problem ist, dass beim Ausführen des Kollisionsschritts (ich habe Streaming noch nicht vollständig implementiert) die Simulation explodiert und ins Unendliche abläuft und ich meinen Code sehr gründlich auf Fehler überprüft habe.

Ich beginne mit der Initialisierung meiner Variablen:

function Grid(width, height){
        this.width = width;
        this.height = height;
        this.f = [];
        this.e = [
            new vec2(0,0),
            new vec2(0,1),
            new vec2(1,0),
            new vec2(0,-1),
            new vec2(-1,0),
            new vec2(1,1),
            new vec2(1,-1),
            new vec2(-1,-1),
            new vec2(-1,1)
        ];
        this.w  = [4/9, 1/9, 1/9, 1/9, 1/9, 1/36, 1/36, 1/36, 1/36];
        for(var x=0; x<width; x++){
            this.f[x] = [];
            for(var y=0; y<height; y++){
                this.f[x][y] = [];
                for(var i=0; i<9; i++){
                    this.f[x][y][i] = 20+Math.random();
                }
            }
        }
    }

Hier ist this.f die Verteilungsfunktion mit 9 Richtungen: 0 für keine Bewegung, 1-4 für gerade Bewegung und 5-9 für die schrägen Geschwindigkeiten. Die Verteilungsfunktion hat Werte im Bereich von 20-21. This.e enthält alle Richtungen als Vektoren (ich habe meine eigene einfache vec2-Klasse erstellt) und this.w enthält die Gewichte für jede Richtung. Die erste Frage, die ich stellen möchte, lautet: Habe ich die Distribution mit den richtigen Werten initialisiert? Ich konnte nicht viele Informationen über die Initialisierungswerte finden.

Zweitens könnten meine Fehler im Kollisionsschritt liegen:

    collide: function(){
        for(var x=0; x<width; x++){
                for(var y=0; y<height; y++){
                    var rho = 0;
                    for(var i=0; i<9; i++){
                        rho += this.f[x][y][i];
                    }

                    var u = new vec2(0,0);
                    for(var i=0; i<9; i++){
                        u  = u.add( this.e[i].scale( this.f[x][y][i] ) );
                    }
                    u = u.scale( 1/rho );
                    for(var i=0; i<9; i++){
                        var eu = u.dot(this.e[i]);
                        var uu = u.dot(u);
                        var fiEq = this.w[i]*rho*(1+3*eu+4.5*eu*eu-1.5*uu);
                        this.f[x][y][i] = this.f[x][y][i] - .005*(this.f[x][y][i]-fiEq);
                    }
                }
            }
        }

Zuerst berechne ich die makroskopische Dichte rho, dann berechne ich mit Vektoraddition die makroskopische Geschwindigkeit u. Ich verwende diese in der folgenden Formel, um die Gleichgewichtsverteilung zu berechnen: Gleichgewichtsgleichungund dann entspanne ich die Verteilung in Richtung Gleichgewicht. Als zweite Frage möchte ich fragen, ob ich den Kollisionsschritt richtig implementiert habe.

Ein Live-Beispiel ist hier zu sehen

Wenn mehr Informationen benötigt werden, um zu helfen, lassen Sie es mich wissen und wenn Sie mir helfen könnten, würde ich es wirklich schätzen!

In der Regel beantworten wir keine Implementierungsfragen zur Computerphysik, daher ist dies möglicherweise nicht der richtige Ort für die Frage, wie sie formuliert ist. Sie haben vielleicht mehr Glück bei scicomp.stackexchange.com, aber sie mögen die Code-Review-Aspekte dort vielleicht auch nicht.
Einige allgemeine Tipps: Für welche Zeitintegrationsmethode haben Sie sich entschieden und respektieren Sie die Stabilitätsgrenzen? Haben Sie überprüft, dass für jede Kraft auf einen Knoten eine gleiche und entgegengesetzte Kraft auf den anderen Knoten wirkt?

Antworten (1)

Ein paar Anmerkungen zu deiner Umsetzung:

  1. Sie initialisieren Ihre Verteilungsfunktionen auf unkonventionelle Weise; Normalerweise wollen wir bekannte makroskopische 'Gitter'-Größen wie konvertieren ρ Und u hinein F ich . Eine einfache Möglichkeit, dies zu tun, ist die Verwendung der oben definierten Gleichgewichtsverteilung:

    F ich , e Q ( ρ , u ) = w ich ρ [ 1 + e ich u C S 2 + 1 2 ( e ich e ich C S 2 ICH ) : u u C S 4 ]

    Machen wir unser Leben einfach und wählen wir ρ = 1 Und u = 0 dann einfach initialisieren mit:

    F ich = F ich , e Q ( 1 , 0 ) = w ich

    Notiz:

    • Im „Gitter“-System kann der Wert der makroskopischen Größen (mehr oder weniger) beliebig gewählt werden, um unseren Bedürfnissen gerecht zu werden, solange die relevanten dimensionslosen Zahlen (z. B. die Reynolds-Zahl) im „dimensionalen“ System äquivalent sind.
    • Achten Sie darauf, dass die Geschwindigkeit klein genug gewählt wird, um die Machzahl sicherzustellen M A = u / C S 1 ; normalerweise ist dies begrenzt auf u 0,1 . Das liegt am Kleinen M A Erweiterungsform der Gleichgewichtsverteilung, die zu ist Ö ( M A 2 ) Bedingungen. Meine Vermutung ist, dass Ihr Code aufgrund der gewählten Werte abweicht F ich in der Initialisierung entsprechen einer viel zu hohen Geschwindigkeit.
    • Für anfänglich transiente Strömungen ist diese Initialisierungsmethode nicht die beste Methode, aber für u ( X , 0 ) = 0 es ist in Ordnung.
  2. Ihre Implementierung des Kollisionsschritts sieht korrekt aus, aber Ihre Entspannungsfrequenz ω = 0,005 kommt mir sehr klein vor (zB τ = 200 ). Wahrscheinlich funktioniert dies gut, aber beginnen Sie mit ω = 1 Erstens, weil dies der stabilste Wert ist (das bedeutet, dass wir uns in einem „Gitter“-Zeitschritt in Richtung der Gleichgewichtsverteilung entspannen). Eine kleine Anmerkung: var uu = u.dot(u);kann außerhalb der Schleife genommen werden, da sie nicht von abhängt i.

  3. Ich bezweifle, dass der Code ohne eine Implementierung für den Streaming-Schritt funktionieren wird. Wenn Sie wie oben mit der Gleichgewichtsverteilung initialisieren, wird die Verteilung nach dem ersten Zeitschritt F ich ( X , T + 1 ) = F ich ( X , T ) und bleibt so für alle nachfolgenden Zeitschritte. Dies ist eigentlich eine gute Überprüfung, um zu sehen, ob der Kollisionsschritt korrekt implementiert wurde.

  4. Ich spüre, dass Sie kürzlich begonnen haben, mit LBM zu arbeiten, also lassen Sie mich Ihnen etwas Literatur geben, die sich mit den numerischen Aspekten befasst:

    • Gitter-Boltzmann-Modellierung: Eine Einführung für Geowissenschaftler und Ingenieure, von MC Sukop und DT Thorne
    • Gitter-Boltzmann-Methode: Grundlagen und technische Anwendungen mit Computercodes, von AA Mohamad
    • Die Gitter-Boltzmann-Gleichung für die Fluiddynamik und darüber hinaus, von S. Succi

Viel Glück