OpenFOAM 14, parte 1: anatomia di un caso e linguaggio dei dizionari
Con questo articolo inizia la seconda fase del percorso Imparare OpenFOAM 14. La prima fase insegnava ad accedere all’ambiente di calcolo e a eseguire un flusso di lavoro CFD già preparato. Questa fase cambia la domanda: da «come eseguo questo caso?» a «perché questo caso ha proprio questi file, e come li costruirei da solo?». È la Parte 1 di 8 della serie sulla costruzione del caso.
Il riferimento è OpenFOAM 14 della distribuzione OpenFOAM Foundation / CFD Direct. Parte della sintassi descritta qui è specifica della versione 14, in particolare il trattamento attuale di dimensioni con nome, unità e configurazione globale.
Obiettivo principale
Alla fine di questa parte dovresti saper aprire un file di input OpenFOAM mai visto, identificarne gli elementi strutturali, collocarlo nell’architettura del caso e usare la documentazione ufficiale o gli strumenti da riga di comando per indagare le voci che ancora non conosci.
0. Prima di cominciare
0.1 Che cosa si dà per scontato
- Come accedere al server Linux e aprire una shell.
- La navigazione di base con
cd,pwdels. - Come eseguire un semplice caso OpenFOAM già preparato.
- L’idea generale che un caso CFD contiene una mesh, dei campi, delle proprietà fisiche e dei controlli del solutore.
0.2 Che cosa non serve ancora sapere
- La derivazione completa ai volumi finiti delle equazioni di governo.
- Come scegliere lo schema numerico ottimale per un problema di ricerca.
- Tutte le condizioni al contorno e tutti i modelli di turbolenza disponibili.
- Lo sviluppo del codice sorgente C++ di OpenFOAM.
0.3 Contenuto
- Il modello mentale di un caso OpenFOAM
- I tre livelli strutturali: system, constant e cartelle temporali
- L’intestazione FoamFile
- La sintassi dei dizionari: parole chiave, valori, graffe e punti e virgola
- Tipi di dato: parole, stringhe, scalari, vettori, tensori e liste
- Dimensioni e unità in OpenFOAM 14
- I file di campo: una forma speciale ma coerente di dizionario
- Macro, include, variabili d’ambiente ed espressioni regolari
- Come OpenFOAM legge la configurazione e risolve le sovrascritture
- Strumenti di ispezione: comandi di shell e foamDictionary
- Laboratorio guidato: costruire e ispezionare un dizionario innocuo
- Esercizio di lettura: classificare un caso reale
- Esercizi autonomi
- Checklist delle competenze e riferimento rapido
- Note sugli esercizi e osservazioni attese
- Riferimenti ufficiali
1. Il modello mentale di un caso OpenFOAM
Un caso OpenFOAM è un albero di cartelle che descrive una simulazione. Non è un unico file di progetto. File diversi descrivono livelli diversi del problema, e le applicazioni OpenFOAM leggono solo le informazioni di cui hanno bisogno.
Il primo modello mentale utile è dividere il caso in tre domande:
| Posizione | Domanda a cui risponde | Contenuto tipico |
|---|---|---|
system/ | Come deve essere eseguita la simulazione e come vanno trattate numericamente le equazioni? | controlDict, fvSchemes, fvSolution e altra configurazione di esecuzione |
constant/ | Che cosa contiene il sistema fisico? | Dati della mesh, proprietà dei materiali, configurazione del trasporto e dei modelli fisici |
| cartelle temporali | Quanto valgono i campi a un certo istante simulato? | Campi iniziali e risultati successivi, per esempio 0/U, 0/p, 1/U |
Idea chiave
I nomi delle cartelle hanno un significato. system riguarda la procedura di soluzione e il controllo dell’esecuzione; constant riguarda la mesh e i dati fisici e di modello; una cartella temporale contiene lo stato dei campi a un certo tempo simulato.
1.1 Un albero di caso minimo
trainingChannel/
|-- 0/
| |-- U
| `-- p
|-- constant/
| |-- physicalProperties
| |-- momentumTransport
| `-- polyMesh/
| |-- points
| |-- faces
| |-- owner
| |-- neighbour
| `-- boundary
`-- system/
|-- controlDict
|-- fvSchemes
`-- fvSolution

1.2 Un file viene letto perché un’applicazione ne ha bisogno
OpenFOAM è una raccolta di applicazioni e librerie. Un’utility di mesh, un modulo solutore e un’applicazione di post-processing non leggono necessariamente gli stessi file. La presenza di un file in un caso ha quindi senso solo in relazione all’applicazione o al modello che lo usa.
Questo evita un errore tipico dei principianti: pensare che ogni caso OpenFOAM debba contenere esattamente gli stessi file. L’architettura a tre cartelle è stabile, ma il contenuto cambia con il problema.
1.3 Una cartella non coincide con un concetto fisico
La cartella constant non significa «numeri che non cambiano mai durante la simulazione». È il posto standard per la mesh e per la configurazione che descrive proprietà fisiche e modelli. Alcuni dati di modello possono comunque dipendere dalla temperatura, dalla composizione o da altre variabili.
Allo stesso modo, 0 non è in astratto una speciale cartella «condizioni iniziali» codificata nel programma. Normalmente è la cartella temporale che corrisponde al tempo zero della simulazione, e di solito la si usa per fornire i valori iniziali dei campi e le condizioni al contorno.
1.4 I sei livelli da imparare a separare
| Livello | Esempio tipico | Domanda |
|---|---|---|
| Geometria / mesh | constant/polyMesh | Dove sono le celle e le patch di contorno? |
| Definizione dei campi | 0/U, 0/p | Quali variabili esistono e come sono inizializzate? |
| Modello fisico | constant/physicalProperties | Quale materiale e quale comportamento del modello sono rappresentati? |
| Discretizzazione | system/fvSchemes | Come sono approssimati gli operatori differenziali? |
| Soluzione algebrica | system/fvSolution | Come vengono risolti i sistemi di equazioni risultanti? |
| Controllo dell’esecuzione | system/controlDict | Quando parte e si ferma il calcolo e quando vengono scritti i dati? |
Le prossime parti della serie tratteranno questi livelli separatamente. Per ora il compito è riconoscere a quale livello appartiene un file.
2. I tre livelli strutturali
2.1 La cartella system
La cartella system contiene le impostazioni legate alla procedura di soluzione e all’esecuzione del caso. Secondo la User Guide di OpenFOAM v14, un caso di base contiene almeno controlDict, fvSchemes e fvSolution in questa cartella.
controlDict controlla l’esecuzione della simulazione e la scrittura dei dati. Concetti tipici sono il tempo di inizio, la condizione di fine, il passo temporale e l’intervallo di output. Viene trattato nel dettaglio nella Parte 4.
fvSchemes seleziona gli schemi numerici di discretizzazione per derivate temporali, gradienti, termini di divergenza, laplaciani, interpolazione e operatori ai volumi finiti collegati. Viene trattato nel dettaglio nella Parte 5.
fvSolution configura i solutori delle equazioni lineari, le tolleranze, il rilassamento e i controlli dell’accoppiamento pressione-velocità come le impostazioni SIMPLE o PIMPLE. Viene trattato nel dettaglio nella Parte 6.
Non mescolare questi tre ruolicontrolDict controlla l’esecuzione, fvSchemes la discretizzazione e fvSolution la soluzione algebrica e le impostazioni degli algoritmi. Sono collegati ma non intercambiabili.
2.2 La cartella constant
La cartella constant contiene la mesh completa in constant/polyMesh insieme alla configurazione delle proprietà fisiche e dei modelli richiesta dal modulo solutore scelto. Per un semplice caso incomprimibile sono tipici file come physicalProperties e momentumTransport, ma i requisiti esatti dipendono dal problema.
constant/
|-- polyMesh/
| |-- points
| |-- faces
| |-- owner
| |-- neighbour
| `-- boundary
|-- physicalProperties
`-- momentumTransport
Normalmente polyMesh si genera con un’utility di mesh invece di scriverne a mano tutti i file. La Parte 2 di questa serie usa blockMeshDict per costruire una mesh semplice.
2.3 Le cartelle temporali
Le cartelle temporali contengono i file dei campi a un certo tempo simulato. All’inizio di un caso, 0/ contiene di solito i valori iniziali e le condizioni al contorno. Durante il calcolo, OpenFOAM scrive le cartelle temporali successive secondo i controlli di output.
0/
|-- U
`-- p
0.1/
|-- U
`-- p
0.2/
|-- U
`-- p
I campi di OpenFOAM vanno inizializzati anche nei casi in cui la soluzione stazionaria non richiede matematicamente uno stato iniziale transitorio. Per questo anche un caso stazionario contiene normalmente una cartella 0 con i file dei campi.
2.4 Dati generati e configurazione dell’utente
Alcuni file sono scritti principalmente dall’utente, altri sono generati dalle applicazioni. La distinzione conta quando si diagnostica un caso.
| Elemento | Di solito creato da | Trattamento tipico |
|---|---|---|
system/controlDict | Utente o modello copiato | Si legge e si modifica direttamente |
system/fvSchemes | Utente o modello copiato | Si legge e si modifica direttamente |
system/fvSolution | Utente o modello copiato | Si legge e si modifica direttamente |
constant/polyMesh/* | Utility di mesh | Si ispeziona; nel lavoro normale si rigenera invece di modificarlo a mano |
0/U, 0/p | Utente / strumento di inizializzazione | Si modificano o si generano le condizioni iniziali |
| cartelle temporali successive | Solutore | Sono risultati; normalmente non si modificano a mano |
3. L’intestazione FoamFile
Ogni file di dati letto o scritto dal framework comincia con un dizionario chiamato FoamFile. L’intestazione identifica il formato di I/O, la classe dell’oggetto e il nome dell’oggetto. Voci facoltative possono indicare anche la versione e la posizione.
FoamFile
{
format ascii;
class dictionary;
location "system";
object controlDict;
}
3.1 Le voci dell’intestazione
| Voce | Significato | Valori tipici / note |
|---|---|---|
version | Versione del formato di I/O | Facoltativa; nella documentazione attuale il valore predefinito è 2.0 |
format | Come sono codificati i dati | ascii o binary |
class | Classe di oggetto/dati OpenFOAM | dictionary, volScalarField, volVectorField, ecc. |
object | Nome dell’oggetto/file | Per esempio controlDict, U, p |
location | Percorso del file relativo al caso | Facoltativa; per esempio "system" o "0" |
3.2 Classe dizionario e classe di campo
Un file come controlDict è strutturalmente un dizionario:
class dictionary;
object controlDict;
Un campo di velocità appartiene a una classe OpenFOAM diversa:
class volVectorField;
object U;
La classe dice che tipo di struttura dati si aspetta OpenFOAM. Un file di campo quindi non si capisce guardando solo il nome del file: l’intestazione dà un indizio molto più forte.
3.3 Un’abitudine di lettura utile
Quando apri un file OpenFOAM sconosciuto, leggi per primo il blocco FoamFile. Prima di interpretare le singole parole chiave, rispondi a queste domande:
- Di che classe è questo oggetto?
- Quale oggetto rappresenta?
- Dove si trova il file nel caso?
- È probabilmente configurazione dell’utente, un campo o un dato generato?
4. La sintassi dei dizionari
4.1 Input a formato libero
L’input di OpenFOAM è a formato libero. Le colonne non contano e in generale gli a capo non chiudono le voci. Gli spazi si possono quindi scegliere per la leggibilità.
deltaT 0.001;
// Stesso significato di:
deltaT 0.001;
4.2 La voce fondamentale: parola chiave più dato
keyword data;
La maggior parte della configurazione è costruita, alla fine, su questo schema. La parola chiave serve a cercare il dato associato. Il punto e virgola finale fa parte della sintassi delle voci ordinarie.
4.3 Perché il punto e virgola conta
Il punto e virgola mancante è tra gli errori più semplici e più istruttivi. Siccome gli a capo non chiudono le istruzioni, OpenFOAM continua a leggere e alla fine incontra un token che non torna con la grammatica attesa.
// Corretto
myValue 42;
// Sbagliato
myValue 42
nextValue 7;
Abitudine di debug
Quando OpenFOAM segnala un errore di lettura vicino a una parola chiave, controlla anche la riga immediatamente precedente. Il vero errore può essere un punto e virgola o una graffa di chiusura mancante più sopra nel file.
4.4 Sotto-dizionari
Un dizionario può contenere un altro dizionario. Il blocco annidato ha un nome ed è racchiuso tra parentesi graffe.
solvers
{
p
{
solver GAMG;
tolerance 1e-7;
relTol 0.01;
}
}
Leggilo prima strutturalmente e poi numericamente: solvers contiene un sotto-dizionario chiamato p, che contiene tre voci ordinarie.
4.5 Commenti
// Tutto ciò che segue // su questa riga è un commento.
deltaT 0.001; // Anche questo è un commento.
/*
Questo è un commento su più righe.
OpenFOAM ignora il testo racchiuso.
*/
I commenti sono importanti quando si impara dai casi tutorial, ma ricorda che foamDictionary normalmente stampa il contenuto logico del dizionario senza conservare i commenti ordinari.
4.6 Graffe, tonde e quadre sono cose diverse
| Delimitatore | Ruolo tipico | Esempio |
|---|---|---|
{} | Dizionario o sotto-dizionario | boundaryField { ... } |
() | Lista o dato di tipo vettoriale | (1 0 0) o (inlet outlet) |
[] | Dimensioni o unità | [velocity], [m/s], [kg m^-3] |
I delimitatori non sono decorazione
Una parte molto grande della sintassi di OpenFOAM diventa leggibile appena si capisce se un blocco è un dizionario {}, una lista () o un’informazione dimensionale o di unità [].
5. I tipi di dato che incontrerai
5.1 Parole e stringhe
Una parola (word) è un token usato per nomi e selezioni. Una stringa è racchiusa tra virgolette doppie e può contenere caratteri o spazi che non sarebbero validi in una parola semplice.
solver GAMG;
location "system";
Non dare per scontato che ogni token senza virgolette sia testo arbitrario. Molte parole chiave si aspettano un valore preso da una tabella di selezione a run-time, altre un percorso, una parola o un tipo numerico.
5.2 Scalari
Uno scalare è un singolo valore numerico.
deltaT 0.001;
tolerance 1e-7;
La notazione scientifica è comune e va letta normalmente: 1e-7 significa 0,0000001.
5.3 Vettori
Un vettore ha tre componenti e usa la sintassi delle liste tra parentesi tonde.
(1 0 0)
Per un vettore velocità in un sistema di coordinate cartesiane, le tre voci corrispondono alle componenti x, y e z. Il significato viene dal contesto: la stessa sintassi può rappresentare qualunque grandezza vettoriale.
5.4 Tensori e tensori simmetrici
Un tensore generale contiene nove componenti. Un tensore simmetrico ne memorizza solo sei indipendenti. Non serve ancora memorizzarne l’ordine, ma devi riconoscerli come dati numerici strutturati e non come lunghe liste di valori scollegati.
// Tensore generale: 9 valori
(1 0 0 0 1 0 0 0 1)
// Tensore simmetrico: 6 valori indipendenti
(1 0 0 1 0 1)
5.5 Liste
Le liste sono racchiuse tra parentesi tonde. Nell’input dell’utente spesso la lunghezza della lista si omette, mentre l’output di OpenFOAM può scrivere esplicitamente un conteggio prima della lista.
patches
(
inlet
outlet
walls
);
3
(
inlet
outlet
walls
)
Sono due forme di lista che puoi incontrare. Il contesto determina il tipo di elemento atteso.
5.6 I dati annidati sono la norma
Un file di caso realistico combina tipi di dato diversi. Non cercare di interpretare tutto il file in una volta: scomponilo in livelli.
example
{
name channelA;
scale 0.001;
direction (1 0 0);
patches
(
inlet
outlet
walls
);
}
Questo esempio è semplicemente un sotto-dizionario che contiene una parola, uno scalare, un vettore e una lista.
6. Dimensioni e unità in OpenFOAM 14
OpenFOAM associa dimensioni alle grandezze fisiche ed esegue controlli di coerenza dimensionale. La versione 14 dà particolare risalto, nella configurazione dei casi, a dimensioni e unità con nome. È uno dei campi in cui conviene preferire la documentazione v14 agli esempi più vecchi che si trovano in rete.
6.1 Le dimensioni rispondono a: che tipo di grandezza fisica è?
Le dimensioni descrivono le potenze delle sette dimensioni fisiche di base. La vecchia forma a esponenti è ancora valida ed è importante saperla riconoscere:
[0 1 -1 0 0 0 0]
Corrisponde a una lunghezza divisa per un tempo, cioè a una velocità. I casi di esempio di OpenFOAM 14 preferiscono, dove disponibili, le dimensioni con nome:
[velocity]
Altri esempi utili sono [pressure] e [kinematicViscosity]. Le dimensioni con nome sono più facili da leggere e riducono la fatica di contare gli esponenti.
6.2 Le unità rispondono a: in quale unità di misura è dato il valore?
Un valore può essere seguito, facoltativamente, da un’unità. OpenFOAM converte il valore nel sistema di unità di base attivo e controlla che l’unità fornita abbia le dimensioni corrette.
rho 1000 [kg m^-3];
nu 10 [cSt];
Il secondo esempio è particolarmente utile: i centistokes vengono convertiti nelle unità di base interne, mentre OpenFOAM verifica che cSt abbia le dimensioni di una viscosità cinematica.
6.3 Proprietà dimensionate in v14
Gli esempi attuali della v14 usano spesso una sintassi compatta in cui le dimensioni della proprietà sono note al codice e l’utente fornisce solo il valore, eventualmente con l’unità.
rho 1000;
nu 1e-5;
Non dare per scontato che un vecchio tutorial con il vettore numerico delle dimensioni esplicito per ogni proprietà rappresenti lo stile preferito in v14. La sintassi vecchia può aiutare a leggere casi datati, ma il materiale didattico nuovo dovrebbe seguire le convenzioni della v14.
6.4 Dimensioni dei campi
I file di campo descrivono esplicitamente le dimensioni del campo. Per la velocità, una voce in stile v14 è:
dimensions [velocity];
Per i campi di tipo pressione le dimensioni esatte dipendono dalla formulazione. Non dedurre mai il significato fisico di un campo solo dal nome del file: controlla il modulo solutore scelto e la definizione del campo.
6.5 L’utility foamUnits
OpenFOAM 14 fornisce foamUnits, un’applicazione per elencare dimensioni e unità, ispezionare un’unità specifica e calcolare fattori di conversione.
foamUnits
foamUnits power
foamUnits cal
foamUnits -all
Usala quando non sei sicuro che un’unità con nome esista o di quali dimensioni rappresenti. È più sicuro che affidarsi alla memoria o a un esempio trovato in rete che non c’entra.
6.6 Configurazione delle unità globale e a livello di caso
In OpenFOAM 14 i controlli globali sono in $FOAM_ETC/configDict. Un caso può sovrascrivere alcuni controlli con system/configDict. Il file globale contiene, tra l’altro, l’insieme di unità attivo e le definizioni di conversione.
cat $FOAM_ETC/configDict
In questo corso non serve modificare la configurazione globale. Il punto importante è riconoscere che la v14 usa configDict per i controlli globali e ammette sovrascritture a livello di caso.
Regola della versione 14 per questo corso
Quando esiste una differenza di sintassi tra un vecchio tutorial e la User Guide v14, il riferimento sono la User Guide v14 e gli strumenti di OpenFOAM 14 installati.
7. I file di campo: file speciali con lo stesso linguaggio
I file di campo come U e p stanno nelle cartelle temporali. Usano lo stesso linguaggio generale dei dizionari, ma la loro classe e le voci obbligatorie descrivono un campo distribuito sulla mesh.
7.1 Un esempio minimo di campo di velocità
FoamFile
{
format ascii;
class volVectorField;
object U;
}
dimensions [velocity];
internalField uniform (0 0 0);
boundaryField
{
inlet
{
type fixedValue;
value uniform (0.5 0 0);
}
outlet
{
type zeroGradient;
}
walls
{
type noSlip;
}
}
È un campo di velocità semplificato, usato solo per illustrare la struttura. La scelta delle condizioni al contorno è trattata nella Parte 3.
7.2 Le quattro voci strutturali importanti
| Voce | Ruolo |
|---|---|
dimensions | Dimensioni fisiche del campo |
internalField | Valori nel campo interno della mesh; in un file 0 scritto dall’utente spesso è un valore iniziale uniforme |
boundaryField | Sotto-dizionario con le condizioni del campo per le patch di contorno della mesh |
sources | Inizializzazione/configurazione facoltativa delle sorgenti del campo, nei casi che usano sorgenti interne |
7.3 Uniforme e non uniforme
Spesso l’utente inizializza un campo con un unico valore uniforme:
internalField uniform (0 0 0);
L’output del solutore in genere è non uniforme, perché celle diverse contengono valori diversi. Un risultato scritto può quindi contenere una lista con un valore per ogni elemento del campo.
internalField nonuniform List<scalar>
4
(
0.12
0.15
0.18
0.17
);
L’esempio è volutamente corto. Le liste dei risultati reali possono contenere migliaia o milioni di valori.
7.4 Tipo di patch della mesh e condizione al contorno del campo
Distinzione fondamentale
La mesh ha patch di contorno con tipi geometrici/topologici memorizzati in constant/polyMesh/boundary. Ogni campo assegna poi a quelle patch una condizione al contorno nel proprio boundaryField. Sono cose collegate, ma non la stessa cosa.
Per esempio, una patch della mesh chiamata walls può essere di tipo wall, mentre il campo di velocità U applica a quella patch la condizione noSlip. Un campo di pressione può applicare alla stessa patch una condizione diversa.
7.5 I nomi delle patch devono corrispondere alla mesh
Quando un file di campo nomina direttamente una patch di contorno, il nome deve corrispondere a una patch della mesh. OpenFOAM supporta anche gruppi di patch e corrispondenze con espressioni regolari, che vedrai più avanti in questo articolo e di nuovo nella Parte 3.
8. Macro, include, variabili d’ambiente ed espressioni regolari
I dizionari OpenFOAM possono evitare ripetizioni e condividere configurazione. Non serve padroneggiare subito tutti i meccanismi, ma devi riconoscere i più comuni quando leggi casi reali.
8.1 Espansione di macro con $
Un valore o una voce di dizionario si può riusare con l’espansione di macro. Un semplice esempio concettuale:
referenceValue 0.25;
selectedValue $referenceValue;
Nei dizionari annidati le macro sono molto usate per riusare impostazioni dei solutori o definizioni di schemi condivise. Le prossime parti mostreranno esempi reali in fvSchemes e fvSolution.
8.2 Includere un altro file
#include "studentValues"
Il file incluso viene letto come se il suo contenuto fosse scritto nel punto dell’inclusione. Se si trova in un’altra cartella, il percorso può usare variabili d’ambiente, per esempio:
#include "$FOAM_CASE/constant/initialConditions"
Due varianti che puoi incontrare sono #includeIfPresent e #includeEtc. I nomi ne dicono lo scopo: inclusione condizionale e inclusione relativa alle cartelle di configurazione di OpenFOAM.
8.3 Variabili d’ambiente
Le variabili d’ambiente possono comparire dentro percorsi e stringhe. Quelle comuni in OpenFOAM sono:
| Variabile | Significato |
|---|---|
$FOAM_CASE | Percorso del caso in esecuzione |
$FOAM_CASENAME | Nome della cartella del caso corrente |
$FOAM_APPLICATION | Nome dell’applicazione in esecuzione |
$FOAM_TUTORIALS | Cartella dei casi tutorial installati |
$FOAM_ETC | Cartella di configurazione di OpenFOAM |
echo $FOAM_TUTORIALS
echo $FOAM_ETC
8.4 Espressioni regolari nella ricerca delle parole chiave
Alcune ricerche nei dizionari ammettono un’espressione regolare tra virgolette che corrisponde a più nomi. È comune nella configurazione dei campi al contorno e nelle impostazioni dei solutori.
".*Wall"
{
type noSlip;
}
Lo schema .*Wall significa «qualunque carattere seguito da Wall». Potrebbe quindi corrispondere a nomi come upperWall e lowerWall.
"(upper|lower)Wall"
{
type noSlip;
}
Questo secondo schema è più specifico e corrisponde a upperWall o lowerWall. Non aggiungere espressioni regolari complesse se non rendono davvero il file più chiaro.
8.5 Input con codice avanzato: riconoscerlo, non usarlo ancora
OpenFOAM 14 include un sistema di input con codice ampiamente aggiornato, con direttive come #calc, #codeBlock, #stream, #codeDict e #print. Sono potenti, ma sono volutamente fuori dagli obiettivi pratici della Parte 1.
Per ora
Se vedi una direttiva con codice, identificala come meccanismo di input avanzato e consulta la documentazione v14. Non sostituire una semplice voce di dizionario con codice a run-time se non c’è un motivo chiaro.
9. Come viene risolta la configurazione
9.1 L’ordine delle parole chiave di solito non conta
Per le normali parole chiave distinte di un dizionario l’ordine in genere non è significativo. OpenFOAM cerca le voci per parola chiave e non per posizione della riga.
9.2 Parole chiave duplicate: vince l’ultima
Quando la stessa parola chiave compare più volte nello stesso contesto di dizionario, la definizione successiva sovrascrive la precedente. È un comportamento utile con macro e include.
relTol 0.05;
relTol 0;
Il valore effettivo è l’ultimo. Così si può importare un insieme comune di impostazioni e sovrascriverne localmente un parametro.
9.3 La parola chiave esatta ha la precedenza sulle espressioni regolari
Se sia una parola chiave esatta sia una voce con espressione regolare possono corrispondere a una ricerca, la parola chiave esatta ha la precedenza. Diventa importante quando una regola generale è seguita da una regola specifica per una patch o un campo.
9.4 Controlli globali e sovrascritture locali
OpenFOAM 14 legge la configurazione globale da $FOAM_ETC/configDict. File configDict a livello di utente o di caso possono sovrascrivere alcune impostazioni con una precedenza definita. È un altro motivo per diagnosticare un caso chiedendosi non solo «che cosa c’è in questo file?» ma anche «questo valore potrebbe essere ereditato o sovrascritto altrove?».
9.5 La domanda di debug più utile
Chiediti prima questo
Quale parola chiave esatta sta cercando di leggere l’applicazione, da quale dizionario, e che tipo di dato si aspetta?
Questa domanda trasforma molti messaggi di errore lunghi in una piccola indagine: file → dizionario → parola chiave → tipo atteso → valore fornito.
10. Strumenti di ispezione
Un buon utente di OpenFOAM non si affida solo a un editor di testo. La shell e gli strumenti di gestione del caso di OpenFOAM rispondono rapidamente a domande strutturali.
10.1 Ispezione di base dalla shell
pwd
ls
find . -maxdepth 2 -type f | sort
less system/controlDict
grep -n "FoamFile" system/*
Questi comandi rispondono a domande di base: dove mi trovo, quali file esistono e dove compare un certo token. Per leggere usa less invece di cat quando un file è lungo.
10.2 foamDictionary
foamDictionary interpreta la sintassi dei dizionari OpenFOAM. È più utile dell’ispezione testuale grezza quando vuoi conoscere la struttura logica effettiva delle voci.
foamDictionary system/fvSchemes
Il comando stampa le voci del dizionario senza i commenti ordinari. Le macro vengono mantenute, a meno che non si chieda l’espansione.
10.3 Estrarre una voce particolare
foamDictionary -entry startFrom system/controlDict
foamDictionary -entry startFrom -value system/controlDict
La prima forma stampa la voce completa, la seconda solo il valore.
10.4 Navigare nei dizionari annidati con /
foamDictionary -entry "solvers/p" system/fvSolution
La sintassi con la barra raggiunge le voci attraverso i dizionari annidati. Il percorso esatto dipende dal caso.
10.5 Elencare le parole chiave di un sotto-dizionario
foamDictionary -entry solvers -keywords system/fvSolution
È utile quando vuoi scoprire per quali equazioni di campo esiste una configurazione esplicita del solutore.
10.6 Espandere le macro quando serve
foamDictionary -expand system/fvSchemes
Aiuta quando un file è compatto perché diverse voci sono definite tramite macro.
10.7 Altri strumenti da ricordare per dopo
| Strumento | Uso |
|---|---|
foamSearch | Cerca nei dizionari dei tutorial esempi di una certa voce |
foamGet | Copia nel caso modelli di configurazione supportati |
foamInfo | Mostra informazioni ed esempi per modelli selezionabili, condizioni al contorno e moduli solutori |
foamToC | Elenca le opzioni selezionabili a run-time direttamente dalle tabelle di OpenFOAM |
foamUnits | Ispeziona dimensioni, unità e conversioni |
Questi strumenti saranno sviluppati meglio nella Parte 8. La Parte 1 stabilisce solo che l’ambiente OpenFOAM installato è esso stesso una fonte di documentazione.
11. Laboratorio guidato: costruire e ispezionare un dizionario innocuo
Questo laboratorio insegna la sintassi senza toccare un calcolo CFD. Si crea un dizionario che nessun solutore usa e lo si ispeziona con foamDictionary.
11.1 Creare il file
In un caso di prova usa e getta, crea system/studentDict con questo contenuto:
FoamFile
{
format ascii;
class dictionary;
object studentDict;
}
studentName student01;
referenceValue 0.25;
direction (1 0 0);
labels
(
inlet
outlet
walls
);
settings
{
enabled true;
count 4;
tolerance 1e-6;
}
11.2 Interpretare tutto il file
foamDictionary system/studentDict
Se il file è sintatticamente valido, foamDictionary deve stampare le voci interpretate. È la prova che il file rispetta la grammatica dei dizionari OpenFOAM anche se nessuna applicazione di simulazione lo usa.
11.3 Leggere un valore
foamDictionary -entry referenceValue -value system/studentDict
Valore logico atteso: 0.25.
11.4 Leggere un valore annidato
foamDictionary -entry settings/tolerance -value system/studentDict
Il percorso con la barra entra nel sotto-dizionario settings.
11.5 Elencare le parole chiave annidate
foamDictionary -entry settings -keywords system/studentDict
Devi vedere enabled, count e tolerance.
11.6 Introdurre un errore di sintassi controllato
Fai una copia del file, poi togli il punto e virgola dopo referenceValue 0.25. Esegui di nuovo foamDictionary.
Osserva, non tirare a indovinare
Leggi il primo errore significativo del parser. Annota il file, la posizione approssimativa e il token che OpenFOAM non si aspettava. Rimetti il punto e virgola e verifica che il file torni a essere letto correttamente.
11.7 Aggiungere una macro
Dopo aver ripristinato il file valido, aggiungi:
copyOfReference $referenceValue;
Poi confronta:
foamDictionary system/studentDict
foamDictionary -expand system/studentDict
La forma espansa è utile per vedere il valore effettivo dopo la sostituzione della macro.
11.8 Aggiungere un include
Crea system/studentValues con il contenuto:
includedValue 17;
Poi aggiungi queste righe a studentDict, prima della voce che le usa:
#include "studentValues"
copiedIncludedValue $includedValue;
Esegui foamDictionary -expand system/studentDict e verifica che la voce inclusa sia visibile e che la macro venga risolta.
11.9 Che cosa insegna questo laboratorio
- La sintassi di OpenFOAM si può imparare indipendentemente dalla fisica.
- Il parser può validare la struttura dei dizionari.
- I dizionari annidati hanno percorsi indirizzabili.
- Macro e include possono ridurre le ripetizioni.
- Un errore introdotto apposta è utile solo se leggi la diagnostica invece di cambiare più cose insieme.
12. Esercizio di lettura: classificare un caso reale
Scegli un semplice caso tutorial di OpenFOAM 14 che è già stato eseguito con successo nell’ambiente di formazione. All’inizio non modificarlo.
12.1 Trovare l’albero dei tutorial
echo $FOAM_TUTORIALS
Esplora un caso semplice, pertinente al modulo solutore che hai già usato nella prima fase del percorso.
12.2 Un inventario superficiale dei file
find . -maxdepth 2 -type f | sort
Non aprire subito tutti i file. Prima classifica le posizioni.
12.3 Compilare una tabella di classificazione
Per ogni file importante annota quanto segue.
| File | Livello | Classe da FoamFile | Che cosa pensi che controlli |
|---|---|---|---|
system/controlDict | Esecuzione | dictionary | … |
system/fvSchemes | Discretizzazione | dictionary | … |
system/fvSolution | Soluzione algebrica | dictionary | … |
0/U | Campo | volVectorField | … |
0/p | Campo | volScalarField | … |
12.4 Ispezionare solo la struttura
Per ogni file identifica:
- classe e oggetto di
FoamFile; - parole chiave di primo livello;
- sotto-dizionari;
- liste;
- scalari e vettori;
- dimensioni o unità;
- macro, include o voci con espressioni regolari, se presenti.
Non ti si chiede ancora di spiegare ogni scelta numerica. L’obiettivo è l’alfabetizzazione strutturale.
12.5 Usare foamDictionary per verificare la tua lettura
foamDictionary system/controlDict
foamDictionary system/fvSchemes
foamDictionary system/fvSolution
Confronta la struttura interpretata con quella che avevi identificato a mano.
13. Esercizi autonomi
13.1 Esercizio A – Analizzare la struttura
Senza eseguire OpenFOAM, descrivi la struttura di questo dizionario.
measurement
{
name probeA;
origin (0.01 0.02 0.03);
channels
(
pressure
velocity
temperature
);
settings
{
interval 0.1;
enabled true;
}
}
Rispondi a queste domande:
- Quante voci dirette ci sono dentro
measurement? - Quale voce è un vettore?
- Quale voce è una lista?
- Quale voce è a sua volta un sotto-dizionario?
- Qual è il percorso completo di
intervalcon la sintassi a barre difoamDictionary?
13.2 Esercizio B – Trovare l’errore di sintassi
parameters
{
length 0.2;
width 0.05
height 0.01;
}
Individua l’errore prima di usare un parser. Poi crea un dizionario temporaneo che contiene il blocco e verifica la tua diagnosi con foamDictionary.
13.3 Esercizio C – Dimensioni e unità
Classifica ogni espressione tra parentesi quadre come dimensione o come unità di misura, nel suo contesto:
dimensions [velocity];
nu 10 [cSt];
rho 1000 [kg m^-3];
dimensions [0 1 -1 0 0 0 0];
Poi usa foamUnits per ispezionare cSt e velocity.
13.4 Esercizio D – Anatomia di un campo
Dato il file U semplificato della sezione 7, rispondi:
- Che cosa dimostra che
Uè un campo vettoriale? - Qual è la velocità interna iniziale?
- Quale sotto-dizionario contiene le condizioni per le patch della mesh?
- Quale voce prescrive un valore esplicito in ingresso?
- Perché in questo file
noSlipnon è un tipo di patch della mesh?
13.5 Esercizio E – Ragionare su macro e include
Supponi che system/commonValues contenga:
baseTolerance 1e-6;
e che un altro dizionario contenga:
#include "commonValues"
tolerance $baseTolerance;
Spiega quale file definisce il valore numerico e quale voce riceve il valore espanso. Poi indica che cosa dovrebbe mostrare foamDictionary -expand.
13.6 Esercizio F – Classificare un caso
Prendi un caso tutorial funzionante e classifica almeno dieci file o cartelle con il modello a sei livelli della sezione 1.4. Almeno un elemento deve venire da ciascuna di queste categorie: mesh, campo, modello fisico, discretizzazione, soluzione algebrica, controllo dell’esecuzione.
14. Checklist delle competenze e riferimento rapido
14.1 Sei pronto per la Parte 2 quando sai fare quanto segue
- ☐ Spiegare la differenza tra
system,constante le cartelle temporali. - ☐ Leggere un’intestazione
FoamFilee identificareclasseobject. - ☐ Riconoscere una voce parola chiave/valore e spiegare perché finisce con un punto e virgola.
- ☐ Distinguere dizionari
{}, liste()e dimensioni/unità[]. - ☐ Riconoscere scalari, vettori, tensori e liste.
- ☐ Spiegare la differenza tra una dimensione fisica e un’unità di misura.
- ☐ Riconoscere le dimensioni con nome della v14, come
[velocity]. - ☐ Spiegare il ruolo di
internalFieldeboundaryField. - ☐ Spiegare la differenza tra una patch della mesh e una condizione al contorno di un campo.
- ☐ Riconoscere l’espansione di macro con
$e#include. - ☐ Usare
foamDictionaryper stampare un file ed estrarre una voce annidata. - ☐ Leggere un errore del parser senza cambiare insieme più impostazioni scollegate.
14.2 Riferimento strutturale su una pagina
CASO
|
|-- system/ COME ESEGUIRE / RISOLVERE
| |-- controlDict esecuzione e controllo dell'output
| |-- fvSchemes discretizzazione
| `-- fvSolution solutori delle equazioni e algoritmi
|
|-- constant/ QUALE SISTEMA FISICO / MESH
| |-- polyMesh/ dati della mesh generati
| |-- physicalProperties proprietà dei materiali (dipende dal caso)
| `-- ... altri file di modello
|
`-- 0/, 0.1/, 1/, ... STATO DEI CAMPI AI TEMPI SIMULATI
|-- U esempio di campo vettoriale
`-- p esempio di campo scalare
SINTASSI COMUNE
keyword value; voce ordinaria
name { ... } sotto-dizionario
( ... ) lista / dato vettoriale
[ ... ] dimensioni o unità
$keyword espansione di macro
#include "file" include un altro file
".*Wall" chiave con espressione regolare
14.3 Il metodo da usare quando non conosci una voce
- Identifica il file e la sua classe
FoamFile. - Identifica il dizionario o sotto-dizionario che contiene la voce.
- Identifica il tipo di dato atteso.
- Controlla la User Guide di OpenFOAM v14.
- Cerca nei tutorial installati se un esempio può aiutare.
- Usa
foamDictionary,foamInfoofoamToCdove serve. - Cambia una cosa alla volta.
- Rilancia e leggi il primo errore significativo.
Il punto d’arrivo della Parte 1
Non serve conoscere tutte le parole chiave. Serve sapere come è strutturato il linguaggio e come indagare una parola chiave che non hai mai visto.
A. Note sugli esercizi e osservazioni attese
Queste note sono volutamente sintetiche. Servono per controllarsi da soli dopo aver tentato gli esercizi.
A.1 Esercizio A
measurementcontiene quattro voci dirette:name,origin,channelsesettings.originè un vettore a tre componenti.channelsè una lista di parole.settingsè un sotto-dizionario.- Il percorso con la barra per
intervalèmeasurement/settings/interval, semeasurementè a sua volta una voce di primo livello.
A.2 Esercizio B
Manca il punto e virgola dopo width 0.05. Siccome l’input di OpenFOAM è a formato libero, il parser può lamentarsi a un token successivo invece che esattamente nel punto della punteggiatura mancante.
A.3 Esercizio C
[velocity]è una dimensione con nome.[cSt]è un’unità di viscosità cinematica.[kg m^-3]è un’unità di misura composta.[0 1 -1 0 0 0 0]è la forma a esponenti delle dimensioni di una velocità.
A.4 Esercizio D
- La classe
volVectorFieldnell’intestazione identificaUcome campo vettoriale di volume. - La velocità interna iniziale è
(0 0 0). boundaryFieldcontiene le condizioni del campo per le patch della mesh.- Il blocco
fixedValuedell’ingresso contiene un valore esplicito. noSlipè una condizione al contorno del campo applicata a una patch; il tipo di patch della mesh è definito separatamente nella descrizione del contorno della mesh.
A.5 Esercizio E
commonValues fornisce il valore 1e-6 tramite baseTolerance. Il dizionario che lo riceve assegna quel valore a tolerance per espansione di macro. La vista espansa deve mostrare il valore numerico effettivo invece di lasciare il riferimento non risolto.
B. Riferimenti ufficiali
Questa parte si basa sulla documentazione di OpenFOAM 14 della OpenFOAM Foundation / CFD Direct. Usa questi riferimenti quando devi controllare la sintassi o un comportamento specifico della versione.
- C. Greenshields, OpenFOAM v14 User Guide, OpenFOAM Foundation, 14 luglio 2026
- User Guide v14, §4.1 – Struttura dei file di un caso
- User Guide v14, §4.2 – Formato dei file di input/output
- User Guide v14, §4.3 – Controlli globali
- User Guide v14, §4.7 – Strumenti di gestione del caso
- User Guide v14, §6.3 – Introduzione alle condizioni al contorno
- Note di rilascio di OpenFOAM 14 – modifiche specifiche della versione, comprese unità e input con codice
Disciplina con la documentazione
Quando scrivi materiale nuovo usa la documentazione v14. I tutorial più vecchi restano utili per i concetti, ma la sintassi e gli schemi di configurazione preferiti possono cambiare tra una release di OpenFOAM e l’altra.
B.1 Che cosa viene dopo
Parte 2: costruire una mesh con blockMeshDict. Si passa dal linguaggio e dall’anatomia del caso al primo file di configurazione che si costruisce partendo da una geometria: vertici, blocchi esaedrici, numero di celle, grading e patch di contorno. Tutte le parti sono raccolte nel progetto Imparare OpenFOAM 14.