OpenFOAM 14, parte 3: campi, condizioni iniziali e condizioni al contorno
Parte 3 di 8 della serie sulla costruzione del caso nel percorso Imparare OpenFOAM 14. La Parte 2 ha costruito con blockMesh il canale rettangolare trainingChannel e le sue patch inlet, outlet e walls; questa parte dà a quelle patch un significato fisico, scrivendo i campi 0/U e 0/p.
Dai patch della mesh al significato fisico. Il tema è come si scrivono e come si ragionano i campi 0/U e 0/p in OpenFOAM Foundation 14, come li si collega alle patch della mesh, come si diagnosticano gli errori di configurazione e come si verifica il risultato. Ogni riquadro «Approfondimento» espande un punto con la teoria, l’implementazione in v14, le alternative e i controlli pratici.
Come usare questa parte
Prerequisiti. Questa parte presuppone il flusso di lavoro CFD iniziale in sette passi, applicato nel primo caso pratico (flusso laminare in canale e validazione di Poiseuille), e le unità precedenti sulla struttura del caso (Parte 1) e sulla mesh (Parte 2).
Ambito. OpenFOAM Foundation 14. Come scrivere e ragionare sui campi 0/U e 0/p, collegarli alle patch della mesh, diagnosticare gli errori di configurazione e verificare il risultato.
Percorso attraverso questa parte
Percorso principale: fisica → file → corrispondenza con le patch → 0/U e 0/p completi → verifiche → esercizi. I riquadri «Richiamo facoltativo» contengono materiale di base e si possono saltare se si ha già dimestichezza con la CFD.
Caso di riferimento: canale rettangolare laminare 3D | Guida di riferimento: doc.cfd.direct/openfoam/user-guide-v14.
Patto di apprendimento
Questa unità non introduce un nuovo solutore. Insegna lo strato di configurazione che dà significato matematico a un dominio CFD già dotato di mesh. Alla fine dovresti essere in grado di scrivere i due file di campo senza copiare un intero tutorial.
Che cosa dovresti già avere
- Un ambiente shell OpenFOAM 14 funzionante;
foamVersiondeve identificare la versione 14. - La mesh del canale della Parte 2, preferibilmente una semplice mesh a blocco singolo.
- Una familiarità di base con la sintassi dei dizionari e con
blockMeshecheckMesh. - Una copia separata e modificabile del caso di addestramento, mai il caso originale/di riferimento.
Risultati attesi e confini
Alla fine saprai distinguere internalField da boundaryField, identificare la classe e le dimensioni di un campo, assegnare le condizioni per U e p a tutte le patch e risalire da un errore di input alla sua origine.
Non in questa unità
La generazione della mesh è trattata nella Parte 2; il controllo del tempo, gli schemi ai volumi finiti e i solutori algebrici appartengono alle Parti 4–6. L’esecuzione completa del solutore richiede anche quei file.
Mappa di lettura
| Sezioni | Argomento | Risultato |
|---|---|---|
| 1–2 | Anatomia del campo e identità delle patch | Sapere che cosa rappresenta ciascun file |
| 3–4 | 0/U e 0/p completi | Scrivere dati al contorno fisicamente coerenti |
| 5–7 | Semantica delle condizioni al contorno, validazione e flusso di lavoro | Prevedere e ispezionare le conseguenze |
| 8–10 | Estensioni, errori, esercizi | Lavorare in modo sempre più autonomo |
| Appendici | Mesh minima, soluzione di riferimento, fonti | Riprodurre e verificare l’esempio |
Nota sulla numerazione: la mappa raggruppa le sezioni per obiettivo; i titoli numerati che seguono riprendono la numerazione del corso (i file completi 0/U e 0/p sono nelle sezioni 4 e 5). Le soluzioni commentate degli esercizi, che la mappa colloca tra le appendici, sono nei riquadri di approfondimento della sezione 10.
1. Problema di riferimento e ipotesi
Usiamo un flusso dimostrativo incomprimibile, monofase, isotermo e laminare attraverso un condotto rettangolare 3D. La direzione principale del flusso è +x. La velocità di ingresso è imposta e la pressione cinematica all’uscita è fissata come riferimento.

walls, 4 facce solide); non ci sono patch empty. All’ingresso (inlet) è imposta U, all’uscita (outlet) è fissato il riferimento di p; il flusso è diretto lungo +x.Dimensioni della geometria didattica
| Grandezza | Simbolo | Valore dimostrativo |
|---|---|---|
| Lunghezza | L | 0,100 m |
| Altezza | H | 0,010 m |
| Larghezza | W | 0,005 m |
| Velocità di ingresso | Uin | (0.05 0 0) m/s |
| Viscosità illustrativa | ν | 1,0 × 10−6 m²/s |
I nomi del contorno della mesh assunti in tutta la parte sono esattamente inlet, outlet e walls. Le quattro facce laterali appartengono all’unica patch chiamata walls. Se la geometria della Parte 2 usa nomi diversi, modifica i file di campo perché corrispondano alla tua mesh effettiva.
Richiamo facoltativo · Numero di Reynolds
Per un condotto rettangolare il diametro idraulico è Dh = 2HW/(H+W) = 6,67 mm. Con la velocità e la viscosità illustrative, Re = UmeanDh/ν ≈ 333. È una dimostrazione laminare plausibile; non sostituisce la validazione del flusso reale nel reattore.
Approfondimento · I numeri del canale: Re, lunghezza di sviluppo e caduta di pressione attesa
Il diametro idraulico nasce dalla definizione Dh = 4A/P (area della sezione su perimetro bagnato): A = H·W = 5,0 × 10−5 m², P = 2(H+W) = 0,030 m, quindi Dh = 4·5,0 × 10−5/0,030 = 6,667 × 10−3 m. Con un ingresso uniforme la velocità media coincide con quella imposta, Umean = 0,05 m/s, e Re = 0,05 · 6,667 × 10−3 / 1,0 × 10−6 = 333,3. La transizione nei condotti avviene tipicamente oltre Re ≈ 2000, quindi l’ipotesi laminare è ampiamente rispettata.
Lunghezza di sviluppo. Un profilo uniforme all’ingresso non è il profilo di regime: gli strati limite crescono dalle pareti fino a riempire la sezione. La stima classica per il regime laminare è Le ≈ 0,05·Re·Dh ≈ 0,05 · 333 · 6,67 mm ≈ 111 mm, cioè dello stesso ordine della lunghezza del canale (L = 100 mm, circa 15 Dh). Il flusso è quindi ancora in sviluppo, o appena sviluppato, in prossimità dell’uscita: un dettaglio importante per giudicare l’ipotesi zeroGradient sulla velocità in uscita (sezione 4).
Caduta di pressione di riferimento. Per il flusso completamente sviluppato in un condotto con rapporto di forma W/H = 0,5 la soluzione in serie della equazione di Poisson dà f·Re ≈ 62,2 (fattore d’attrito di Darcy). La caduta di pressione cinematica su L vale Δp/ρ = f (L/Dh) U²/2 = (62,2/333,3) · 15 · (0,05²/2) ≈ 3,5 × 10−3 m²/s². Il flusso reale, con il tratto di sviluppo, dà un valore un po’ più alto. È un ordine di grandezza utile da confrontare con il campo p calcolato (che all’ingresso varrà circa 0,0035–0,004 m²/s² sopra il riferimento d’uscita).
| Grandezza | U = 0,05 m/s | U = 0,06 m/s | U = 0,08 m/s |
|---|---|---|---|
| Portata Q = U·A | 2,5 × 10−6 m³/s | 3,0 × 10−6 m³/s | 4,0 × 10−6 m³/s |
| Re | 333 | 400 | 533 |
| Le ≈ 0,05·Re·Dh | ≈ 111 mm | ≈ 133 mm | ≈ 178 mm |
| Δp/ρ sviluppato su L | ≈ 3,5 × 10−3 m²/s² | ≈ 4,2 × 10−3 m²/s² | ≈ 5,6 × 10−3 m²/s² |
I valori per 0,06 e 0,08 m/s servono negli esercizi B e C della sezione 10. Con ν di un liquido simile all’acqua (ρ ≈ 998 kg/m³) 3,5 × 10−3 m²/s² corrispondono a circa 3,5 Pa.
Approfondimento · Quale mesh stai usando? Parte 2 e Appendice A a confronto
Questa parte cita i conteggi di facce della mesh 40 × 12 × 8 dell’Appendice A (coordinate in metri, units [m];). Il blockMeshDict costruito nella Parte 2 descrive lo stesso canale 100 × 10 × 5 mm, ma con units [mm]; e una suddivisione 40 × 10 × 5. La geometria e i nomi delle patch sono gli stessi, quindi i file 0/U e 0/p di questa parte funzionano identici su entrambe; cambiano solo i numeri letti in constant/polyMesh/boundary.
| Voce | Mesh Parte 2 (40 × 10 × 5) | Mesh Appendice A (40 × 12 × 8) |
|---|---|---|
| Celle | 2000 | 3840 |
Facce inlet / outlet | 10 × 5 = 50 | 12 × 8 = 96 |
Facce walls | 2·(40·5) + 2·(40·10) = 1200 | 2·(40·8) + 2·(40·12) = 1600 |
| Facce interne | 5350 | 10624 |
| Dimensioni di cella | 2,5 × 1,0 × 1,0 mm | 2,5 × 0,833 × 0,625 mm |
Le facce di una patch su una faccia del blocco sono il prodotto delle suddivisioni nelle due direzioni che la generano: l’ingresso giace nel piano y–z, quindi ha Ny·Nz facce; le due pareti a y costante hanno Nx·Nz facce ciascuna, le due a z costante Nx·Ny. Rifare questo conto prima di aprire il file boundary è il modo più rapido per accorgersi di una mesh diversa da quella attesa.
Mappa delle condizioni al contorno
| Patch | Ruolo nella mesh | Campo U | Campo p |
|---|---|---|---|
inlet | patch generica | fixedValue (0.05 0 0) | zeroGradient |
outlet | patch generica | zeroGradient | fixedValue 0 |
walls | wall | noSlip | zeroGradient |
Questa è una configurazione semplice e specifica del modello: presuppone che la gravità o altre forze di volume non contribuiscano all’equazione della pressione e che all’uscita non ci sia un riflusso significativo. Condizioni di uscita e di pressione più generali sono discusse più avanti.
Approfondimento · Perché proprio queste ipotesi: gravità, riflusso e scelta del modulo
Gravità. Nel modulo incompressibleFluid non c’è un termine di galleggiamento: la gravità, se presente in un flusso a densità costante, si può assorbire in una pressione modificata ed è irrilevante per il campo di velocità. Diventa importante nei moduli con densità variabile, dove la pressione risolta è p_rgh (pressione meno il contributo idrostatico ρ g·h) e alle pareti si usa fixedFluxPressure al posto di zeroGradient, proprio perché il gradiente di pressione normale deve bilanciare le forze di volume.
Riflusso. Con zeroGradient sulla velocità all’uscita, ciò che entra eventualmente dall’esterno non ha un valore controllato: se un vortice attraversa l’uscita il problema diventa mal posto e il calcolo può divergere. Per un condotto diritto laminare a Re ≈ 333 il flusso esce ovunque e l’ipotesi è rispettata; nella sezione 8.3 vedremo che cosa fare quando non lo è.
Modulo. Tutta la parte assume il modulo solutore incompressibleFluid, selezionato in system/controlDict con solver incompressibleFluid; ed eseguito da foamRun (Parte 4). Le proprietà fisiche (viscosità nu in constant/physicalProperties) e il regime laminare (constant/momentumTransport) sono trattati nella Parte 7. Sono i requisiti di questo modulo a determinare quali campi servono in 0/: qui solo U e p; un modello di turbolenza aggiungerebbe per esempio k, epsilon o omega e nut.
2. Dentro un file di campo OpenFOAM
I file di campo vivono nelle cartelle temporali, normalmente 0/ all’inizio di un calcolo. Lo zero iniziale identifica un istante iniziale, non una categoria di cartella di input. Quando un solutore scrive tempi successivi, crea altre cartelle che contengono i valori dei campi.
case/
├── 0/
│ ├── U # campo di velocità
│ └── p # campo di pressione cinematica, per questo modulo
├── constant/
│ └── polyMesh/
│ └── boundary # identità delle patch della mesh
└── system/
├── blockMeshDict
├── controlDict
├── fvSchemes
└── fvSolution
Approfondimento · Le cartelle temporali in pratica
Il nome di una cartella temporale è il valore del tempo simulato scritto come numero: 0, 0.01, 0.02 e così via (il formato dipende da timeFormat e timePrecision in controlDict, Parte 4). Il solutore parte dalla cartella indicata da startFrom/startTime: con startTime 0 legge 0/; con startFrom latestTime riparte dall’ultima cartella scritta, che contiene campi completi e quindi funge da nuova condizione iniziale.
Le cartelle scritte dal solutore non sono una copia di 0/: internalField diventa di solito nonuniform List<vector> con un valore per cella, e compaiono campi derivati come phi (il flusso volumetrico sulle facce, un surfaceScalarField) e la sottocartella uniform/ con informazioni sul tempo. Le condizioni al contorno vengono riscritte con il loro tipo: per questo un restart conserva le patch così come sono state definite.
Strumenti utili: foamListTimes elenca le cartelle temporali escludendo 0; foamListTimes -rm le cancella prima di rilanciare da capo, lasciando intatta 0/. Una convenzione diffusa nei tutorial è conservare una copia pulita dei campi iniziali (per esempio 0.orig/) quando un’utilità di pre-elaborazione sovrascrive 0/; con le field functions della v14 (sezione 8.4) questa necessità si riduce.
Tre dichiarazioni indipendenti
FoamFile: identifica l’oggetto file, incluseclass,locationeobject.dimensions: dichiara le dimensioni fisiche, controllate da OpenFOAM durante l’esecuzione. Foundation v14 supporta nomi leggibili come[velocity].internalField/boundaryField: specificano il campo iniziale nelle celle e le condizioni sulle facce di contorno della mesh.

constant/polyMesh/boundary); la fisica viene assegnata separatamente in ciascun campo (0/U e 0/p, dentro boundaryField).Anatomia di 0/U — schema illustrativo
FoamFile
{
version 2.0;
format ascii;
class volVectorField;
location "0";
object U;
}
dimensions [velocity];
internalField uniform (0 0 0);
boundaryField
{
...
}
Approfondimento · L’intestazione FoamFile voce per voce
| Voce | Significato | Note per la v14 |
|---|---|---|
version | Versione del formato di I/O | Facoltativa; il valore predefinito è 2.0. |
format | ascii o binary | I file scritti a mano sono ascii; il solutore scrive nel formato scelto con writeFormat in controlDict. |
class | Il tipo C++ dell’oggetto da leggere | dictionary per i dizionari; per i campi volScalarField, volVectorField, volSymmTensorField, volTensorField, surfaceScalarField, pointVectorField… |
location | Percorso del file nel caso | Facoltativa e solo informativa; nei campi iniziali è "0". |
object | Nome dell’oggetto | Obbligatoria secondo la guida, anche se non usata; per convenzione uguale al nome del file (U, p). |
Il prefisso vol indica valori associati ai centri delle celle (più i valori sulle facce di contorno); surface indica valori sulle facce, point sui vertici. La parte Scalar/Vector fissa la forma di ogni valore: 1 componente per p, 3 per U, 6 per un tensore simmetrico, 9 per un tensore generico. È per questo che una class sbagliata produce errori di lettura del tipo «atteso un vettore» anche quando i numeri sono plausibili (sezione 9).
Approfondimento · Dimensioni con nome, esponenti e unità in v14
Ogni grandezza ha un insieme di sette esponenti delle dimensioni di base, nell’ordine massa, lunghezza, tempo, temperatura, quantità di sostanza, corrente, intensità luminosa. La forma numerica storica e la forma con nome sono equivalenti; dalla v14 i casi di esempio usano solo dimensioni con nome nei file di input, e la guida raccomanda di farlo.
| Forma con nome | Forma numerica | Unità SI | Uso |
|---|---|---|---|
[velocity] | [0 1 -1 0 0 0 0] | m/s | U |
[kinematicPressure] | [0 2 -2 0 0 0 0] | m²/s² | p in incompressibleFluid |
[pressure] | [1 -1 -2 0 0 0 0] | Pa = kg/(m·s²) | p nei moduli comprimibili |
[kinematicViscosity] | [0 2 -1 0 0 0 0] | m²/s | nu |
[length] | [0 1 0 0 0 0 0] | m | coordinate, distanze |
Sono ammesse anche espressioni composte, come [sqr(length)/time] o [area/time]. In v14 le unità sono una funzione standard: un valore può essere seguito dalla sua unità tra parentesi quadre e viene convertito nelle unità SI di base, per esempio internalField uniform 1 [bar]; (la guida mostra proprio questa forma). Le unità vengono controllate rispetto alle dimensioni della grandezza, e secondo le note di rilascio della v14 il controllo delle dimensioni si applica alla lettura di tutti i campi geometrici.
Per verificare un nome o una conversione si usa foamUnits:
foamUnits # lists all named dimensions and units
foamUnits velocity # details of one named dimension
foamUnits kinematicPressure
foamUnits -value "cm/s" # factor to base units (0.01)
foamUnits -value bar Pa # factor from the first unit to the second (1e+05)
L’output esatto dipende dall’installazione; il fattore, invece, è fisso.
Un campo interno non è una condizione al contorno
internalField inizializza i valori all’interno dei volumi delle celle. Non prescrive l’ingresso, l’uscita o le pareti: queste sono specificate in modo indipendente dentro boundaryField. Un campo di velocità iniziale nullo è compatibile con una velocità di ingresso imposta diversa da zero.
Richiamo facoltativo · Valore iniziale e dati al contorno
Per una EDP non stazionaria, una condizione iniziale specifica un campo in tutto il dominio spaziale all’istante t = t0; una condizione al contorno ne vincola il comportamento su ∂Ω. Hanno ruoli matematici diversi e non sono intercambiabili.
Approfondimento · uniform, nonuniform e che cosa contiene davvero un campo
Un volVectorField su questa mesh contiene 3840 vettori interni (uno per cella) più un vettore per ciascuna faccia di contorno: 96 + 96 + 1600 = 1792 valori sulle patch. uniform (0 0 0) è un’abbreviazione che replica lo stesso vettore in tutte le 3840 celle. La forma esplicita, quella che il solutore scrive nelle cartelle temporali successive, è:
internalField nonuniform List<vector>
3840
(
(0.0498 0.0001 0)
(0.0512 0.0002 0)
...
)
;
Il numero all’inizio della lista deve coincidere con il numero di celle; un errore qui produce un messaggio di dimensione della lista non corrispondente. Nei file scritti a mano si usa quasi sempre uniform, oppure, in v14, una field function (sezione 8.4). Le direttive dei dizionari restano disponibili anche nei campi: $internalField espande il valore della voce internalField (utile per esempio in value $internalField;) e #include permette di tenere i valori iniziali in un file comune.
3. La mesh definisce l’identità delle patch
Dopo blockMesh, il file constant/polyMesh/boundary elenca le patch di contorno. Queste voci identificano la geometria e il tipo di patch. Non prescrivono, da sole, né U né p.
Estratto illustrativo di constant/polyMesh/boundary
3
(
inlet
{
type patch;
nFaces 96;
startFace ...;
}
outlet
{
type patch;
nFaces 96;
startFace ...;
}
walls
{
type wall;
nFaces 1600;
startFace ...;
}
)
I conteggi qui sopra corrispondono alla mesh di esempio 40 × 12 × 8: 96 facce di ingresso, 96 di uscita e 1600 di parete. In un vero file boundary generato, startFace è un numero, non un’ellissi; questo estratto è solo un aiuto alla lettura.
Approfondimento · Il file boundary reale e il significato di startFace
OpenFOAM memorizza tutte le facce della mesh in un’unica lista (constant/polyMesh/faces): prima tutte le facce interne, poi le facce di contorno raggruppate per patch, una patch dopo l’altra. nFaces è quante facce consecutive appartengono alla patch, startFace è l’indice (contato da 0) della prima. Per la mesh 40 × 12 × 8 le facce interne sono 39·12·8 + 40·11·8 + 40·12·7 = 3744 + 3520 + 3360 = 10624, quindi l’ingresso parte da 10624, l’uscita da 10624 + 96 = 10720 e le pareti da 10720 + 96 = 10816. Il totale, 10816 + 1600 = 12416 facce, coincide con quanto riporta checkMesh. Il file generato ha quindi un aspetto di questo tipo:
FoamFile
{
format ascii;
class polyBoundaryMesh;
location "constant/polyMesh";
object boundary;
}
3
(
inlet
{
type patch;
nFaces 96;
startFace 10624;
}
outlet
{
type patch;
nFaces 96;
startFace 10720;
}
walls
{
type wall;
inGroups List<word> 1(wall);
nFaces 1600;
startFace 10816;
}
)
La riga inGroups List<word> 1(wall); (che il file generato riporta per le patch di tipo wall) dice che la patch appartiene al gruppo wall: tutte le patch non generiche vengono messe automaticamente in un gruppo con il nome del proprio tipo. Questo dettaglio torna utile nella sezione 9. L’ordine delle patch è quello della lista boundary del blockMeshDict. Non modificare mai a mano nFaces o startFace: sono la topologia della mesh, non parametri.
Corrispondenza dei nomi
Per chiarezza scriviamo una voce di condizione al contorno esplicita per ogni patch. Le etichette inlet, outlet e walls devono essere scritte in modo identico sia in 0/U sia in 0/p. OpenFOAM 14 supporta anche la selezione per gruppo e per espressione regolare, ma per ora non serve.
| File boundary | Campo U | Campo p |
|---|---|---|
inlet / patch | inlet { type fixedValue; ... } | inlet { type zeroGradient; } |
outlet / patch | outlet { type zeroGradient; } | outlet { type fixedValue; ... } |
walls / wall | walls { type noSlip; } | walls { type zeroGradient; } |
Importante · Tipo di patch ≠ condizione al contorno del campo
Una patch della mesh di tipo wall può portare noSlip per la velocità e zeroGradient per la pressione. Al contrario, i tipi di vincolo come symmetry ed empty richiedono condizioni di campo corrispondenti compatibili.
Approfondimento · Tipi di patch della mesh e tipi di vincolo
La guida v14 distingue tre famiglie di patch della mesh. Le patch generiche (patch) rappresentano tipicamente bordi aperti come ingressi e uscite e richiedono condizioni esplicite in ogni campo. Le patch parete (wall) richiedono anch’esse condizioni esplicite; il tipo wall serve ai modelli che hanno bisogno di sapere dove sono le pareti (per esempio le funzioni di parete e il calcolo della distanza dalla parete nei modelli di turbolenza). I vincoli geometrici sono empty, symmetry, symmetryPlane, wedge, cyclic, cyclicSlip, nonConformalCyclic, nonConformalError, processor, processorCyclic, nonConformalProcessorCyclic e internal: ognuno ha una condizione al contorno con lo stesso nome, che è l’unica ammessa su quella patch.
Se il tipo del campo non è compatibile con il vincolo (per esempio zeroGradient su una patch empty), la lettura si ferma con un errore del tipo inconsistent patch and patchField types for patch type empty and patchField type zeroGradient. Per non riscrivere i vincoli in ogni campo, la guida suggerisce di includere il file di sistema caseDicts/setConstraintTypes, che definisce una voce per ogni gruppo di vincoli: dopo l’inclusione restano da configurare solo le patch generiche e le pareti.
boundaryField
{
#includeEtc "caseDicts/setConstraintTypes"
inlet
{
type fixedValue;
value uniform (0.05 0 0);
}
...
}
Nel nostro canale non ci sono patch di vincolo, quindi l’inclusione non cambia nulla; diventa comoda nei casi 2D (sezione 8.1) o nei casi decomposti in parallelo, dove compaiono patch processor (vedi il caso pratico sul calcolo parallelo MPI).
Approfondimento · Selezione per gruppo e per espressione regolare
Una voce di boundaryField può indicare una patch in tre modi, con questa precedenza: (1) il nome esatto della patch; (2) il nome di un gruppo a cui la patch appartiene (per esempio wall, il gruppo automatico di tutte le patch di tipo wall); (3) un’espressione regolare POSIX tra virgolette doppie, come ".*Wall" o "(lower|upper)Wall". Un nome esatto prevale sempre su un gruppo o su un’espressione, indipendentemente dall’ordine nel file. Una versione compatta e del tutto equivalente del nostro 0/p è quindi:
boundaryField
{
"(inlet|walls)" // regular expression: double quotes required
{
type zeroGradient;
}
outlet // exact patch name: highest precedence
{
type fixedValue;
value uniform 0;
}
}
La forma compatta è utile con decine di patch, ma rende meno evidente quale condizione riceve ciascuna patch: per questo in questa parte si scrive una voce per patch. Conseguenza importante: una voce chiamata wall non è un errore di battitura innocuo, perché coincide con il nome del gruppo e quindi si applica a tutte le patch di parete. Se la mesh ha anche una patch chiamata esattamente wall, la voce si riferisce a quella in modo esatto.
4. Scrivere il file completo della velocità: 0/U
La velocità è rappresentata da un volVectorField. In Foundation v14, dimensions [velocity] specifica le dimensioni attese della velocità. All’ingresso c’è una velocità uniforme fissata in direzione +x.

0/U completo — risposta di riferimento
FoamFile
{
version 2.0;
format ascii;
class volVectorField;
location "0";
object U;
}
dimensions [velocity];
internalField uniform (0 0 0);
boundaryField
{
inlet
{
type fixedValue;
value uniform (0.05 0 0);
}
outlet
{
type zeroGradient;
}
walls
{
type noSlip;
}
}
Interpretare le tre voci di patch
inlet—fixedValue: sono prescritte tutte e tre le componenti della velocità. Qui il vettore punta lungo +x.outlet—zeroGradient: il gradiente normale di ciascuna componente della velocità è nullo. È un’approssimazione semplice di uscita del flusso, non un modello generale di contorno aperto.walls—noSlip: la velocità di parete è nulla per le pareti fisse e ferme di questo esempio.
Nota che noSlip non richiede una voce value esplicita. Al contrario, fixedValue richiede il valore prescritto.
Approfondimento · Che cosa fa fixedValue all’ingresso, in termini di volumi finiti
Nel metodo ai volumi finiti ogni cella adiacente all’ingresso ha una faccia di contorno. fixedValue assegna a quella faccia il vettore Ub = (0.05 0 0) m/s. Il valore entra nelle equazioni in due modi: nel termine convettivo, attraverso il flusso volumetrico sulla faccia φf = Ub·Sf (Sf è il vettore area della faccia, orientato verso l’esterno, quindi qui φf < 0: il fluido entra); nel termine diffusivo, attraverso il gradiente normale sulla faccia, approssimato come (Ub − UP)/|d|, dove UP è il valore nel centro della cella e |d| la distanza tra centro della cella e centro della faccia.
Sommando sulle 96 facce di ingresso si ottiene la portata imposta: Q = 0,05 m/s × 5,0 × 10−5 m² = 2,5 × 10−6 m³/s (2,5 ml/s). Con un ingresso fixedValue la portata è quindi determinata esattamente dall’input, indipendentemente dalla mesh. Il profilo imposto è però piatto (a «tappo»): accanto alle pareti la velocità salta da 0,05 m/s a zero nella prima cella, ed è il tratto di sviluppo stimato nella sezione 1 a ricostruire il profilo realistico.
Alternative per lo stesso ingresso, tutte presenti in Foundation v14 (verifica con foamInfo <nome>):
flowRateInletVelocity: si impone la portata (volumetrica o massica) invece della velocità; il profilo sulla patch viene calcolato dalla condizione. Comodo quando il dato sperimentale è una portata.uniformFixedValue: un valore uniforme che può variare nel tempo, specificato conuniformValueseguito da unaFunction1(constant,table,tableFile,sine,square,polynomial,scalecon le rampe comelinearRamp,coded…). Utile per un avvio graduale.functionalFixedValue(nuovo in v14): un valore non uniforme, e anche variabile nel tempo, definito da una field function, per esempio un profilo sviluppato (sezione 8.4).
Il caso pratico sulla sensibilità alle condizioni di ingresso confronta proprio un ingresso piatto con un profilo sviluppato e ne misura le conseguenze a valle.
Approfondimento · zeroGradient all’uscita: che cosa impone e quando regge
zeroGradient impone ∂U/∂n = 0. Nella discretizzazione il valore sulla faccia di contorno viene semplicemente copiato dal centro della cella adiacente, Ub = UP, e il flusso diffusivo attraverso la faccia è nullo. La condizione è «naturale» se il profilo di velocità non cambia più lungo x vicino all’uscita, cioè se il flusso è sviluppato. Nel nostro canale la lunghezza di sviluppo stimata (≈ 111 mm) è paragonabile alla lunghezza del dominio: le derivate in x all’uscita sono piccole ma non esattamente nulle, e la condizione introduce un piccolo errore locale nelle ultime celle. Se i risultati vicino all’uscita contano, si allunga il dominio a valle.
La portata in uscita non è imposta da zeroGradient: è la continuità, risolta attraverso l’equazione della pressione, a renderla uguale a quella in ingresso. È per questo che U e p vanno pensati come coppia (sezione 6).
Approfondimento · noSlip e le altre condizioni di parete per la velocità
noSlip è una condizione derivata da fixedValue con valore implicito nullo: equivale a scrivere type fixedValue; value uniform (0 0 0);, ma rende esplicita l’intenzione fisica e non richiede la voce value. Impone sia la componente tangenziale nulla (aderenza) sia quella normale nulla (impermeabilità). È la condizione che la guida v14 usa per le pareti nei tutorial (per esempio damBreak e il gradino all’indietro).
| Condizione | Che cosa impone | Quando usarla |
|---|---|---|
noSlip | U = 0 sulla parete | Parete solida ferma (il nostro caso) |
movingWallVelocity | Velocità della parete in moto; corregge il flusso se la mesh si muove | Parete che scorre, per esempio il coperchio di una cavità |
fixedValue | Un vettore qualsiasi sulla parete | Parete traslante con velocità nota |
slip | Componente normale nulla, gradiente nullo delle componenti tangenziali | Parete senza attrito (idealizzazione) |
L’elenco completo delle condizioni disponibili per un campo vettoriale si ottiene con foamToC -vectorBCs; la descrizione di una singola condizione, con i casi di esempio che la usano, con foamInfo movingWallVelocity.
5. Scrivere il file completo della pressione: 0/p
Per la formulazione incompressibleFluid scelta, il campo primario p è la pressione cinematica, con unità m²/s², e non la pressione in pascal. La classe del campo è volScalarField.
0/p completo — risposta di riferimento
FoamFile
{
version 2.0;
format ascii;
class volScalarField;
location "0";
object p;
}
dimensions [kinematicPressure];
internalField uniform 0;
boundaryField
{
inlet
{
type zeroGradient;
}
outlet
{
type fixedValue;
value uniform 0;
}
walls
{
type zeroGradient;
}
}
Riferimento della pressione e unità fisiche
La condizione all’uscita fissa un valore di riferimento della pressione cinematica. Non significa che il fluido abbia pressione assoluta nulla. Per una densità costante ρ, una differenza di pressione si converte con ΔpPa = ρ Δpcinematica.
Richiamo facoltativo · Gauge della pressione e spazio nullo
In molte formulazioni incomprimibili sono solo i gradienti di pressione a muovere la velocità. Senza un riferimento appropriato, il livello della pressione può restare indeterminato a meno di una costante. Il valore fissato all’uscita fornisce un riferimento per questo caso didattico. Altre formulazioni possono usare trattamenti diversi del riferimento.
Approfondimento · Pressione cinematica: definizione e conversione con un esempio
Dividendo l’equazione della quantità di moto incomprimibile per la densità costante ρ si ottiene ∂U/∂t + ∇·(UU) = −∇(p/ρ) + ∇·(ν∇U): il solutore lavora direttamente con pcin = p/ρ, che ha unità Pa/(kg/m³) = m²/s² (equivalenti a J/kg, un’energia per unità di massa). È per questo che in incompressibleFluid la viscosità richiesta è quella cinematica ν e non serve conoscere ρ per risolvere il flusso.
Esempio. Se a regime il campo p vale circa 0,0035 m²/s² all’ingresso e 0 all’uscita (il valore stimato nella sezione 1), per acqua a 20 °C (ρ ≈ 998 kg/m³) la caduta di pressione fisica è ΔpPa = 998 × 0,0035 ≈ 3,5 Pa. Il valore assoluto si ottiene aggiungendo la pressione effettiva all’uscita, per esempio quella atmosferica: pingresso ≈ 101325 + 3,5 Pa. Un valore negativo di p nel dominio non è quindi un errore fisico: significa solo una pressione inferiore a quella di riferimento.
Approfondimento · Che cosa succede senza un valore fissato: pRefCell e pRefValue
Nella formulazione incomprimibile la pressione compare solo come gradiente, e l’equazione della pressione che il solutore costruisce (un’equazione di Poisson derivata dalla continuità) ammette soluzioni che differiscono per una costante se su nessuna patch è imposto un valore: la matrice è singolare, con uno spazio nullo formato dai campi costanti. Con fixedValue all’uscita il problema non si pone.
Nei casi chiusi, come una cavità con tutte pareti e quindi zeroGradient ovunque, il livello va fissato altrove: i solutori incomprimibili leggono nel dizionario dell’algoritmo in system/fvSolution (PIMPLE o SIMPLE, Parte 6) le voci pRefCell (indice di una cella) o pRefPoint (una posizione) e pRefValue (il valore da attribuirvi). Queste voci vengono usate solo quando nessuna patch fissa la pressione; nel nostro canale sono superflue.
Non mescolare formulazioni della pressione
| Modello di esempio | Possibile rappresentazione di p | Da non presumere |
|---|---|---|
| Modulo incomprimibile monofase usato qui | [kinematicPressure] (m²/s²) | Che p = 0 significhi 0 Pa assoluti. |
| Comprimibile / altri moduli fisici | Può usare la pressione fisica [pressure] (Pa) | Di poter copiare 0/p invariato da un modulo all’altro. |
Per ogni nuovo modulo solutore, ispeziona un tutorial v14 pertinente e la documentazione del modulo prima di scegliere le dimensioni del campo di pressione o i tipi di condizione al contorno.
Approfondimento · Come verificare la formulazione richiesta da un modulo
foamInfo incompressibleFluidstampa la descrizione del modulo e i casi di esempio che lo usano.- Il tutorial del gradino all’indietro della guida v14 (
$FOAM_TUTORIALS/incompressibleFluid/pitzDaily) usa propriodimensions [kinematicPressure];,internalField uniform 0;,zeroGradientall’ingresso e alle pareti efixedValue0 all’uscita: la stessa struttura di questa parte. - Nei moduli comprimibili (per esempio
fluid,shockFluid)pè la pressione assoluta in Pa con[pressure]e valori dell’ordine di 1 bar; nei moduli con galleggiamento compare anchep_rgh. Copiare il nostro0/pin uno di questi casi produrrebbe, nella migliore delle ipotesi, un errore di dimensioni; nella peggiore, una densità calcolata da una pressione assoluta nulla. find "$FOAM_TUTORIALS" -path '*/0/p' | heade poifoamDictionary -entry dimensions -value <file>mostrano rapidamente quali dimensioni usano i tutorial di un modulo.
6. Che cosa significano matematicamente queste condizioni?
La sintassi diventa utile solo quando la si traduce in vincoli fisici e matematici. Le descrizioni semplificate che seguono sono appropriate per il campo e la geometria di questa parte.
| Tipo di condizione | Significato semplificato | Nel nostro caso |
|---|---|---|
fixedValue | Dirichlet: è specificato il valore del campo sul contorno. | U all’ingresso; p all’uscita |
zeroGradient | Condizione omogenea sul gradiente normale: ∂φ/∂n = 0. | U all’uscita; p all’ingresso e alle pareti |
noSlip | Per una parete ferma, la velocità del fluido tangenziale e normale è nulla. | U alle pareti |
symmetry | Vincolo geometrico per un vero contorno di simmetria. | Non usato in questo canale 3D |
empty | Vincolo geometrico per mesh 2D/1D estruse. | Non usato in questo canale 3D |
Richiamo facoltativo · Dirichlet e Neumann
Una condizione di Dirichlet specifica φ sul contorno. Una condizione di Neumann ne specifica la derivata normale. Una condizione al contorno ai volumi finiti va interpretata insieme all’equazione che governa il problema, alla discretizzazione e alle ipotesi fisiche; la sola sintassi non garantisce un modello CFD ben posto.
Approfondimento · Le condizioni di base della v14 e la loro forma discreta
La guida v14 elenca sei condizioni di base (sorgenti in $FOAM_SRC/finiteVolume/fields/fvPatchFields/basic), da cui derivano quasi tutte le altre. Indicando con φP il valore nel centro della cella adiacente, φb il valore sulla faccia di contorno e Δ = 1/|d| l’inverso della distanza tra i due punti:
| Condizione | Voci richieste | Valore sulla faccia | Gradiente normale sulla faccia |
|---|---|---|---|
fixedValue | value | φb = φref | Δ(φb − φP) |
fixedGradient | gradient | φb = φP + g/Δ | g |
zeroGradient | nessuna | φb = φP | 0 |
calculated | value | calcolato da altri campi | — |
mixed | refValue, refGradient, valueFraction | w φref + (1 − w)(φP + gref/Δ) | combinazione delle due |
directionMixed | come mixed, con valueFraction tensoriale | valore fisso in alcune direzioni, gradiente nelle altre | — |
Con valueFraction w = 1 la condizione mixed diventa un valore fisso, con w = 0 un gradiente fisso. Le condizioni derivate più comuni sono costruite così: inletOutlet, per esempio, è un mixed che passa a valore fisso dove il flusso entra e a gradiente nullo dove esce. Nella matrice del sistema lineare ogni condizione contribuisce con un coefficiente sulla diagonale della cella adiacente e un termine noto: fixedValue aggiunge entrambi (il valore imposto è un termine noto, la dipendenza da φP rinforza la diagonale), zeroGradient nessuno dei due nel termine diffusivo.
Perché U e p vengono trattati come coppia?
Nel flusso incomprimibile velocità e pressione sono accoppiate dalla quantità di moto e dalla continuità. Specificare una velocità in ingresso e un riferimento di pressione in uscita è un abbinamento semplice e comune. Non è universalmente appropriato in caso di inversione del flusso, portata imposta, pareti in moto, flusso con galleggiamento o modelli comprimibili.
Approfondimento · Perché la coppia funziona: un conteggio delle informazioni
Le equazioni sono ∇·U = 0 e ∂U/∂t + ∇·(UU) = −∇p + ν∇²U. La velocità soddisfa un’equazione di trasporto-diffusione, che su ogni contorno richiede o il valore o il gradiente normale; la pressione non ha una propria equazione di evoluzione: nell’algoritmo SIMPLE/PIMPLE soddisfa un’equazione di Poisson costruita imponendo la continuità ai flussi corretti. Ne derivano due regole pratiche.
- Dove U è imposto, p prende gradiente nullo. All’ingresso e alle pareti il flusso attraverso la faccia è già fissato dalla velocità; l’equazione della pressione non deve correggerlo, e la condizione coerente è un gradiente normale (nullo, in assenza di forze di volume). È esattamente la scelta di questa parte.
- Dove p è imposto, U prende gradiente nullo. All’uscita la pressione fissa il livello e la velocità si adatta, così che la portata in uscita derivi dalla continuità. Imporre sia U sia p sullo stesso contorno sovradetermina il problema; non imporre nessuno dei due in nessun punto lo lascia indeterminato.
Sulle pareti, a rigore, il gradiente normale della pressione è legato ai termini viscosi (∂p/∂n = ν∇²U·n); zeroGradient è l’approssimazione standard, accurata per flussi come questo. Quando ci sono forze di volume si usa fixedFluxPressure, che calcola il gradiente coerente con il flusso imposto.
L’inizializzazione influisce sulla convergenza, non sul contorno prescritto
Il campo iniziale U = (0 0 0) in ogni cella è un’ipotesi di partenza semplice e valida, anche se l’ingresso impone già U = (0.05 0 0). Un’ipotesi iniziale diversa può cambiare la storia della convergenza; non sostituisce la condizione al contorno.
Approfondimento · Che cosa succede al primo passo con U iniziale nullo
Al primo passo il campo interno è fermo e solo le facce di ingresso hanno velocità non nulla: il flusso in ingresso, 2,5 × 10−6 m³/s, non trova un corrispondente flusso in uscita. La prima correzione di pressione risolve l’equazione di Poisson e redistribuisce la velocità in tutto il dominio, così che la continuità sia soddisfatta subito: in un fluido incomprimibile l’informazione di pressione si propaga istantaneamente. Per questo, nel log, i residui iniziali dei primi passi sono alti (spesso vicini a 1) e poi calano.
Partire da uniform (0.05 0 0) in tutto il dominio riduce il transitorio iniziale; partire da un campo sviluppato (per esempio da un calcolo precedente, mappato con mapFields) lo riduce ancora di più. Per un calcolo stazionario il risultato finale non cambia; per un calcolo transitorio fisico, invece, il campo iniziale è parte del problema e va scelto con lo stesso rigore delle condizioni al contorno.
7. Laboratorio pratico: assemblare e ispezionare
Lavora solo nella tua copia modificabile del caso del canale. Conserva la mesh originale della Parte 2 e gli eventuali controlli del solutore già validati. Lo scopo di questo esercizio è aggiungere o modificare i file di campo; non modificare l’installazione di OpenFOAM.
Fase 1 — Confermare la mesh
foamVersion
cd /path/to/your/editable/channelCase
blockMesh
checkMesh
sed -n '1,180p' constant/polyMesh/boundary
Leggi il numero e i nomi delle patch nel file boundary generato. Se non sono esattamente inlet, outlet e walls, devi adattare gli esempi di conseguenza. Non rinominare mai una patch della mesh soltanto in un file di campo.
Approfondimento · Che cosa deve riportare checkMesh per la mesh dell’Appendice A
Prevedere i numeri prima di eseguire è il modo più efficace di verificare. Per la mesh 40 × 12 × 8 dell’Appendice A i valori attesi sono:
| Voce di checkMesh | Valore atteso | Da dove viene |
|---|---|---|
| points | 4797 | 41 × 13 × 9 |
| faces | 12416 | 10624 interne + 1792 di contorno |
| internal faces | 10624 | 39·12·8 + 40·11·8 + 40·12·7 |
| cells / hexahedra | 3840 / 3840 | 40 × 12 × 8 |
patch inlet: facce, punti | 96, 117 | 12 × 8; 13 × 9 |
patch outlet: facce, punti | 96, 117 | 12 × 8; 13 × 9 |
patch walls: facce, punti | 1600, 1640 | punti di contorno 1794 meno i 2 × 77 interni a ingresso e uscita |
| bounding box | (0 0 0) (0.1 0.01 0.005) | vertici, in metri |
La riga finale deve essere Mesh OK. Le celle misurano 2,5 × 0,833 × 0,625 mm, quindi il rapporto d’aspetto massimo riportato sarà dell’ordine di 4, del tutto accettabile. Per la mesh della Parte 2 (40 × 10 × 5) i numeri cambiano come indicato nella sezione 1. sed -n '1,180p' stampa le prime 180 righe del file, più che sufficienti per un file boundary con tre patch; checkMesh riporta comunque gli stessi nomi nella sua tabella delle patch.
Fase 2 — Scrivere i file di campo
mkdir -p 0
# Apri 0/U e 0/p nel tuo editor di testo preferito.
# Inserisci gli esempi completi delle Sezioni 4 e 5.
Controlla la classe, l’oggetto, le dimensioni con nome, ogni parentesi graffa e ogni punto e virgola. I file di campo sono testo ASCII/UTF-8; l’indentazione migliora la leggibilità ma non fa parte della sintassi.
Approfondimento · Scrivere i file senza editor e senza errori di copia
Se preferisci non usare un editor interattivo, un here-document della shell scrive il file esattamente come lo incolli; le virgolette attorno a EOF impediscono alla shell di espandere $ e altri caratteri speciali:
cat > 0/p <<'EOF'
FoamFile
{
format ascii;
class volScalarField;
object p;
}
dimensions [kinematicPressure];
internalField uniform 0;
boundaryField
{
inlet { type zeroGradient; }
outlet { type fixedValue; value uniform 0; }
walls { type zeroGradient; }
}
EOF
L’esempio mostra anche che la disposizione su più righe è solo una convenzione: inlet { type zeroGradient; } su una riga è identico alla forma estesa. Attenzione ai caratteri invisibili quando si copia da PDF o pagine web: virgolette tipografiche (“ ”) al posto di ", trattini lunghi al posto del segno meno, spazi non separabili. Il parser di OpenFOAM non li riconosce e l’errore indicato può sembrare incomprensibile. Un controllo rapido: grep -nP '[^\x00-\x7F]' 0/U 0/p elenca le righe con caratteri non ASCII.
Fase 3 — Ispezionare le voci strutturalmente
foamDictionary 0/U
foamDictionary -entry dimensions -value 0/U
foamDictionary -entry internalField 0/U
foamDictionary -entry 'boundaryField/inlet' 0/U
foamDictionary -entry 'boundaryField/outlet/type' -value 0/p
foamDictionary -entry 'boundaryField/walls/type' -value 0/U
La sintassi dei percorsi annidati di foamDictionary usa /. Se l’estrazione di una voce riesce, il file può essere letto come dizionario; ciò non dimostra che tutte le condizioni specifiche del modello siano fisicamente corrette.
Approfondimento · L’output atteso di foamDictionary e tre comandi in più
Il primo comando stampa il file intero senza commenti. Gli altri dovrebbero produrre un output di questo tipo (la spaziatura esatta può differire):
$ foamDictionary -entry dimensions -value 0/U
[velocity]
$ foamDictionary -entry internalField 0/U
internalField uniform (0 0 0);
$ foamDictionary -entry 'boundaryField/inlet' 0/U
inlet
{
type fixedValue;
value uniform (0.05 0 0);
}
$ foamDictionary -entry 'boundaryField/outlet/type' -value 0/p
fixedValue
$ foamDictionary -entry 'boundaryField/walls/type' -value 0/U
noSlip
-value stampa solo il dato, senza parola chiave e punto e virgola: è la forma adatta agli script. Tre comandi utili in più: -keywords elenca le chiavi di un sottodizionario e quindi verifica la copertura delle patch in un colpo solo; -set modifica una voce senza aprire l’editor (qui, già pronto per l’esercizio B della sezione 10):
foamDictionary -entry boundaryField -keywords 0/U
foamDictionary -entry boundaryField -keywords 0/p
foamDictionary -entry boundaryField/inlet/value -set "uniform (0.08 0 0)" 0/U
I primi due devono stampare inlet, outlet e walls, gli stessi nomi del file boundary. Se una voce non esiste, foamDictionary termina con un errore che nomina la chiave mancante e il percorso del dizionario: è già un primo controllo di coerenza.
Fase 4 — Validare con la configurazione del solutore esistente
Se il caso ha già una configurazione fisica valida in constant/ e i file system/controlDict, fvSchemes e fvSolution, esegui il consueto flusso di lavoro con foamRun. Altrimenti fermati qui: le parti successive (4, 5, 6 e 7) spiegano i dizionari mancanti.
# Solo se il caso completo è già stato configurato:
foamRun > log.foamRun 2>&1
# Poi ispeziona il log in un passaggio separato:
less log.foamRun
Importante · I controlli della mesh non validano le condizioni al contornocheckMesh valida la topologia e la qualità della mesh. Non può certificare che un’uscita in pressione sia fisicamente sensata o che una condizione sulla velocità sia adatta a un dato flusso.
Approfondimento · Leggere il log alla ricerca degli errori sui campi
Gli errori sui file di campo emergono all’inizio del log, subito dopo la creazione della mesh, quando il modulo legge i campi (righe come Reading field p e Reading field U). Un errore fatale di lettura inizia con --> FOAM FATAL IO ERROR, riporta un messaggio, poi il file e il numero di riga (file: .../0/U/boundaryField/walls at line 31. o simile), e termina con FOAM exiting. Poiché il log può essere lungo, conviene cercare direttamente:
grep -n "FOAM FATAL" log.foamRun
grep -n -A 12 "FOAM FATAL" log.foamRun | head -40
Se il calcolo parte, i primi controlli fisici sono la continuità (gli errori di continuità riportati a ogni passo devono restare piccoli) e la portata all’uscita, che deve tendere a 2,5 × 10−6 m³/s. Il post-processing della portata su una patch è trattato nei casi pratici, per esempio il canale laminare con validazione di Poiseuille.
8. Casi speciali che incontrerai
8.1 Simulazioni bidimensionali
Un calcolo 2D standard in OpenFOAM è rappresentato da una mesh estrusa spessa una sola cella, con le facce anteriore e posteriore assegnate al vincolo geometrico empty. In ciascun campo richiesto, anche quelle patch usano type empty;. Non impostare empty su una parete 3D fisica solo perché non vuoi flusso attraverso di essa.
Condizione al contorno del campo per una vera patch empty della mesh
frontAndBack
{
type empty;
}
Approfondimento · Trasformare il canale in un caso 2D, e che cosa cambia nella fisica
Per ottenere una versione 2D del nostro canale nel piano x–y bastano due modifiche al blockMeshDict: una sola cella in z, cioè (40 12 1), e le due facce a z costante, (0 3 2 1) e (4 5 6 7), spostate da walls a una nuova patch frontAndBack di tipo empty. Poi, in ogni campo, si aggiunge la voce frontAndBack { type empty; } (oppure si include caseDicts/setConstraintTypes). La direzione con empty non viene risolta: checkMesh lo segnala riportando due direzioni geometriche invece di tre.
La fisica però cambia: il caso 2D rappresenta un canale tra due lastre piane parallele, di larghezza infinita in z, non più un condotto rettangolare. Il diametro idraulico diventa 2H = 20 mm, Re a parità di velocità triplica (≈ 1000) e il profilo sviluppato è la parabola di Poiseuille piana, con velocità massima pari a 1,5 volte la media. È il caso trattato nel primo caso pratico, flusso laminare tra lastre piane e validazione di Poiseuille. Errori tipici: dimenticare la patch empty in un solo campo (errore di voce mancante per frontAndBack), usare più di una cella nella direzione vuota, o usare zeroGradient su una patch empty (errore di tipi di patch incoerenti, sezione 3).
Per i casi assialsimmetrici si usa invece una mesh a cuneo sottile con due patch di tipo wedge, con la condizione di campo wedge corrispondente.
8.2 La simmetria non è una parete senza attrito
Usa symmetry solo dove il problema fisico e la geometria giustificano una simmetria per riflessione. Vincola la soluzione in un modo specifico; non è intercambiabile con noSlip né con un contorno aperto generico.
Approfondimento · Che cosa impone symmetry e un esempio sul nostro canale
Su un piano di simmetria la componente normale della velocità è nulla, le componenti tangenziali hanno gradiente normale nullo e gli scalari (come p) hanno gradiente normale nullo: la soluzione è lo specchio di sé stessa rispetto al piano. Matematicamente il risultato su una faccia piana coincide con quello della condizione slip per la velocità, ed è per questo che si sente dire «parete senza attrito»; ma il significato è diverso: symmetry afferma che dall’altra parte c’è la stessa soluzione riflessa, quindi anche le perturbazioni (vortici, instabilità) sono forzate a essere simmetriche. symmetryPlane richiede una patch perfettamente piana; symmetry ammette anche patch non perfettamente piane.
Esempio: il nostro condotto è simmetrico rispetto al piano z = 2,5 mm. Si potrebbe modellare metà sezione (z da 0 a 2,5 mm, 4 celle in z) con la faccia a z = 2,5 mm di tipo symmetry nella mesh e symmetry in ogni campo, dimezzando le celle. È lecito solo perché geometria, condizioni al contorno e flusso laminare stazionario sono tutti simmetrici; per un flusso con distacchi instabili non lo sarebbe. Anche qui il tipo deve essere coerente: symmetry nella mesh e symmetry nel campo.
8.3 Riflusso a un’uscita
La semplice uscita con velocità zeroGradient non è robusta in ogni configurazione. Se si prevede un riflusso, valuta condizioni specifiche per le uscite come pressureInletOutletVelocity e condizioni di pressione appropriate, usando la documentazione e i tutorial ufficiali. Scegliere una condizione per il riflusso è una decisione di modellazione fisica, non una sostituzione meccanica.
Approfondimento · Le condizioni di uscita della v14 per il riflusso
| Condizione | Campo | Comportamento | Voci |
|---|---|---|---|
inletOutlet | scalari e vettori | Gradiente nullo dove il fluido esce, valore fisso dove entra | inletValue |
pressureInletOutletVelocity | U | Gradiente nullo, tranne la componente tangenziale, fissata quando il flusso entra | tangentialVelocity facoltativa (predefinita 0; in v14 anche una field function) |
totalPressure | p | p = p0 in uscita; in ingresso subsonico p = p0 meno la pressione dinamica | p0 |
entrainmentPressure | p | Come totalPressure, ma il termine di ingresso usa la componente normale della velocità; la guida lo considera più robusto | p0 |
prghTotalPressure | p_rgh | Controparte di totalPressure per i moduli con galleggiamento | p0 |
La coppia tipica per un contorno aperto in cui il flusso può entrare o uscire è pressureInletOutletVelocity su U con totalPressure (o entrainmentPressure) su p, come nella patch atmosphere del tutorial damBreak della guida. Per capire se il riflusso c’è davvero, si controlla il segno del flusso sulla patch d’uscita: valori locali negativi di phi sull’uscita indicano fluido che rientra. La v14 introduce anche, come prototipo, meanInletOutlet, una variante scalare di inletOutlet in cui il valore di ingresso è la media dei valori delle celle adiacenti.
8.4 Novità di OpenFOAM 14: le field functions
Foundation v14 introduce le field functions, che possono inizializzare direttamente campi interni non uniformi. In casi appropriati questo può eliminare la necessità di un’utilità di inizializzazione separata. È un’anteprima avanzata, non un requisito del caso di riferimento attuale.
Estratto concettuale dall’esempio ufficiale di field function del tubo d’urto (shockTube)
internalField
{
type zonal;
defaultValue 1 [bar];
zones
{
lowPressure
{
type box;
box (0 -1 -1) (5 1 1);
value 0.1 [bar];
}
}
}
Si tratta di un esempio di un modello di pressione diverso, non di un sostituto per il 0/p del nostro canale (che usa la pressione cinematica). La condizione al contorno v14 functionalFixedValue consente in modo analogo valori basati su field functions.
Richiamo facoltativo · Campo non uniformeuniform indica un solo valore applicato ovunque nella regione del campo interessata. nonuniform fornisce tipicamente valori per cella o per faccia. Le field functions della v14 offrono un terzo modo, di livello più alto, per inizializzare distribuzioni a partire da regole geometriche o funzionali.
Approfondimento · Come si legge l’esempio zonal
L’esempio viene dal tutorial $FOAM_TUTORIALS/shockFluid/shockTube, un caso 1D comprimibile. internalField non è più un valore ma un sottodizionario con un type: zonal assegna valori diversi in zone diverse della mesh. defaultValue 1 [bar] vale ovunque fuori dalle zone; qui l’unità [bar] viene convertita in 105 Pa, coerentemente con le dimensioni [pressure] di quel campo. La zona lowPressure è generata al volo come zona di celle con un generatore di tipo box (le celle il cui centro cade nella scatola con angoli (0 −1 −1) e (5 1 1), in metri) e lì il valore è 0.1 [bar]. Il risultato è il classico salto di pressione iniziale del problema di Riemann.
Prima della v14 lo stesso risultato richiedeva un campo uniforme in 0/, una copia di riserva e l’esecuzione di setFields con un setFieldsDict; ora la definizione vive nel file di campo stesso ed è riproducibile senza passaggi aggiuntivi. setFields esiste ancora in v14.
Approfondimento · I tipi di field function e functionalFixedValue
| Tipo | Che cosa fa (guida v14, §6.1) |
|---|---|
zonal | Valori diversi in zone diverse della mesh, con un valore predefinito altrove. |
surfaces | Regioni separate da superfici (superfici di ricerca, file STL/OBJ); le celle tagliate ricevono valori frazionari, quindi un’interfaccia più liscia. |
coded | Valori definiti con codice compilato al volo, in un blocco evaluate (e update per l’aggiornamento nel tempo), con i riferimenti field, C (centri delle celle) e t (tempo). |
distanceFunction | Una Function1 della posizione lungo una direction data. |
fieldFunction | Una Function1 di un altro campo, per esempio una proprietà funzione della temperatura. |
timeFunction | Una Function1 del solo tempo. |
Esistono anche field functions applicative che sostituiscono vecchie utilità: atmosphericBoundaryLayerVelocity e le corrispondenti per k ed epsilon (al posto di setAtmBoundaryLayer), waveAlpha e waveVelocity (al posto di setWaves). L’esempio coded della guida, un flusso con rotazione, ha questa struttura:
internalField
{
type coded;
evaluate
#{
field = velocity(1, 0, 0) + (C ^ rate(2, 0, 0));
#};
}
Qui velocity(1, 0, 0) è un vettore con dimensioni di velocità e C ^ rate(2, 0, 0) il prodotto vettoriale tra la posizione del centro cella e una velocità angolare: una traslazione più una rotazione rigida. La stessa distribuzione si porta su una patch con functionalFixedValue, che riusa la definizione del campo interno attraverso la macro $internalField:
inlet
{
type functionalFixedValue;
value $internalField;
}
Secondo le note di rilascio, functionalFixedValue supporta inizialmente le funzioni zonal, distanceFunction e coded. Un’applicazione naturale al nostro canale sarebbe un profilo d’ingresso sviluppato invece del profilo piatto: per esempio l’approssimazione a prodotto di parabole u(y,z) = 2,25 Umean (1 − (2y′/H)²)(1 − (2z′/W)²), con y′ e z′ misurati dal centro della sezione, ha esattamente la media Umean (la media di ciascuna parabola è 2/3, e 2,25 × 4/9 = 1). Prima di scriverla in un caso reale, confronta la sintassi con l’esempio della guida v14 (§6.1 e §6.5) e con foamInfo functionalFixedValue.
9. Risoluzione dei problemi: diagnosticare il primo errore reale
Quando OpenFOAM segnala un errore di lettura di un campo, concentrati sul primo messaggio di errore informativo, sul percorso del file e sulla voce del dizionario incriminata. Correggi una causa alla volta.
| Sintomo | Causa probabile | Primo controllo |
|---|---|---|
| Manca la voce di una patch | Una patch della mesh non ha una condizione di campo corrispondente. | Confronta polyMesh/boundary con boundaryField. |
| Tipo di condizione di patch sconosciuto | Errore di battitura o condizione specifica di un modello non disponibile. | Controlla type, foamInfo e le condizioni disponibili. |
| Dimensioni sbagliate | Le dimensioni del campo non corrispondono a quelle che il modello si aspetta. | Controlla le dimensioni con nome e il modulo. |
| Atteso vettore / scalare | La forma del valore o la classe del campo sono sbagliate. | Controlla volVectorField rispetto a volScalarField. |
| Il parser si ferma a una riga successiva | Manca un punto e virgola o una parentesi graffa più in alto nel file. | Ispeziona l’intero blocco circostante. |
| Il caso gira ma è fisicamente sbagliato | Scelta sbagliata delle condizioni, della direzione, della geometria o dell’interpretazione della pressione. | Riconsidera la fisica, non solo la sintassi. |
Approfondimento · Come appaiono questi errori nel log
Il testo esatto dipende dalla versione e dal punto in cui l’errore viene rilevato, ma gli schemi seguenti sono quelli tipici della linea Foundation. Riconoscerli fa risparmiare molto tempo:
| Sintomo | Schema tipico del messaggio | Che cosa leggere |
|---|---|---|
| Voce di patch mancante | Cannot find patchField entry for walls | Il nome della patch mancante e il file (0/U o 0/p) |
| Tipo sconosciuto | Unknown patchField type noslip for patch walls | Segue l’elenco dei tipi validi: cerca il nome corretto (qui noSlip, con la S maiuscola) |
value mancante | keyword value is undefined in dictionary .../0/U/boundaryField/inlet | Il percorso indica la patch esatta |
| Atteso vettore | Expected a '(' while reading VectorSpace…, per esempio con value uniform 0.05; in 0/U | La riga indicata contiene un valore scalare dove serve un vettore |
| Vincolo incoerente | inconsistent patch and patchField types for patch type empty and patchField type zeroGradient | Il tipo nella mesh e il tipo nel campo |
| Dimensioni | messaggi che parlano di dimensioni diverse o incompatibili, con le due serie di esponenti stampate | Confronta gli esponenti con foamUnits |
Ogni errore fatale riporta anche file: … con il percorso del sottodizionario e un numero di riga. Per gli errori di sintassi (punto e virgola, parentesi) la riga indicata è quella in cui il parser si è accorto del problema, spesso molto dopo la causa.
Usare gli strumenti di documentazione
foamInfo fixedValue
foamInfo noSlip
foamInfo zeroGradient
foamToC -scalarBCs
foamToC -vectorBCs
foamUnits velocity
foamUnits kinematicPressure
In v14, foamInfo spiega il modello o la condizione, dove disponibile; foamToC elenca le opzioni di selezione a tempo di esecuzione compilate; foamUnits fornisce informazioni su dimensioni con nome e unità. Il loro output dipende dalle librerie installate e dall’ambiente.
Approfondimento · Che cosa aspettarsi da foamInfo, foamToC e foamUnits
foamInfo noSlipstampa l’intestazione documentata del sorgente della condizione (descrizione, uso con un esempio di voce) e l’elenco dei tutorial che la usano: un modo rapido per trovare un esempio funzionante da studiare.foamToC -scalarBCsefoamToC -vectorBCsinterrogano direttamente le librerie compilate e producono elenchi lunghi; filtrali, per esempiofoamToC -vectorBCs | grep -i slip. L’output difoamToCè più definitivo di quello difoamInfo, perché riflette ciò che è davvero caricabile.foamToC -search noSlipindica in quale tabella di selezione si trova una voce;-solver incompressibleFluidcarica le librerie di quel modulo prima di elencare.foamUnits velocityefoamUnits kinematicPressuremostrano gli esponenti corrispondenti ([0 1 −1 0 0 0 0] e [0 2 −2 0 0 0 0]) e le unità associate; senza argomenti,foamUnitselenca tutte le dimensioni con nome e le unità definite.
Tre esercizi di guasto controllato
- Errore A: cambia
wallsinwallsolo in0/U. Prevedi che cosa non corrisponderà più. Ripristina. - Errore B: rimuovi il punto e virgola dopo
dimensions [velocity]. Verifica se la lettura del dizionario fallisce; ripristina il file. - Errore C: imposta
0/pa[velocity]. Spiega perché le unità contraddicono il significato del campo. Ripristina.
Per ogni guasto registra: problema atteso, messaggio osservato, file di origine, correzione minima. Non modificare casi di produzione o di ricerca condivisi.
Approfondimento · Che cosa succede davvero nei tre guasti
Errore A — attenzione al gruppo wall. La previsione intuitiva è che la patch walls resti senza voce in 0/U e che la lettura si fermi con Cannot find patchField entry for walls. In OpenFOAM 14, però, ogni patch di tipo wall appartiene automaticamente al gruppo wall (sezione 3), e una voce chiamata wall in boundaryField viene interpretata come selezione di gruppo: la patch walls riceve comunque noSlip e il caso, con ogni probabilità, viene letto senza errori. È una lezione utile: un nome «sbagliato» può essere un nome valido con un altro significato. Per osservare davvero l’errore di voce mancante, usa un nome che non coincida con alcun gruppo, per esempio wals. Verifica entrambe le varianti e registra che cosa accade.
Errore B — la lettura non fallisce necessariamente. Una voce primitiva prosegue fino al primo ;: senza il punto e virgola, la voce dimensions assorbe anche la riga successiva e diventa [velocity] internalField uniform (0 0 0), mentre la chiave internalField sparisce. Il file resta un dizionario sintatticamente leggibile, quindi foamDictionary 0/U può funzionare; il guasto si vede con foamDictionary -entry dimensions -value 0/U (che stampa anche il resto della riga) e con foamDictionary -entry internalField 0/U, che fallisce perché la chiave non esiste più. Il solutore si fermerà con un errore sulla voce dimensions o sulla mancanza di internalField: in entrambi i casi la riga indicata non è quella del punto e virgola mancante.
Errore C — dimensioni. La pressione cinematica ha dimensioni [0 2 −2 0 0 0 0] (m²/s²), la velocità [0 1 −1 0 0 0 0] (m/s): il termine ∇p dell’equazione della quantità di moto deve avere le dimensioni di un’accelerazione (m/s²), e con p in m/s avrebbe dimensioni 1/s. OpenFOAM controlla la coerenza dimensionale: secondo le note di rilascio, in v14 il controllo avviene già alla lettura dei campi, altrimenti alla prima operazione che combina termini incompatibili. Il messaggio riporta le due serie di esponenti; il file da correggere è 0/p.
| Guasto | Problema atteso | Messaggio osservato | File di origine | Correzione minima |
|---|---|---|---|---|
| A | … | … | 0/U | wall → walls |
| B | … | … | 0/U | aggiungere ; |
| C | … | … | 0/p | [velocity] → [kinematicPressure] |
La tabella è un modello di registro: compila le colonne lasciate vuote con le tue previsioni e con i messaggi effettivamente osservati.
10. Esercizi e valutazione
Esercizio A — Leggere e classificare (guidato)
Senza eseguire il solutore, usa gli esempi completi di U e p e rispondi:
- Quale file contiene un campo vettoriale? Come lo sai?
- Quale voce descrive i valori all’interno delle celle? Quali voci descrivono le patch?
- Perché
internalField uniform (0 0 0)può coesistere con una velocità di ingresso di 0,05 m/s? - Dove è definito il riferimento della pressione?
- Quali tre identificatori devono corrispondere al file
boundarydella mesh?
Soluzione commentata · Esercizio A
0/U: lo diconoclass volVectorFieldnell’intestazione, le dimensioni[velocity]e la forma dei valori, sempre tra parentesi con tre componenti.0/pè unvolScalarFieldcon valori a una componente.internalFielddescrive i valori nelle celle; le voci dentroboundaryField(inlet,outlet,walls) descrivono le patch.- Perché il valore interno è solo la condizione iniziale (un’ipotesi di partenza), mentre la velocità d’ingresso è una condizione al contorno imposta sulle facce della patch
inletper tutta la durata del calcolo; i due dati hanno ruoli matematici diversi (sezioni 2 e 6). - In
0/p, alla patchoutlet:type fixedValue; value uniform 0;. inlet,outletewalls, scritti identici in entrambi i file.
Esercizio B — Modificare e prevedere (in parte guidato)
Cambia la velocità di ingresso prescritta in (0.08 0 0) m/s. Prima di eseguire qualsiasi cosa, indica:
- Quale file, quale voce e quale componente esatti devono cambiare?
- Qual è la nuova portata volumetrica media in ingresso, per un ingresso uniforme, se l’area di ingresso è 0,010 × 0,005 m²?
- Anche il valore interno iniziale deve essere cambiato?
- Perché un nuovo modulo della velocità richiede di riconsiderare il numero di Reynolds e il regime?
Punto di controllo per l’esercizio B
Per una velocità di ingresso normale uniforme di 0,08 m/s e un’area di 5,0 × 10−5 m²: Q = U A = 4,0 × 10−6 m³/s. Cambiare l’ipotesi iniziale interna è facoltativo; il valore al contorno d’ingresso è l’input di portata prescritto.
Soluzione commentata · Esercizio B
- File
0/U, voceboundaryField/inlet/value, componente x:uniform (0.05 0 0)diventauniform (0.08 0 0). In un solo comando:foamDictionary -entry boundaryField/inlet/value -set "uniform (0.08 0 0)" 0/U.0/pnon cambia. - Q = 0,08 × (0,010 × 0,005) = 0,08 × 5,0 × 10−5 = 4,0 × 10−6 m³/s (4 ml/s), come nel punto di controllo.
- No.
uniform (0 0 0)resta un’ipotesi iniziale valida; si può portarla a(0.08 0 0)per accorciare il transitorio, ma il risultato stazionario non cambia. - Perché Re = U Dh/ν cresce in proporzione: da ≈ 333 a ≈ 533. Il regime resta laminare, ma la lunghezza di sviluppo stimata sale a ≈ 178 mm, quasi il doppio del canale: l’ipotesi
zeroGradientall’uscita diventa meno accurata, la caduta di pressione cresce (≈ 5,6 × 10−3 m²/s² nel tratto sviluppato) e, con passo temporale fisso, il numero di Courant aumenta del 60 % (Parte 4). Più in generale, ogni modifica della velocità deve far verificare che le ipotesi del modello (laminare, nessun riflusso) restino vere.
Esercizio C — Costruire in autonomia (non guidato)
Partendo da una mesh del canale valida le cui patch si chiamano inlet, outlet e walls, scrivi 0/U e 0/p a partire da una cartella 0/ vuota. Requisiti:
- Flusso laminare incomprimibile lungo +x, con U all’ingresso = 0,06 m/s.
- Aderenza (no-slip) su tutte le facce solide del condotto.
- Un semplice riferimento di pressione cinematica in uscita pari a 0.
- Campi iniziali U e p uniformi e nulli.
- Ogni patch della mesh coperta esplicitamente in entrambi i file di campo.
Lista di accettazione
| Controllo | Evidenza attesa |
|---|---|
| Struttura | Entrambi i file di campo contengono un’intestazione FoamFile valida e le chiavi di campo richieste. |
| Tipi | U è volVectorField; p è volScalarField. |
| Dimensioni | Le dimensioni con nome corrispondono alla formulazione incomprimibile scelta. |
| Copertura delle patch | Tutti e tre i nomi delle patch della mesh compaiono in entrambi i dizionari boundaryField. |
| Fisica | Le condizioni di campo sono coerenti con il problema idealizzato del canale descritto. |
| Interpretazione | Sai spiegare ogni voce al contorno senza ricorrere a un foglio delle soluzioni. |
L’obiettivo non è ancora ottenere una particolare curva di caduta di pressione. Questa parte valuta l’alfabetizzazione nella configurazione, non la validazione completa di un modello di ricerca.
Soluzione di riferimento · Esercizio C, con le verifiche della lista
0/U:
FoamFile
{
version 2.0;
format ascii;
class volVectorField;
location "0";
object U;
}
dimensions [velocity];
internalField uniform (0 0 0);
boundaryField
{
inlet
{
type fixedValue;
value uniform (0.06 0 0);
}
outlet
{
type zeroGradient;
}
walls
{
type noSlip;
}
}
0/p è identico a quello della sezione 5: [kinematicPressure], uniform 0, zeroGradient su inlet e walls, fixedValue con uniform 0 su outlet. Grandezze di controllo: Q = 0,06 × 5,0 × 10−5 = 3,0 × 10−6 m³/s, Re ≈ 400, lunghezza di sviluppo ≈ 133 mm, Δp/ρ nel tratto sviluppato ≈ 4,2 × 10−3 m²/s².
Ogni riga della lista di accettazione ha un comando che produce l’evidenza:
foamDictionary -entry FoamFile/class -value 0/U # volVectorField
foamDictionary -entry FoamFile/class -value 0/p # volScalarField
foamDictionary -entry dimensions -value 0/U # [velocity]
foamDictionary -entry dimensions -value 0/p # [kinematicPressure]
foamDictionary -entry boundaryField -keywords 0/U # inlet outlet walls
foamDictionary -entry boundaryField -keywords 0/p # inlet outlet walls
foamDictionary -entry boundaryField/inlet/value -value 0/U # uniform (0.06 0 0)
Le righe «Fisica» e «Interpretazione» non hanno un comando: si verificano spiegando a voce, patch per patch, perché ogni condizione è quella giusta, con gli argomenti delle sezioni 4–6.
Appendice A. Mesh di riferimento minima per una prova indipendente
Se la Parte 2 non ha lasciato una mesh compatibile, il seguente system/blockMeshDict 3D a blocco singolo crea esattamente i nomi di patch usati in tutta questa parte. Tutte le coordinate sono in metri.
FoamFile
{
version 2.0;
format ascii;
class dictionary;
location "system";
object blockMeshDict;
}
units [m];
vertices
(
(0 0 0) // 0
(0.100 0 0) // 1
(0.100 0.010 0) // 2
(0 0.010 0) // 3
(0 0 0.005) // 4
(0.100 0 0.005) // 5
(0.100 0.010 0.005) // 6
(0 0.010 0.005) // 7
);
blocks
(
hex (0 1 2 3 4 5 6 7) (40 12 8) simpleGrading (1 1 1)
);
edges ();
boundary
(
inlet
{
type patch;
faces ((0 4 7 3));
}
outlet
{
type patch;
faces ((1 2 6 5));
}
walls
{
type wall;
faces
(
(0 1 5 4)
(3 7 6 2)
(0 3 2 1)
(4 5 6 7)
);
}
);
mergePatchPairs ();
La mesh contiene 40 × 12 × 8 = 3840 celle esaedriche. Le quattro facce lunghe condividono la patch walls. Questa definizione della mesh è sufficiente per blockMesh e checkMesh; non è un caso CFD completo ed eseguibile senza i restanti dizionari del solutore e le proprietà.
Approfondimento · Verificare l’orientamento delle facce e il minimo indispensabile per blockMesh
Ogni faccia di contorno deve essere elencata in modo che, applicando la regola della mano destra all’ordine dei vertici, la normale punti fuori dal blocco. Per l’ingresso (0 4 7 3): 0→4 è +z, 4→7 è +y, e z × y = −x, verso l’esterno sul piano x = 0. Per l’uscita (1 2 6 5): +y poi +z, y × z = +x. Per le pareti: (0 1 5 4) dà −y, (3 7 6 2) dà +y, (0 3 2 1) dà −z, (4 5 6 7) dà +z. Tutte puntano all’esterno, e il blocco hex (0 1 2 3 4 5 6 7) è destrorso (la faccia 0-1-2-3 percorsa in senso antiorario vista da +z, con 4-5-6-7 sopra). blockMesh segnala le facce orientate male; checkMesh le rileva come facce di contorno non chiuse o volumi negativi.
units [m]; è il controllo delle unità di blockMesh introdotto in v14 (nella Parte 2 si usa units [mm]; con coordinate in millimetri; entrambe le forme sostituiscono il vecchio scale). Per eseguire blockMesh servono anche un system/controlDict minimo e la cartella constant/; la sequenza completa per la sola mesh è nella Parte 2. Celle risultanti: 2,5 mm in x, 0,833 mm in y, 0,625 mm in z.
Appendice B. Tabella di interpretazione delle voci
| Voce | Significato | Esempio in questa parte |
|---|---|---|
FoamFile.class | Tipo di oggetto da leggere | volVectorField per U |
FoamFile.object | Nome dell’oggetto campo | U o p |
dimensions | Dimensioni fisiche | [velocity] |
internalField | Valori iniziali nelle celle | uniform (0 0 0) |
boundaryField | Condizioni specifiche per patch | inlet, outlet, walls |
type fixedValue | Valore del campo prescritto | U all’ingresso |
type zeroGradient | Gradiente normale nullo | p all’ingresso |
type noSlip | Velocità di parete nulla | U sulle pareti ferme |
Appendice C. Fonti e letture di approfondimento
Tutta la sintassi e le funzioni specifiche della v14 in questa parte si basano sulla User Guide v14 di OpenFOAM Foundation / CFD Direct. La documentazione delle release di OpenFOAM.com appartiene a una distribuzione separata e non va sostituita senza verificarne la compatibilità.
- Panoramica della User Guide —
doc.cfd.direct/openfoam/user-guide-v14/ - 4.2 Formato dei file di input/output —
doc.cfd.direct/openfoam/user-guide-v14/basic-file-format - 5.4 blockMesh —
doc.cfd.direct/openfoam/user-guide-v14/blockmesh - 6.1 Field functions —
doc.cfd.direct/openfoam/user-guide-v14/field-functions - 6.3 Introduzione alle condizioni al contorno —
doc.cfd.direct/openfoam/user-guide-v14/boundary-conditions - 6.4 Condizioni al contorno derivate —
doc.cfd.direct/openfoam/user-guide-v14/derived-boundary-conditions - 4.7 Strumenti di gestione del caso —
doc.cfd.direct/openfoam/user-guide-v14/case-management - Note di rilascio di OpenFOAM 14 —
openfoam.org/release/14/
Pagine della guida v14 citate negli approfondimenti:
- 5.3 Contorno della mesh (tipi di patch, gruppi)
- 6.2 Field sources (la voce facoltativa
sourcesdei file di campo) - 6.5 Field functions nelle condizioni al contorno (
functionalFixedValue) - 2.1 Gradino all’indietro (tutorial
incompressibleFluidcon[kinematicPressure])
Approfondimento · La voce facoltativa sources nei file di campo
Oltre a dimensions, internalField e boundaryField, la guida v14 elenca una quarta voce facoltativa dei file di campo: sources. Serve quando un modello di sorgente in constant/fvModels introduce fluido all’interno del dominio (per esempio un volumeSource): il campo deve sapere quale valore ha il fluido iniettato, per esempio la sua velocità. sources è un dizionario con una voce per ogni sorgente, con lo stesso nome del modello in fvModels, e ciascuna voce usa una condizione come uniformFixedValue con uniformValue. Il nostro canale non ha sorgenti interne, quindi la voce è assente; è utile saperla riconoscere quando la si incontra in un tutorial.
Prossima unità · Parte 4 — controlDict e controllo della simulazione
Hai definito quali campi esistono e che cosa accade ai loro contorni. La parte successiva spiega come OpenFOAM avvia, fa avanzare e scrive una simulazione, e come queste impostazioni compaiono in system/controlDict.
Parte successiva: OpenFOAM 14, parte 4: controlDict e controllo della simulazione. Torna all’indice del percorso Imparare OpenFOAM 14.