C++ basierte Open Source Library für die Analyse von Problemen der Struktur- und Strömungsmechanik
aktuelle Version: 2.0.1
C++ basierte Open Source Library für die Analyse von Problemen der Struktur- und Strömungsmechanik aktuelle Version: 2.0.1 |
|||
| Ansprechpartner: | Ngan Long Tu | Dienste: | CAE-Anwendungen |
|---|---|---|---|
| Links: | OpenFOAM PageKitware PageSourceForge PageParaView Page | ||

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.
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
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
und viele Turbulenzmodelle, die hier nicht im Einzelnen aufgezählt werden sollen.
OpenFOAM ist im SCC auf dem KIT-Cluster HP XC3000 (HC3) installiert. Hier kann auch Paraview aufgerufen werden. 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.
Wíchtig: Das Beispiel beschreibt die Vorgehensweise am KIT-Cluster HC3.

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.
Zunächst wird das OpenFOAM Environment erzeugt. Dazu gibt man
. set_OF
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.
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.
|
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.
|
FoamFile nu nu [ 0 2 -1 0 0 0 0 ] 0.01; |
nu hat den Wert 0.01 m2/s.
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 |
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.
Etwas komfortabler ist der Aufruf
foamJob icoFoam
hier wird automatisch ein Log-File log angelegt, in dem man den Iterationsverlauf und die Residuen beobachten kann. Gibt man danach noch
foamLog log
wird, ein Unterverzeichnis logs angelegt, in dem der zeitliche Verlauf der einzelnen Residuen und globalen Größen getrennt in Dateien gespeichert wird. Diese können dann als xy-Plots angezeigt werden (mit gnuplot, Matlab o.a.).
Auf dem Cluster sollten nach Möglichkeit Jobs, die große Ressourcenanforderungen haben, nicht im Vordergrund gestartet werden, sondern über das Job Mangement System (JMS). Es gibt einen Submit-Mechanismus, der den Job in eine Warteschlange einreiht und die angeforderte Anzahl an Knoten samt nötigem Hauptspeicher reserviert:
job_submit -c p -p n -t time -m memory "foamJob -p icoFoam"
Die einzelnen Parameter von job_submit werden beschrieben, wenn man
job_submit -H
aufruft. Mit job_submit wird das Kommando foamJob -p icoFoam abgeschickt. Die Option -p bedeutet, dass der Job parallelisiert berechnet werden soll. Die Anzahl der parallelen Prozessoren werden durch den Parameter "-p n" im job_submit festgelegt. Bei serieller Abarbeitung fällt die -p Option weg und in job_submit steht "-p 1".
job_submit -c p -p 1 -t time -m memory "foamJob icoFoam"
Bei paralleler Abarbeitung muss vorher das Gitter partitioniert werden (s.u.).
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:
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.
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 16 Domänen ist die folgende Datei:
|
FoamFile numberOfSubdomains 16; 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 erfolgt der Aufruf:
job_submit -c p -p 16 -t 100 -m 6000 "foamJob -p icoFoam"
Im case werden 16 Unterverzeichnisse processor0, .... , processor15 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 der temporären lokalen Verzeichnisse. Am Besten erzeugt man sich eine Datei z.B. name_JOB mit folgendem Inhalt:
. set_OF
set_roots
foamJob -p icoFoam
reconstructParDis
und startet den Job aus dem case-Verzeichnis heraus mit z.B.
job_submit -c p -p 8 -t 100 -m 2000 name_JOB
set_roots ist ein Shellscript, das die temporäten lokalen Verzeichnisse anlegt, ein decomposePar ausführt und anschließend die Unterverzeichnisse processor0, ... ,processor7 in die lokalen Verzeichnisse kopiert. reconstrucParDis kopiert die Verzeichnisse processor0, ... ,processor7 nach erfolgter Berechnung wieder in das lokale Filesystem. Da ein lokales Filesystem nur einem Knoten bekannt ist, funktioniert das Ganze auch nur, wenn die Parallelisierung nicht über mehrere Knoten verteilt ist. Das bedeutet
Die folgenden Links führen zu den Handbüchern und Tutorien:
Viele weitere Referenzen findet man unter www.pdfbe.com/op/openfoam-book.pdf.