Reading Time: 8 minutes

Schlüssel zum Mitnehmen

  • Periodische Grenzen in FIPY werden am saubersten mit PeriodicGrid -Objekten oder periodischen GMSH-Befehlen anstelle der manuellen Gesichtskopplung implementiert.
  • Symmetrische Grenzen sind Null-Fluss-Neumann-Bedingungen, die auf Symmetrieebenen angewendet werden. Sie sind keine separate FIPY-Kategorie, sondern eine physikalische Verwendung von Standard-Randbedingungsmustern.
  • Robin-Grenzen kombinieren Wert- und Flussbeschränkungen. Sie können mit ImplicitRobinSource, ImplicitSourceTerm oder einem FaceVariable Divergenz-Ansatz implementiert werden.
  • Die gängigsten Robin-Grenzflächen sind Vorzeichenfehler aus falschen Flussrichtungskonventionen und variablen Aliasing, wenn mehrere Python-Namen auf das gleiche FaceVariable-Objekt verweisen.
  • Verwenden Sie für zeitabhängige periodische Grenzen bedingte Ausdrücke wie t % 10 anstelle von Python-Funktionen. Python-Funktionen werden nicht automatisch neu bewertet, wenn sich die Simulationszeitvariable ändert.

Wenn Sie grundlegende FIPY-Tutorials durchgearbeitet haben, wissen Sie bereits, dass die Randbedingungen die Theorie der Kanten des Netzes sind. Dirichlet, Neumann, Robin und periodische Grenzen mögen theoretisch einfach aussehen, aber Implementierungsdetails sind in realen Simulationen wichtig.

Dieser Artikel behandelt fortgeschrittene FIPY-Muster für periodische Domänen, Symmetrieebenen und Robin-Grenzen. Diese sind in Einheitszellenmodellen, achsensymmetrischen Problemen, konvektiven Wärmeübertragungen und Massenaustauschsimulationen üblich.

Die folgenden Beispiele zeigen, wie jeder Grenztyp korrekt implementiert wird, wie man zwischen Ansätzen wählt und wie man stille Fehler vermeidet, die stundenlanges Debuggen verschwenden können.

Periodische Randbedingungen: Kopplung der Kanten

Periodische Grenzen kleben gegenüberliegende Seiten der Domäne zusammen. Auf der gegenüberliegenden Seite taucht wieder eine Lösung auf. Dieses Muster ist in Einheitszellensimulationen, repräsentativen Volumenelementen, Materialwissenschaften und vereinfachten Transportmodellen üblich, bei denen sich die reale Domäne wiederholt.

Der einfache Ansatz: PeriodicGrid-Objekte

FIPY bietet integrierte periodische Rasterobjekte, die die Gesichtskopplung automatisch handhaben. Für 1D-Domains ist das Setup einfach:

from fipy import PeriodicGrid1D, CellVariable, DiffusionTerm, TransientTerm

nx = 50
dx = 1.0
mesh = PeriodicGrid1D(nx=nx, dx=dx)

C = CellVariable(name="concentration", mesh=mesh, value=0.0)

# No explicit boundary condition needed.
# FiPy handles periodic coupling through the mesh.
eq = TransientTerm() == DiffusionTerm(coeff=1.0)

# Initialize with a non-uniform perturbation.
x = mesh.cellCenters[0]
C.setValue(1.0, where=(x > 0.7) & (x < 0.8))

eq.sweep(var=C)

Für 2D-Domänen bietet FIPY PeriodicGrid2D und orientierte Varianten:

from fipy import PeriodicGrid2D, CellVariable, DiffusionTerm

nx, ny = 50, 50
dx = dy = 1.0

# Periodic on all sides
mesh = PeriodicGrid2D(nx=nx, ny=ny, dx=dx, dy=dy)

# Oriented variants can be used when needed:
# PeriodicGrid2DLeftRight: periodic only in x
# PeriodicGrid2DTopBottom: periodic only in y

Die orientierten Varianten sind nützlich, wenn Sie Periodizität in eine Richtung, aber unterschiedliche Randbedingungen in der anderen Richtung benötigen. Zum Beispiel kann ein Transportproblem periodischen Zu- und Abfluss in eine Richtung und keine Flusswände in der anderen erfordern.

Komplexe Geometrien: GMSH Periodische Netze

Wenn es sich bei der Domäne nicht um eine einfache Linie oder ein Rechteck handelt, verwenden Sie GMSH, um periodische Beziehungen auf Mesh-Ebene zu definieren. Die wichtigen Befehle sind Periodic Line und Periodic Surface.

// In a Gmsh .geo file
Periodic Line {1} = {2} + 10;
Periodic Surface {3} = {4};

Importieren Sie dann das Netz in Python:

from fipy import GmshImporter2D

mesh = GmshImporter2D("mesh.geo")

Der Vorteil ist, dass die periodische Kopplung im Netz definiert ist, nicht manuell im Solver. Dies ist robuster für willkürliche Geometrien, da der Solver mit einem Netz arbeitet, das bereits die periodischen Beziehungen enthält.

Manuelle Gesichtskopplung: Wenn Sie Kontrolle benötigen

Für benutzerdefinierte Fälle möchten Sie möglicherweise Gesichter manuell zuordnen und Einschränkungen anwenden. Dies gibt volle Kontrolle, erfordert jedoch eine sorgfältige Gesichtsindizierung.

from fipy import CellVariable, Grid1D

nx = 50
dx = 1.0
mesh = Grid1D(nx=nx, dx=dx)

C = CellVariable(mesh=mesh, value=0.0)

left_faces = mesh.facesLeft
right_faces = mesh.facesRight

# Manual periodic-style coupling
C.constrain(C.faceValue[mesh.facesLeft.value], where=mesh.facesRight)

Die manuelle Kopplung ist fragiler als die Verwendung von PeriodicGrid. Bevorzugen Sie integrierte periodische Netze, es sei denn, Sie benötigen Verhalten, das sie nicht bereitstellen können.

Zeitabhängige periodische Grenzen

Zeitabhängige periodische Grenzen können schwierig sein. Ein häufiger Fehler besteht darin, eine Python-Funktion zu definieren und zu erwarten, dass FIPY sie automatisch neu bewertet:

# Wrong: this evaluates once and then stays fixed
def sw_func(t):
    if t < 5:
        return 0.0
    elif t < 10:
        return 1.0
    else:
        return sw_func(t - 10)

valueRight = sw_func(t)

Das Funktionsergebnis wird einmal ausgewertet. Wenn sich t ändert, wird der Grenzwert nicht automatisch aktualisiert.

Verwenden Sie stattdessen bedingte Ausdrücke und FIPY-kompatible Variablen:

# Correct pattern: expression can re-evaluate as t changes
t_mod = t % 10
valueRight = ((t_mod >= 5) & (t_mod < 10)) * 1.0

C.constrain(valueRight, where=mesh.facesRight)

Der entscheidende Punkt ist, dass sich FIPY-Variablen wie symbolische Ausdrücke verhalten. Erstellen Sie zeitabhängige Bedingungen mit FIPY-kompatiblen Ausdrücken, logischen Masken und Array-Operationen anstelle von Python if -Anweisungen.

Wenn periodische Grenzen lautlos versagen

Ein häufiger stiller Fehler ist die Verwendung einer einheitlichen Anfangsbedingung für eine periodische Domäne:

C = CellVariable(mesh=mesh, value=1.0)

eq = TransientTerm() == DiffusionTerm(coeff=1.0)
eq.solve(var=C, dt=0.1)

Das Ergebnis ändert sich nie, da das Feld keinen Gradienten hat. Periodische Grenzen erzeugen keine Steigungen für sich.

Initialisieren Sie immer periodische Domänen mit einer ungleichmäßigen Bedingung, z. B. einer Störung, einer Schrittfunktion oder einem Gaußschen Blob.

Symmetrische Randbedingungen: Nullfluss auf Symmetrieebenen

Symmetrische Grenzen nutzen die Symmetrie aus, sodass Sie nur einen Teil der Domäne simulieren können. Dies ist bei axialsymmetrischen Wärmeübertragungen, kristallographischen Modellen und Flüssen mit Symmetrieebenen üblich.

In FIPY werden symmetrische Grenzen als Null-Fluss-Neumann-Bedingungen auf der Symmetrieebene implementiert.

from fipy import Grid2D, CellVariable, DiffusionTerm, TransientTerm

nx, ny = 50, 25
dx = dy = 0.1

mesh = Grid2D(nx=nx, ny=ny, dx=dx, dy=dy)

T = CellVariable(name="temperature", mesh=mesh, value=100.0)

# Symmetry plane at the top: zero flux
T.faceGrad.constrain(0.0, where=mesh.facesTop)

# Bottom boundary: fixed temperature
T.constrain(100.0, where=mesh.facesBottom)

# Left and right: insulated
T.faceGrad.constrain(0.0, where=mesh.facesLeft)
T.faceGrad.constrain(0.0, where=mesh.facesRight)

eq = TransientTerm() == DiffusionTerm(coeff=1.0)

Die physikalische Bedeutung ist, dass Wärme oder Masse nicht die Symmetrieebene überquert, da die weggelassene Hälfte der Domäne die simulierte Hälfte widerspiegelt.

Achssymmetrische Zylinderkoordinaten

Achssymmetrische Probleme erfordern zusätzliche Sorgfalt, da die radiale Koordinate den Diffusionsoperator ändert. In Zylinderkoordinaten enthält der radiale Diffusionsbegriff einen geometrischen Faktor:

(1/R) ∂(R ∂C/∂R) / ∂R

FIPY kann diese Art von Verhalten darstellen, aber der Aufbau erfordert eine sorgfältige Koeffizientenkonstruktion und das Netzdesign.

from fipy import CellVariable, FaceVariable, DiffusionTerm, TransientTerm

r = mesh.cellCenters[0]

# Example structure for a radial coefficient
axisymmetric_coeff = FaceVariable(mesh=mesh, value=1.0)

eq = TransientTerm() == DiffusionTerm(coeff=axisymmetric_coeff)

Die Achse bei r = 0 ist aufgrund des 1/r-Faktors singulär. Vermeiden Sie es, Zellzentren genau bei r = 0 zu platzieren. Starten Sie das Netz mit einem kleinen positiven Radius, verwenden Sie zellzentrierte Radialkoordinaten sorgfältig oder verwenden Sie ein Netzdesign, das die Singularität vermeidet.

Robin Randbedingungen: Mischwert-Fluss-Einschränkungen

Robin-Randbedingungen Geben Sie eine lineare Kombination der Variablen und ihrer normalen Ableitung an. Sie kombinieren eine Wertbeschränkung mit einer Flussbedingung.

Ein häufiges Beispiel ist das Newtonsche Kühlgesetz:

k ∂t/∂n + h(t – t∞) = 0

Dabei ist der Wärmefluss an der Grenze proportional zur Differenz zwischen der Oberflächentemperatur und der Umgebungstemperatur.

Der ImplicitrobinSource-Ansatz

ImplicitRobinSource ist oft der sauberste Ansatz für konvektive Wärmeübertragung und Massenaustausch.

import fipy as fp

nx = 50
dx = 1.0
mesh = fp.Grid1D(nx=nx, dx=dx)

T = fp.CellVariable(name="temperature", mesh=mesh, value=20.0)

# Physical parameters
k = 1.0
h = 0.5
T_inf = 10.0
T_left = 100.0

# Equation setup
eq = fp.TransientTerm() == fp.DiffusionTerm(coeff=k)

# Left boundary: fixed temperature
bc_left = fp.FixedValue(mesh.facesLeft, T_left)

# Right boundary: convective heat transfer
bc_right = fp.ImplicitRobinSource(
    mesh.facesRight,
    coeff=h,
    value=h * T_inf
)

dt = 0.1
for step in range(100):
    eq.solve(var=T, boundaryConditions=[bc_left, bc_right], dt=dt)

Der ImplicitRobinSource-Ansatz fügt einen impliziten Quellen- oder Senkenbeitrag zur Solver-Matrix hinzu. Dies kann insbesondere bei Wärmeaustausch- oder Stofftransferproblemen stabiler sein als die explizite Grenzbehandlung.

Der Facevariable Divergenz-Ansatz

Für räumlich variierende Koeffizienten oder gekoppelte Multi-Physik-Grenzen ergibt ein FaceVariable Divergenzansatz mehr Kontrolle.

from fipy import CellVariable, FaceVariable, Grid1D
from fipy import DiffusionTerm, ImplicitSourceTerm, TransientTerm

nx = 100
dx = 1.0
mesh = Grid1D(nx=nx, dx=dx)

C = CellVariable(mesh=mesh, value=0.0)

D_coeff = 2.0
h_coeff = 1.0
C_ambient = 0.5

# Step 1: define face coefficient
D_face = FaceVariable(mesh=mesh, value=D_coeff)

# Step 2: zero out coefficient at the boundary as a precaution
D_face[..., mesh.facesLeft.value] = 0.0

# Step 3: formulate Robin-like boundary contribution
robin_flux = (h_coeff * (C_ambient - C)).divergence

eq = (
    TransientTerm()
    == DiffusionTerm(coeff=D_face)
    + robin_flux
    - ImplicitSourceTerm(coeff=0.0)
)

Dieser Ansatz erfordert drei Details:

  1. Null den Diffusionskoeffizienten an der Zielgrenzfläche heraus.
  2. Formulieren Sie den Robin-Fluss als Divergenzquelle.
  3. Fügen Sie den Beitrag konsequent zur Gleichung hinzu.

Das Nullstellen des Grenzkoeffizienten wird oft als sichere Vorsichtsmaßnahme behandelt, da es verhindert, dass das Standardverhalten ohne Fluss mit dem benutzerdefinierten Robin-Beitrag in Konflikt steht.

Häufige Gefahren der Robin-Grenzen

Signieren Sie Fehler in Flussrichtung

Die Vorzeichenkonvention kann je nachdem, ob der Fluss als innen oder nach außen behandelt wird, umkehren.

# Wrong sign
RobinCoeff = maskSurfaces * D * n / (-dPf.dot(a) + b)

# Corrected sign pattern
RobinCoeff = maskSurfaces * D * n / (dPf.dot(a) + b)

Begrenzungsfälle überprüfen:

  • Wenn h → 0, sollte sich die Grenze wie ein Null-Fluss-Neumann verhalten.
  • Wenn h → ∞, sollte sich die Grenze wie ein Festwert-Dirichlet verhalten.

Variable Aliasing

Variable Aliasing tritt auf, wenn mehrere Python-Namen auf dasselbe FaceVariable-Objekt zeigen.

# Wrong: all names reference the same object
D = FaceVariable(mesh=mesh, value=0.9)
Gamma = D
b = D

Gamma.setValue(0.0, where=maskSurfaces)

Das Ändern von Gamma ändert auch D und b. Dies kann die Randbedingung stillschweigend durchbrechen.

Verwenden Sie stattdessen einen nicht mutierenden Ausdruck:

# Better: create a new masked expression
Gamma = D * ~maskSurfaces

Dadurch entsteht ein neuer Ausdruck, der D von der Begrenzung und Null an der Grenze entfernt ist, ohne das ursprüngliche Objekt zu mutieren.

Konvergenzprobleme

Robin-Grenzen können stationäre Lösungen instabil oder schwer konvergierend machen. Eine praktische Lösung besteht darin, die Zeitabhängigkeit auch für ein Problem einzuführen, das den stationären Zustand erreichen sollte. Die vorübergehende Evolution kann dem Solver helfen, die richtige Lösung schrittweise zu erreichen.

Räumlich variierende und Patch-basierte Grenzen

Randbedingungen können nur durch räumliche Masken auf ausgewählte Regionen angewendet werden. Dies ist nützlich, wenn verschiedene Teile derselben Grenze ein unterschiedliches physikalisches Verhalten aufweisen.

from fipy import Grid2D, CellVariable, DiffusionTerm

nx, ny = 80, 80
dx = dy = 0.1
mesh = Grid2D(nx=nx, ny=ny, dx=dx, dy=dy)

T = CellVariable(mesh=mesh, value=0.0)

X, Y = mesh.faceCenters

# Left half of the boundary
mask_left = X < 0.5 * nx * dx

# Fixed value on one patch
T.constrain(1.0, where=mesh.facesLeft & mask_left)

# Zero flux on the other patch
T.faceGrad.constrain(0.0, where=mesh.facesLeft & ~mask_left)

Dieser Patch-Grenzansatz ist wichtig für Probleme mit gemischten physikalischen Bedingungen, wie z. B. einer Wand, die teilweise beheizt und teilweise isoliert ist.

Was wir empfehlen: Wählen Sie den richtigen Ansatz

Periodische Grenzen

  1. Verwenden Sie PeriodicGrid für einfach strukturierte 1D-, 2D- oder 3D-Domänen.
  2. Verwenden Sie periodische GMSH-Meshes für komplexe Geometrien, da die Kopplung auf Netzebene robuster ist als die Einschränkungen für manuelle Flächen.
  3. Initialisieren Sie mit ungleichmäßigen Bedingungen, da einheitliche Werte bei reinen Diffusionsproblemen keine Evolution hervorrufen.
  4. Verwenden Sie bedingte Ausdrücke wie t % N für zeitabhängige periodische Grenzen, nicht Python-Funktionen.

Symmetrische Grenzen

  1. Wenden Sie auf der Symmetrieebene mit faceGrad.constrain(0.0) Null-Fluss-Neumann-Bedingungen an.
  2. Behandeln Sie bei axialsymmetrischen Problemen die Singularität r = 0 sorgfältig durch das Netzdesign.
  3. Überprüfen Sie die Symmetrie, indem Sie überprüfen, ob der Lösungsgradient in der Symmetrieebene Null ist.

Robin-Grenzen

  1. Verwenden Sie ImplicitRobinSource für konvektive Wärmeübertragung und Massenaustausch.
  2. Verwenden Sie den FaceVariable Divergenz-Ansatz für räumlich variierende Koeffizienten oder gekoppelte multiphysische Grenzen.
  3. Zero Out-Koeffizienten an der Grenzfläche als Vorsichtsmaßnahme bei der Verwendung von benutzerdefinierten Flussmittelformulierungen.
  4. Achten Sie auf Sign-Fehler und überprüfen Sie Einschränkungsfälle.
  5. Achten Sie auf variables Aliasing. Bevorzugen Sie maskierte Ausdrücke wie D * ~mask, anstatt gemeinsam genutzte Variablen mit setValue() zu mutieren.

Vergleich: Wann jeder Ansatz verwendet werden soll

Grenztyp Anwendungsfall Empfohlener FIPY-Ansatz Gemeinsame Falle
Periodisch, strukturiert Einheitszellen, RVES, Domänen wiederholen PeriodicGrid1D, PeriodicGrid2D oder PeriodicGrid3D Einheitliche Anfangsbedingung
Periodisch, komplex willkürliche Geometrien gmsh Periodic Befehle Mesh-Import- oder Pairing-Fehler
periodisch, zeitveränderlich Pulsierende Strömungen oder zyklische Bedingungen Bedingter Ausdruck wie t % N Python-Funktionen werden nicht neu bewertet
Symmetrisch Achssymmetrische Probleme oder Kristallsymmetrie faceGrad.constrain(0.0) r = 0 Singularität in Zylinderkoordinaten
Robin, konvektiv Wärmeübertragung oder Massenaustausch ImplicitRobinSource Signieren Sie Fehler in Flussrichtung
Robin, komplex räumlich variierende Koeffizienten oder Multiphysik-Kopplung FaceVariable plus Divergenz Variable Aliasing- und Konvergenzprobleme

Fehlerbehebung: Fehler bei allgemeinen Randbedingungen

Die Lösung ändert sich nicht

Wenn eine periodische Domäne überall denselben Wert erzeugt, überprüfen Sie die Anfangsbedingung. Eine einheitliche Anfangsbedingung hat keinen Gradienten, so dass sich reine Diffusion nicht weiterentwickeln muss.

Der Grenzwert ist falsch

Überprüfen Sie für Robin-Grenzen:

  • Das Zeichen der Flussrichtung.
  • ob Sie Gesichter und nicht Zellen einschränken.
  • ob der Diffusionskoeffizient an der Grenze in benutzerdefinierten Formulierungen auf Null gesetzt wurde.

Der Solver divergiert

Versuchen Sie für Robin-Grenzen:

  • Reduzieren von dt und Erhöhung der Auflösung.
  • Hinzufügen einer vorübergehenden Evolution auch für Probleme, die den stationären Zustand erreichen sollen.
  • Verwenden von PETSC-Solvern anstelle von einfachen Sweeps für komplexe Begrenzungseinstellungen.

Die Grenze wird nicht aktualisiert

Für zeitabhängige periodische Grenzen ist die wahrscheinliche Ursache eine Python-Funktion, die anstelle einer FIPY-Expression verwendet wird. Verwenden Sie Variable-Objekte und logische Masken anstelle von if und elif-Anweisungen.

Schlussfolgerung

Bei periodischen, symmetrischen und robinischen Randbedingungen trifft die Theorie von Fipy auf die Kanten des Netzes. Periodische Gitter greifen die Gesichtskopplung automatisch an. Symmetrieebenen sind Null-Fluss-Neumann-Bedingungen. Robin-Grenzen kombinieren Wert- und Flussbeschränkungen durch ImplicitRobinSource oder einen FaceVariable Divergenzansatz.

Die wichtigste Gewohnheit ist die Überprüfung von Einschränkungen. Überprüfen Sie für Robin-Grenzen, dass h → 0 kein Flussverhalten und h → ∞ ein Verhalten mit festem Wert gibt. Stellen Sie bei periodischen Domänen sicher, dass die Anfangsbedingung nicht einheitlich ist. Bestätigen Sie für symmetrische Grenzen, dass der Gradient an der Symmetrieebene Null ist.

Diese Überprüfungen fangen die meisten Randbedingungsfehler ab, bevor sie zu langen Debug-Sitzungen werden.

Verwandte Anleitungen

Nächste Schritte

  1. Beginnen Sie mit PeriodicGrid1D für eine einfache periodische 1D-Domäne.
  2. Fügen Sie Zeitabhängigkeit mit bedingten Ausdrücken wie t % N hinzu.
  3. Beginnen Sie für Robin-Grenzen mit ImplicitRobinSource und überprüfen Sie Grenzfälle.
  4. Wechseln Sie zu GMSH-Meshes für komplexe Geometrien, sobald strukturierte Fälle funktionieren.

Hilfe bei der Implementierung von Randbedingungen in bestimmten Forschungsmodellen, besuchen Sie unsere Homepage , um die Beratungsressourcen und die FIPY-Entwicklungsunterstützung zu unterstützen.