-
OpenFOAM
-
OpenFOAM ist eine C++ basierte Open Source Library für die Analyse von Problemen der Struktur- und Strömungsmechanik.
- Ansprechpartner:
Einführung in OpenFOAM
OpenFOAM (Open Source Field Operation and Manipulation) ist eine Open Source CFD Toolbox, bestehend aus C++ Libraries und Executables oder auch als Applications bezeichnet. Eine genauere Beschreibung findet man in der Dokumentation.
Das Modell ist in einem sog. Case-Verzeichnis abgelegt, welches aus weiteren Unterverzeichnissen und Dateien besteht und in dem u.a. die Netz- und Modellbeschreibungen durch sog. Dictionaries festgelegt sind. DieNetze können sowohl direkt per Editor im blockMeshDict, dem Blockmesh Directory, eingegeben werden, es gibt aber auch eine Reihe von Konvertierungsprogrammen, die aus den Meshformaten anderer kommerzieller Programme OpenFOAM-Formate erzeugen können, so u.a.
- aus Fluent .msh-Files
- aus STAR-CD/ProStar Meshfiles
- aus Gambit .neu-File
Die Prä/Postprozessoren HyperMesh und ANSYS ICEM_CFD selbst können direkt Netze für OpenFOAM erzeugen.
Der Standardpostprozessor für OpenFOAM ist Paraview. Aber es gibt auch Tools, mit denen die Ergebnisse in
- ein Fluent-Format
- ein Fieldview-Format
- ein EnSight-Format
konvertiert werden können. Außerdem kann auch ein VTK-Format erzeugt werden, welches wiederum mit Paraview dargestellt werden kann.
Es gibt eine Menge an Standard Solvern für alle möglichen Strömungsmodelle, wie
- inkompressibel, kompressibel
- Multiphasenströmung
- Direct Numerical Simulation (DNS)
- Wärmeausbreitung und Auftriebsströmung
- Teilchentransport
- Molekulardynamische Methoden
- Monte-Carlo-Methoden
- Elektrostatik und magnetohydrodynmische Strömungen
- Spannungs-Dehnungs-Analyse von Festkörpern
- Black-Scholes-Gleichung im Finanzbereich
und viele Turbulenzmodelle, die hier nicht im Einzelnen aufgezählt werden sollen.
OpenFOAM ist im SCC auf dem bwUniCluster installiert. Die parallele Bearbeitung lässt sich sehr einfach durchführen, in dem das Netz partitioniert wird. Für jeden Prozessor wird ein eigenes Verzeichnis angelegt, in dem die Ergebnisse der bearbeiteten Domäne geschrieben werden. Anschließend werden die Ergebnisse aus den Partitionen wieder zusammengeführt.
Kurzanleitung
Einleitung
Steuerung
Geometrie und Vernetzung
Anfangs- und Randbedinungen
Physikalische Eigenschaften
Diskretisierung und Solver
Start des Solvers
Postprozessing
Parallelverarbeitung
Dokumentation
Einleitung
Am Beispiel eines kleines Problems, Lid-Driven Cavity Flow, also die Strömung in einem Kasten bei einer vorgegeben Geschwindigkeit an der Deckfläche, soll das Prinzip von OpenFOAM vorgestellt werden. In OpenFOAM wird grundsätzlich in dreidimensionaler Geometrie gerechnet. Wenn ein Problem als zweidimensionales Modell gerechnet werden soll, sollte eine Elementschicht als Dicke in die dritte Richtung erzeugt und an den Begrenzungsflächen entsprechende Randbedingungen gesetzt werden (s.u.)
Zunächst muss eine neue case Struktur angelegt werden.
wobei für case ein Name stehen kann, in dieser Demonstration z.B. cavity. Die Case-Struktur besteht aus drei Unterverzeichnissen
system enthält |
controlDict |
in dem Anfangs-/Endzeitpunkt und Zeitschritte bzw. Ein-/Ausgabeintervalle für die Ergebnisse festgelegt werden |
fvSchemes | in dem die Differentialgleichungen formuliert werden | |
fvSolution | in dem der Solver spezifiziert wird. | |
constant enthält | polyMesh | in dem die Geometrie und die Boundaries beschrieben sind |
Properties | das sind Dictionaries in dem die physikalische Eigenschaften beschrieben werden | |
Time Directories | 0, ... | Das Verzeichnis 0 enthält die Anfangsbedingungen zur Startzeit (=0). Im controlDict wird als Zeitinkrement deltaT festgelegt und ein writeInterval, so dass alle deltaT*writeInterval Zeiteinheiten, die Ergebnisse in ein neues Verzeichnis herausgeschrieben werden. |
Dazu kommen ggf. noch weitere Verzeichnisse und Dateien.
Steuerung
Zunächst wird das OpenFOAM Environment erzeugt. Auf dem bwUniCluster gibt man
source $FOAM_INIT
(oder einfach: foamInit)
ein.
Über die Steuerung wird die Start- und Endzeit und Zeitschrittweite, sowie das Ausgabeintervall für die Ergebnisse festgelegt. Dazu wird ein controlDict im Unterverzeichnis system mit dem folgenden Inhalt angelegt:
FoamFile application icoFoam; |
Die meisten Parameter sind selbsterklärend, ansonsten findet man eine genauere Beschreibung im OpenFOAM User's Guide.
Geometrie und Vernetzung
Die einfache Geometrie erlaubt es, ein strukturiertes Netz zu erzeugen. Dazu gibt es das blockMesh Tool. Bei komplizierteren Geometrien können unstrukturierte Netze mit anderen Präprozessoren wie z.B. HyperMesh oder ANSYS ICEM_CFD generiert werden.
Es wird ein blockMeshDict in das polyMesh Unterverzeichnis gelegt. Hierin ist die Geometrie und das Netz beschrieben, sowie auch die Randflächen.
FoamFile convertToMeters 0.1; vertices blocks edges patches ( mergePatchPairs |
Header
alle Längeneinheiten werden mit 0.1 multpliziert
Definitionen von Ränder für spätere Randbedingungen |
Basierend hierauf wird das Netz erzeugt, in dem man
blockMesh -case <Pfad>/cavity
eingibt bzw. wenn man im cavity Unterverzeichnis ist, reicht die Eingabe von
blockMesh
aus.
Anfangs- und Randbedingungen
Die Randbedingungen für die Geschwindigkeit U und dem Druck p werden in den beiden Dateien U und p im Unterverzeichnis 0 festgelegt.
FoamFile dimensions [0 1 -1 0 0 0 0]; fixedWalls frontAndBack |
FoamFile dimensions [0 2 -2 0 0 0 0]; internalField uniform 0; boundaryField fixedWalls fixedWalls frontAndBack |
Im Header steht der Name und Typ der Variable (Skalar oder Vektor). Die Dimensionszuweisung erfolgt nach dem folgenden Schema:
die Vektorpositionen stehen für die SI-Einheiten
[kg m s K mol A cd]
und die Zahlen bedeuten die Potenzen dieser Einheiten, aus der sich die gesamte Einheit zusammensetzt. Für die Geschwindigkeit in m/sec ist dann der Vektor [0 1 -1 0 0 0 0], für den (kinematischen) Druck m2/sec2 entsprechend [0 2 -2 0 0 0 0].
Im Inneren des Kastens sind beide Felder Null, auf den Randflächen ist die Geschwindigkeit 0 bzw. hat auf dem Deckel die Komponenten (1 0 0), der Druck hat den Wert "zeroGradient", was bedeutet, dass die Normalenkomponente des Druckgradienten dort verschwindet. Aus den Seitenflächen "frontAndBack"sind keine Randbedingungen vorgegeben.
Physikalische Eigenschaften
Als physikalische Eigenschaften sind bei inkompressibler laminarer Strömung newtonscher Fluide nur die kinematische Viskosität anzugeben und diese wird über die Datei transportProperties im Verzeichnis constant festgelegt:
FoamFile nu nu [ 0 2 -1 0 0 0 0 ] 0.01; |
nu hat den Wert 0.01 m2/s.
Diskretisierung und Solver
Die Diskretisierung der Differentialgleichungen werden in der Datei fvSchemes und die Solverparameter werden in der Datei fvSolution festgelegt, die im Unterverzeichnis system liegen. Einzelheiten dazu findet man ebenfalls im User's Guide.
FoamFile ddtSchemes gradSchemes divSchemes laplacianSchemes interpolationSchemes interpolate(HbyA) linear; snGradSchemes fluxRequired |
FoamFile solvers U preconditioner DILU; PISO |
Start des Solvers
Der Job kann auf interaktive Weise gestartet werden und auch im Batch. Am einfachsten ruft man den Solver direkt auf. In unserem Beispiel ist es der der icoFoam Solver:
icoFoam -case <Pfad>/cavity
oder wenn man sich im Verzeichnis cavity befindet, reicht auch einfach die Eingabe von
icoFoam.
Auf dem bwUniCluster (s. auch Wiki.bwhpc.de: OpenFoam) ist ein Startskript anzulegen, um den Job an das Job Management Systems zu senden. Hier ein Beispiel "openfoam.sh":
#!/bin/bash -l
#SBATCH --nodes=1
#SBATCH --ntasks-per-node=1
#SBATCH --partition=single
#SBATCH --time=0:10:00
#SBATCH --mem=6gb
module load cae/openfoam/v2212
foamInit
blockMesh
icoFoam
Das Startskript wird wie folgt submittiert:
sbatch openfoam.sh
Bei paralleler Abarbeitung muss vorher das Gitter partitioniert werden (s.u.).
Postprocessing
Als Ergebnis erhält man zunächst eine Anzahl an Verzeichnissen, die nach dem Ausgabezeitpunkt benannt sind, so, wie es oben bei den Time Directories der case Struktur beschrieben ist. In unserem Beispiel sind das die Verzeichnisse 0, 0.1, 0.2, .....,0.5 in denen die Ergebnisse zu diesen Zeitpunken stehen.
Der Standardpostprozessor ist Paraview, der in OpenFOAM eingebettet ist. Dazu gibt man im case Unterverzeichnis einfach das Kommando
paraFoam
ein und wählt als Reader OpenFOAM. Genaueres dazu findet man im OpenFOAM User Guide.
Man kann auch Paraview als eigenständigen Postprozessor mit
paraview
aufrufen und eine Fülle an anderen Formaten einlesen, z.B. VTK, EnSight, FLUENT u.v.m.
OpenFOAM selbst bietet einige Konvertierer an, die diese Formate erzeugen. Dazu werden im Unterverzeichnis cavity die verschiedene Datenkonvertierer aufrufen, die die Eingabedaten für verschiedene andere Postprozessoren erzeugen:
- foamDataToFluent
- foamToVTK
- foamToEnsight
- u.a.
Zum Beispiel wird ein VTK Format erzeugt, in dem man
foamToVTK
aufruft, worauf ein Unterverzeichnis VTK erzeugt wird, in dem die Dateien cavity_0.vtk, cavity_20.vtk, ... cavity_100.vtk stehen. Die Zahlen bedeuten hier nicht das Ergebnis zu Zeitpunkten, sondern nach der Anzahl der Zeitschritte. Der Umgang mit Paraview wird im ParaFOAM User's Guide, ParaView Tutorial und anderen Dokumentationen beschrieben.
Auf analoge Weise werden auch Formate für EnSight, FLUENT u.a. erzeugt.
Mit foamCalc können aus den aus den Ergebnissen weitere, abgeleitete Größen berechnet werden. Ein weiteres nützliches Werkzeug ist die sample Bibliothek. Damit lassen sich Daten entlang einer Linie oder auf einer Fläche sammeln und in ein Format ausgeben, das es erlaubt, sie mit Plotprogrammen wie gnuplot, Matlab o.a. grafisch darzustellen. Voraussetzung ist, dass ein sampleDict im system Unterverzeichnis angelegt wird. Ein Beispiel ist
FoamFile setFormat raw; sets start (0.02 0.051 0.005); surfaces (); fields (U.component(1)); |
Hier wird entlang einer Linie mit den Endpunkten (0.02 0.051 0.005) und (0.06 0.051 0.005) an 10 Punkten die y-Komponente der Geschwindigkeit ausgewertet. Es wird ein Unterverzeichnis sets angelegt und die Werte für den XY-Plot in die Unterverzeichnisse 0, 0.1 , ... , 0.5 gelegt. Ein Flächenplot wird nicht angefordert.
Parallelverarbeitung
Zunächst muss das Rechengebiet in Domänen zerlegt werden. Dazu wird wieder ein Dictionary decomposeParDict in das Unterverzeichnis system gelegt. Mit dem Aufruf
decomposePar
erfolgt dann die Partitionierung. Ein Beispiel für eine Zerlegung in 8 Domänen ist die folgende Datei:
FoamFile numberOfSubdomains 8; method simple; simpleCoeffs hierarchicalCoeffs metisCoeffs manualCoeffs distributed no; roots ( ); |
Bei der Methode simple wird die Zelegung durch die Anzahl der Partitionen in jede Richtung durch das Tripel n=(nx,ny,nz) gegeben. Zu den verschiedenen Methoden und die Bedeutung der jeweiligen Koeffizienten methodeCoeffs findet man weitere Informationen im User's Guide.
Nach der Zerlegung kann die Berechnung auf dem bwUniCluster wie auf der Webseite Wiki.bwhpc.de OpenFoam beschrieben gestartet werden.
Läuft die Berechnung an, werden im case 8 Unterverzeichnisse processor0, .... , processor7 angelegt, jeweils mit den Ergebnisse einer Domäne zu den oben beschriebenen Zeitpunkten. Mit dem Aufruf
reconstructPar
werden die Ergebnisse der einzelnen Domänen wieder zusammengeführt.
Die Zeile
distributed no;
in decomposeParDict besagt, dass von allen Prozessoren auf dasselbe Filesystem zugegriffen wird. Das kann bei großen Problemen und auch bei hohem Parallelisierungsgrad zu Performanceverlusten führen. Es ist in diesen Fällen besser, jeder Prozessor schreibt seine Daten auf ein lokales Filessystem. Dazu ändert man die Zeile in
distributed yes;
Zusätzlich müssen in decomposeParDict weitere Informationen stehen, die aber erst zur Laufzeit des Jobs bekannt sind, die Namen der temporären lokalen Verzeichnisse.
Folgender Link führt zur Online-Dokumentation von OpenFOAM: https://www.openfoam.com/documentation/