OpenFOAM 14, parte 1: anatomia di un caso e linguaggio dei dizionari

di giux CFD e OpenFOAM 28 min di lettura

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.

Videolezione sulla Parte 1 (in italiano), generata con Gemini Notebook a partire dalla dispensa.

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, pwd e ls.
  • 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

  1. Il modello mentale di un caso OpenFOAM
  2. I tre livelli strutturali: system, constant e cartelle temporali
  3. L’intestazione FoamFile
  4. La sintassi dei dizionari: parole chiave, valori, graffe e punti e virgola
  5. Tipi di dato: parole, stringhe, scalari, vettori, tensori e liste
  6. Dimensioni e unità in OpenFOAM 14
  7. I file di campo: una forma speciale ma coerente di dizionario
  8. Macro, include, variabili d’ambiente ed espressioni regolari
  9. Come OpenFOAM legge la configurazione e risolve le sovrascritture
  10. Strumenti di ispezione: comandi di shell e foamDictionary
  11. Laboratorio guidato: costruire e ispezionare un dizionario innocuo
  12. Esercizio di lettura: classificare un caso reale
  13. Esercizi autonomi
  14. Checklist delle competenze e riferimento rapido
  15. Note sugli esercizi e osservazioni attese
  16. 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:

PosizioneDomanda a cui rispondeContenuto 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 temporaliQuanto 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
Struttura di un caso OpenFOAM: cartelle system, constant e directory temporali con i file principali
Un albero di caso semplificato. I file esatti dipendono dalla fisica e dal flusso di lavoro scelti.

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

LivelloEsempio tipicoDomanda
Geometria / meshconstant/polyMeshDove sono le celle e le patch di contorno?
Definizione dei campi0/U, 0/pQuali variabili esistono e come sono inizializzate?
Modello fisicoconstant/physicalPropertiesQuale materiale e quale comportamento del modello sono rappresentati?
Discretizzazionesystem/fvSchemesCome sono approssimati gli operatori differenziali?
Soluzione algebricasystem/fvSolutionCome vengono risolti i sistemi di equazioni risultanti?
Controllo dell’esecuzionesystem/controlDictQuando 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 ruoli
controlDict 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.

ElementoDi solito creato daTrattamento tipico
system/controlDictUtente o modello copiatoSi legge e si modifica direttamente
system/fvSchemesUtente o modello copiatoSi legge e si modifica direttamente
system/fvSolutionUtente o modello copiatoSi legge e si modifica direttamente
constant/polyMesh/*Utility di meshSi ispeziona; nel lavoro normale si rigenera invece di modificarlo a mano
0/U, 0/pUtente / strumento di inizializzazioneSi modificano o si generano le condizioni iniziali
cartelle temporali successiveSolutoreSono 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

VoceSignificatoValori tipici / note
versionVersione del formato di I/OFacoltativa; nella documentazione attuale il valore predefinito è 2.0
formatCome sono codificati i datiascii o binary
classClasse di oggetto/dati OpenFOAMdictionary, volScalarField, volVectorField, ecc.
objectNome dell’oggetto/filePer esempio controlDict, U, p
locationPercorso del file relativo al casoFacoltativa; 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

DelimitatoreRuolo tipicoEsempio
{}Dizionario o sotto-dizionarioboundaryField { ... }
()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

VoceRuolo
dimensionsDimensioni fisiche del campo
internalFieldValori nel campo interno della mesh; in un file 0 scritto dall’utente spesso è un valore iniziale uniforme
boundaryFieldSotto-dizionario con le condizioni del campo per le patch di contorno della mesh
sourcesInizializzazione/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:

VariabileSignificato
$FOAM_CASEPercorso del caso in esecuzione
$FOAM_CASENAMENome della cartella del caso corrente
$FOAM_APPLICATIONNome dell’applicazione in esecuzione
$FOAM_TUTORIALSCartella dei casi tutorial installati
$FOAM_ETCCartella 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

StrumentoUso
foamSearchCerca nei dizionari dei tutorial esempi di una certa voce
foamGetCopia nel caso modelli di configurazione supportati
foamInfoMostra informazioni ed esempi per modelli selezionabili, condizioni al contorno e moduli solutori
foamToCElenca le opzioni selezionabili a run-time direttamente dalle tabelle di OpenFOAM
foamUnitsIspeziona 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.

FileLivelloClasse da FoamFileChe cosa pensi che controlli
system/controlDictEsecuzionedictionary…
system/fvSchemesDiscretizzazionedictionary…
system/fvSolutionSoluzione algebricadictionary…
0/UCampovolVectorField…
0/pCampovolScalarField…

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:

  1. Quante voci dirette ci sono dentro measurement?
  2. Quale voce è un vettore?
  3. Quale voce è una lista?
  4. Quale voce è a sua volta un sotto-dizionario?
  5. Qual è il percorso completo di interval con la sintassi a barre di foamDictionary?

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:

  1. Che cosa dimostra che U è un campo vettoriale?
  2. Qual è la velocità interna iniziale?
  3. Quale sotto-dizionario contiene le condizioni per le patch della mesh?
  4. Quale voce prescrive un valore esplicito in ingresso?
  5. Perché in questo file noSlip non è 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, constant e le cartelle temporali.
  • ☐ Leggere un’intestazione FoamFile e identificare class e object.
  • ☐ 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 internalField e boundaryField.
  • ☐ 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 foamDictionary per 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

  1. Identifica il file e la sua classe FoamFile.
  2. Identifica il dizionario o sotto-dizionario che contiene la voce.
  3. Identifica il tipo di dato atteso.
  4. Controlla la User Guide di OpenFOAM v14.
  5. Cerca nei tutorial installati se un esempio può aiutare.
  6. Usa foamDictionary, foamInfo o foamToC dove serve.
  7. Cambia una cosa alla volta.
  8. 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

  • measurement contiene quattro voci dirette: name, origin, channels e settings.
  • 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, se measurement è 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 volVectorField nell’intestazione identifica U come campo vettoriale di volume.
  • La velocità interna iniziale è (0 0 0).
  • boundaryField contiene le condizioni del campo per le patch della mesh.
  • Il blocco fixedValue dell’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.

  1. C. Greenshields, OpenFOAM v14 User Guide, OpenFOAM Foundation, 14 luglio 2026
  2. User Guide v14, §4.1 – Struttura dei file di un caso
  3. User Guide v14, §4.2 – Formato dei file di input/output
  4. User Guide v14, §4.3 – Controlli globali
  5. User Guide v14, §4.7 – Strumenti di gestione del caso
  6. User Guide v14, §6.3 – Introduzione alle condizioni al contorno
  7. 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.

#CFD #foamDictionary #OpenFOAM

Lascia un commento

Il tuo indirizzo email non sarà pubblicato. I campi obbligatori sono contrassegnati *