Was sind einige gute Datentypen für unstrukturierten zellzentrierten FVM-CFD-Code?


12

Ich bin an einem Rat für effiziente Datenstrukturen für das Durchsuchen von Zellen in unstrukturierter zellbasierter CFD mit endlichem Volumen interessiert.

Ein Beispiel, auf das ich gestoßen bin (in dolfyn cfd code), sieht folgendermaßen aus (ich zeige das relevante Segment) Wir haben also ein Array NFaces, in dem die Anzahl der Gesichter für jede Zelle gespeichert ist. Dann CFace-Array, das die zellenlokale Gesichtsnummer der globalen Gesichtsnummer zuordnet.

\ begin {listing} do ip = 1, Ncel ... do j = 1, NFaces (ip) k = CFace (ip, j) ipp = Gesicht (k)% cell1 inn = Gesicht (k)% cell2 if (inn > 0) dann! intern \ end {Listing}

Der Code basiert auf dem Gesicht, daher gibt es einen Gesichtsdatentyp, der die Seriennummer von zwei Zellen speichert, die zwischen Gesicht (k)% Zelle1 und Gesicht (k)% Zelle2 liegen.

Kommentare hierzu oder Vorschläge für einen alternativen Ansatz sind willkommen.

Antworten:


9

Die Struktur, die Sie anzeigen, ist eine gängige Wahl und entspricht dem Speichern von Zell-Gesichts-Nachbarschaften in einem CSR-Matrixformat, wobei sich die Grenzgeisterzellen an einer bestimmten Stelle befinden. Es ist jedoch zu beachten, dass FV-Methoden auch so formuliert werden können, dass sie vollständig oder fast vollständig aus der Gesichtsdurchquerung bestehen, wobei jedes Gesicht nur einmal besucht wird (Rekonstruieren auf Flächenschwerpunkt / Quadraturpunkt von beiden Seiten, Lösen des Riemann-Problems, Zurückverteilen des Flusses in Reste auf Zellen) ). Sie können dies "vortäuschen", indem Sie Ihre zellenbasierte Durchquerung verwenden und zwei beliebige Zellen überspringen, die sich unterhalb der "Diagonale" in der dünnen Matrix befinden. Eine beliebte Alternative ist jedoch das Speichern(leftCell, rightCell) = support(face)In diesem Fall werden Gesichter zu erstklassigen Einheiten. Dies ist nützlich, da Sie in der Regel einen Ort zum Speichern von Flächenquadraturpunkten (Zentroiden) und Gesichtsnormalen benötigen. Sie können auch Rekonstruktionsteile (wie kleinste Quadrate) in die flächenbasierten Datenstrukturen einfügen. Die Gesichtsüberquerung ist anscheinend vektorisierungsfreundlich, da alle Größen regelmäßig sind. Andererseits gibt es überlappende Ausgaben, sodass Sie die Überquerung organisieren müssen, um zu vermeiden, dass sie in eine innere Schleife eingefügt wird. Bei dieser stärker flächenorientierten Datenstruktur ist es natürlich, die Flächennummern so zu ordnen, dass jeder Randbedingungstyp unter Verwendung einer zusammenhängenden Durchquerung von Flächen angewendet werden kann (auch vektorisierungsfreundlich).

Denken Sie bei Auswahl dieser Datenstruktur daran, die Flächen so zu sortieren, dass beim Durchlaufen die Zellendaten im Cache so weit wie möglich wiederverwendet werden. In einem der PETSc-FUN3D-Dokumente finden Sie eine Leistungsanalyse der Gesichtsbestellung und zugehörige Optimierungen.


Wenn Sie die Flächen in einer Schleife durchlaufen, müssen Sie Informationen von leftCell und rightCell abrufen, um die Flüsse zu berechnen, z . Wie wäre das vektorisierungsfreundlich?
Chris

Wie oben erwähnt (und in den Artikeln zu PETSc-FUN3D erläutert), weisen Sie die Gesichter an, den Cache wiederzuverwenden. Das Ergebnis ist wie ein "einseitiger" Zelldurchlauf, bei dem jedes Gesicht nur einmal besucht wird.
Jed Brown

3

Ich weiß, dass diese Frage bereits beantwortet wurde, aber hier ist ein ähnlicher einseitiger Schleifenspeicher, der in der OpenFOAM C ++ - Bibliothek implementiert ist:

Jede Zelle hat einen Index (ID) in einer Zellliste. Für alle Gesichter sind zwei Listen definiert: "Gesichtsinterner Eigentümer" und "Gesichtsnachbar". Die Länge beider Flächenlisten entspricht der Anzahl der internen Flächen im Netz. Ein Gesichtsbesitzer ist die Zelle mit der niedrigeren ID in der Zellliste (gegenüberliegend für Gesichtsnachbarn). Grenzflächen werden zuletzt geschrieben und haben nach außen gerichtete Normalen (aus dem Lösungsbereich) und natürlich nur eine Eigentümerzelle. Die Gesichtsbereichsnormale ist so ausgerichtet, dass sie von der Eigentümerzelle nach außen zur Nachbarzelle schaut.

Dies funktioniert zB gut für die Flussberechnung. Der Fluss wird einmal pro Fläche ausgewertet, und er wird zu der Summe der Gesamtflächen für die Eigentümerzellen addiert und von den Nachbarzellen abgezogen (die Summierung / Abzug wird auf der Grundlage der Ausrichtung der Gesichtsflächennormalen bestimmt). Die Grenzflächen werden sortiert und am Ende der Gesichtsliste gespeichert, so dass Grenzbedingungen als Slices der Gesichtsliste definiert werden können (Anfangsbeschriftung, Endbeschriftung des Grenzfelds), wodurch auch die Implementierung der Grenzbedingungen vereinfacht wird als Verbesserung der Effizienz des Aktualisierungsprozesses für die Randbedingungen, da er sich auf die Lösung stützt, die durch die Operationen an inneren Flächen bereitgestellt wird.

Da die Grenzflächen zu Patches agglomeriert sind, wird die Kommunikation zwischen Prozessen für gekoppelte (Prozessor-) Patches definiert und vordefiniert. Dies bedeutet, dass sobald sich eine Schleife über dem Grenzgitter befindet, die Zugriffsfunktionen der obersten Ebene umschlossene MPI-Aufrufe einschließen, wodurch dieser Code "automatisch" parallelisiert wird, wenn er auf der oben erläuterten flächenbasierten Konnektivität beruht.


Kein Problem, ich bin froh zu sehen, dass diese Beschreibung für jemanden nützlich ist. :) Arbeiten Sie auch mit OpenFOAM?
Tmaric

Früher ein bisschen früher. Ich neige im Allgemeinen dazu, akzeptierte Trends zu meiden und das Rad neu zu erfinden. Das ist mein Tao.
Johntra Volta

1
Dein Tao ist das Gegenteil des Tao der Informatik: "Erfinde das Rad nicht neu". Aber ich kann es verstehen, es ist ansprechend, Dinge von Grund auf neu zu machen! :)
tmaric
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.