OpenFOAM 14, caso 06: sensibilità alla condizione di ingresso
Sesto caso del percorso Imparare OpenFOAM 14, dopo il calcolo parallelo con MPI: sensibilità alle condizioni al contorno d’ingresso — variazione controllata della velocità in ingresso, validazione del profilo di velocità e verifica del gradiente di pressione.
1. Obiettivi di apprendimento
Questo esercizio introduce la sensibilità alle condizioni al contorno nella CFD. Geometria, mesh, proprietà del fluido e metodi numerici restano fissi, mentre cambia soltanto la velocità in ingresso.
È un concetto di modellazione importante: una condizione al contorno non è semplicemente un’opzione numerica. Fa parte della definizione matematica del problema fisico. Cambiare una condizione al contorno significa chiedere al solutore di risolvere un caso fisico diverso.
Al termine dell’esercizio si dovrebbe essere in grado di:
- identificare quali parti di un caso CFD devono restare invariate in uno studio di sensibilità controllato;
- modificare una velocità d’ingresso di tipo
fixedValuein OpenFOAM; - eseguire più casi altrimenti identici;
- confrontare i profili di velocità con una soluzione analitica;
- estrarre un gradiente di pressione dai risultati di OpenFOAM e ricavarlo con un fit;
- spiegare perché la velocità massima e il gradiente di pressione scalano con la velocità d’ingresso;
- distinguere una sensibilità fisica da un effetto della mesh o del solutore.
2. Geometria di riferimento e modello numerico
L’esercizio riutilizza il canale parametrico già validato nel caso 04.
| Grandezza | Valore |
|---|---|
| Lunghezza del canale | 0,75 m |
| Altezza (gap) del canale | 0,015 m |
| Profondità del canale | 0,001 m |
| Mesh | 300 × 60 × 1 |
| Celle totali | 18.000 |
| Tipo di cella | esaedri |
| Viscosità cinematica | 1,0·10⁻⁶ m²/s |
| Modulo solutore | incompressibleFluid tramite foamRun |
| Modello di flusso | laminare |
La mesh e tutte le impostazioni numeriche sono identiche nei tre casi.
3. Cosa cambia e cosa non cambia
Si studiano tre velocità d’ingresso:
| Caso | Velocità media in ingresso [m/s] | Numero di Reynolds | Velocità massima analitica [m/s] |
|---|---|---|---|
| low | 0,005 | 150 | 0,0075 |
| reference | 0,010 | 300 | 0,0150 |
| high | 0,020 | 600 | 0,0300 |
I seguenti elementi devono restare identici:
- geometria;
- mesh;
- viscosità;
- condizione di pressione in uscita;
- condizione di parete;
fvSchemes;fvSolution;- solutore;
- posizione del post-processing.
Cambia soltanto il valore d’ingresso in 0/U.

4. Comportamento analitico atteso
Per un flusso laminare completamente sviluppato fra lastre piane parallele,
Umax = 1,5 Umean.
Quindi, se la velocità media in ingresso raddoppia, deve raddoppiare anche la velocità massima del flusso sviluppato.
Per un canale di altezza H, il gradiente di pressione cinematica è
dp/dx = −12 ν Umean / H².
In questo esercizio H = 0,015 m e ν = 10⁻⁶ m²/s. I gradienti di pressione teorici sono quindi:
| Caso | dp/dx teorico [m/s²] |
|---|---|
| low | −2,6666667·10⁻⁴ |
| reference | −5,3333333·10⁻⁴ |
| high | −1,0666667·10⁻³ |
La variabile di pressione in questa formulazione incomprimibile di OpenFOAM è la pressione cinematica, cioè la pressione divisa per la densità. Per l’acqua, una differenza di pressione cinematica si può convertire approssimativamente in pascal moltiplicandola per la densità.
5. Prerequisiti
Deve esistere la cartella validata del caso 04:
$FOAM_RUN/04_parametric_channel
Controllare i comandi principali:
foamVersion
command -v checkMesh
command -v foamRun
command -v foamPostProcess
Versione di OpenFOAM attesa:
14
6. Creare i tre casi di sensibilità
Si creano tre copie del caso validato:
cd $FOAM_RUN
mkdir -p 06_boundary_sensitivity/{low,reference,high}
for c in low reference high; do
cp -a 04_parametric_channel/0 \
06_boundary_sensitivity/$c/
cp -a 04_parametric_channel/constant \
06_boundary_sensitivity/$c/
cp -a 04_parametric_channel/system \
06_boundary_sensitivity/$c/
rm -rf \
06_boundary_sensitivity/$c/constant/polyMesh_reference
done
La struttura di cartelle risultante è:
06_boundary_sensitivity/
|-- low/
| |-- 0/
| |-- constant/
| `-- system/
|-- reference/
| |-- 0/
| |-- constant/
| `-- system/
`-- high/
|-- 0/
|-- constant/
`-- system/
7. Modificare solo la condizione al contorno d’ingresso
Il caso reference usa già 0,010 m/s.
Per il caso low:
sed -i \
's/value[[:space:]]*uniform (0.01 0 0);/value uniform (0.005 0 0);/' \
06_boundary_sensitivity/low/0/U
Per il caso high:
sed -i \
's/value[[:space:]]*uniform (0.01 0 0);/value uniform (0.020 0 0);/' \
06_boundary_sensitivity/high/0/U
Controllare tutte e tre le definizioni dell’ingresso:
for c in low reference high; do
echo "===== $c ====="
grep -A4 "inlet" \
06_boundary_sensitivity/$c/0/U
done
Valori attesi:
low -> (0.005 0 0)
reference -> (0.010 0 0)
high -> (0.020 0 0)
La condizione al contorno d’ingresso è un fixedValue perché la velocità è imposta direttamente.
8. Verificare che la mesh non sia cambiata
Uno studio di sensibilità ha senso solo se la variabile controllata è davvero isolata. Si controlla ogni caso:
for c in low reference high; do
echo "===== $c ====="
cd $FOAM_RUN/06_boundary_sensitivity/$c
checkMesh > log.checkMesh
grep -E \
'cells:|hexahedra:|Mesh OK' \
log.checkMesh
done
Output atteso per ogni caso:
cells: 18000
hexahedra: 18000
Mesh OK.
Se il numero di celle differisce fra un caso e l’altro, lo studio non è più un test puro di sensibilità alle condizioni al contorno.
9. Eseguire i tre calcoli
Si lanciano tutti e tre i casi misurando il tempo reale (wall time):
cd $FOAM_RUN/06_boundary_sensitivity
for c in low reference high; do
echo
echo "=========================="
echo "Running $c"
echo "=========================="
cd $FOAM_RUN/06_boundary_sensitivity/$c
/usr/bin/time \
-o log.time \
-f 'Wall time: %e s' \
foamRun > log.foamRun 2>&1
tail -3 log.foamRun
cat log.time
done
Un calcolo andato a buon fine termina con:
End
I tempi misurati sono stati:
| Caso | Wall time [s] |
|---|---|
| low | 143,05 |
| reference | 143,68 |
| high | 141,63 |
I tempi sono quasi uguali perché la dimensione della mesh, il solutore e il numero di iterazioni stazionarie sono praticamente gli stessi. Cambiare il valore d’ingresso non crea, di per sé, un problema computazionale più grande.
10. Post-processing del profilo di velocità
La linea di campionamento trasversale è ereditata dal caso 04 e si trova vicino all’uscita, dove il flusso è completamente sviluppato.
Il corrispondente system/graphUniform dovrebbe contenere:
FoamFile
{
format ascii;
class dictionary;
object graphUniform;
}
start (0.675 -0.007375 0.0005);
end (0.675 0.007375 0.0005);
nPoints 201;
fields (U);
axis y;
#includeEtc "caseDicts/postProcessing/graphs/graphUniform.cfg"
Estrarre il profilo per tutti i casi:
for c in low reference high; do
cd $FOAM_RUN/06_boundary_sensitivity/$c
foamPostProcess \
-solver incompressibleFluid \
-func graphUniform \
-latestTime
done
L’output viene scritto in:
postProcessing/graphUniform/<time>/line.xy
11. Validazione automatica della velocità
Tornare alla cartella comune:
cd $FOAM_RUN/06_boundary_sensitivity
Definire la funzione di analisi:
analyse_case()
{
CASE=$1
UMEAN=$2
FILE=$(find "$CASE/postProcessing/graphUniform" \
-name line.xy | sort -V | tail -1)
awk \
-v CASE="$CASE" \
-v Umean="$UMEAN" '
BEGIN {
H=0.015
UmaxTheory=1.5*Umean
umax=-1
}
$1 !~ /^#/ && NF >= 2 {
y=$1
u=$2
uth=UmaxTheory*(1-(2*y/H)^2)
e=u-uth
ae=(e<0 ? -e : e)
sumsq += e*e
n++
if (ae > maxerr)
maxerr=ae
if (u > umax)
umax=u
}
END {
rmse=sqrt(sumsq/n)
printf "%-10s %10.5f %14.9f %14.9f %12.6f %12.6f\n",
CASE,
Umean,
umax,
UmaxTheory,
100*rmse/UmaxTheory,
100*maxerr/UmaxTheory
}' "$FILE"
}
Stampare l’intestazione della tabella e analizzare i tre casi:
printf "%-10s %10s %14s %14s %12s %12s\n" \
"CASE" "UMEAN" "UMAX_CFD" "UMAX_THEORY" "NRMSE_%" "MAXERR_%"
analyse_case low 0.005
analyse_case reference 0.010
analyse_case high 0.020
12. Risultati misurati per la velocità
I risultati misurati sono:
| Caso | Umean [m/s] | Umax,CFD [m/s] | Umax,teoria [m/s] | NRMSE [%] | Errore max [%] |
|---|---|---|---|---|---|
| low | 0,00500 | 0,007495834 | 0,007500000 | 0,058847 | 0,083101 |
| reference | 0,01000 | 0,014991664 | 0,015000000 | 0,058850 | 0,083131 |
| high | 0,02000 | 0,029983232 | 0,030000000 | 0,058886 | 0,083441 |
La velocità massima calcolata dalla CFD scala quasi esattamente con la velocità imposta in ingresso.
Gli errori diretti su Umax rispetto al valore analitico sono all’incirca:
| Caso | Errore relativo su Umax [%] |
|---|---|
| low | 0,05555 |
| reference | 0,05557 |
| high | 0,05589 |
L’errore normalizzato del profilo resta quasi invariato. È quanto ci si aspetta, perché in tutti e tre i calcoli si usano la stessa mesh e la stessa discretizzazione numerica.
13. Perché il risultato sulla velocità è lineare
In questo benchmark laminare, le equazioni di governo e le condizioni al contorno producono un campo di velocità che scala linearmente con la velocità media imposta.
Per il flusso di Poiseuille fra lastre piane parallele:
Umax = 1,5 Umean.
Quindi:
Umean: 0.005 -> 0.010 -> 0.020 m/s
Umax: ~ 0.0075 -> 0.0150 -> 0.0300 m/s
La forma della parabola normalizzata non cambia. Cambia soltanto la sua ampiezza.
14. Post-processing del gradiente di pressione
La velocità è solo una delle conseguenze del cambiamento della condizione d’ingresso. Deve cambiare anche il gradiente di pressione necessario a spingere il flusso completamente sviluppato.
Creare system/graphPressure in ogni caso:
cd $FOAM_RUN/06_boundary_sensitivity
for c in low reference high; do
cat > $c/system/graphPressure <<'EOF2'
FoamFile
{
format ascii;
class dictionary;
object graphPressure;
}
start (0.55 0 0.0005);
end (0.70 0 0.0005);
nPoints 101;
fields (p);
axis x;
#includeEtc "caseDicts/postProcessing/graphs/graphUniform.cfg"
EOF2
done
La linea è posta nella zona a valle, così che il gradiente di pressione venga misurato dove il flusso è già sviluppato.
Estrarre i campioni di pressione:
for c in low reference high; do
cd $FOAM_RUN/06_boundary_sensitivity/$c
foamPostProcess \
-solver incompressibleFluid \
-func graphPressure \
-latestTime
done
15. Calcolare il gradiente di pressione per regressione lineare
Nella regione di flusso completamente sviluppato il campo di pressione dovrebbe essere approssimativamente lineare in x. Invece di usare solo due punti, si interpolano tutti i 101 campioni con una retta.
Tornare alla cartella comune:
cd $FOAM_RUN/06_boundary_sensitivity
Definire:
pressure_slope()
{
CASE=$1
FILE=$(find "$CASE/postProcessing/graphPressure" \
-name line.xy | sort -V | tail -1)
awk -v CASE="$CASE" '
$1 !~ /^#/ && NF >= 2 {
x=$1
p=$2
sx+=x
sp+=p
sxx+=x*x
sxp+=x*p
n++
}
END {
slope=(n*sxp-sx*sp)/(n*sxx-sx*sx)
printf "%-10s %.10e\n", CASE, slope
}' "$FILE"
}
Poi eseguire:
printf "%-10s %18s\n" "CASE" "CFD dp/dx"
pressure_slope low
pressure_slope reference
pressure_slope high
16. Risultati misurati per il gradiente di pressione
I gradienti misurati sono:
| Caso | dp/dx CFD [m/s²] | Teoria [m/s²] | Errore relativo [%] |
|---|---|---|---|
| low | −2,6651869423·10⁻⁴ | −2,6666667·10⁻⁴ | 0,05549 |
| reference | −5,3303768616·10⁻⁴ | −5,3333333·10⁻⁴ | 0,05543 |
| high | −1,0661283532·10⁻³ | −1,0666667·10⁻³ | 0,05047 |
Anche lo scaling è corretto:
(dp/dx)reference / (dp/dx)low ≈ 2,00000
e
(dp/dx)high / (dp/dx)reference ≈ 2,00010.
Quindi, entro l’errore numerico, raddoppiare la velocità d’ingresso raddoppia il modulo del gradiente di pressione.
17. Interpretare il risultato completo
Questo studio di sensibilità stabilisce tre punti importanti.
17.1 La condizione al contorno cambia la soluzione fisica
I tre casi usano lo stesso metodo numerico, ma non rappresentano lo stesso stato fisico. Le diverse velocità d’ingresso producono ampiezze di velocità diverse e gradienti di pressione diversi.
17.2 L’errore numerico resta stabile
L’NRMSE del profilo di velocità resta vicino allo 0,059% in tutti e tre i casi. Questo indica che la qualità della discretizzazione è simile in tutto l’intervallo provato.
17.3 Il costo computazionale resta simile
I tempi misurati sono tutti vicini a 142–144 secondi. La dimensione del problema non è cambiata: ci sono sempre 18.000 celle e si usa lo stesso processo di soluzione stazionaria.
È una distinzione utile:
change in physical input -> different physical result # input fisico diverso -> risultato fisico diverso
same mesh and solver -> similar numerical cost # stessa mesh e solutore -> costo numerico simile
18. Confronto facoltativo in ParaView
Un confronto visivo è facoltativo, perché la validazione quantitativa è già conclusiva. Volendo, si crea un file .foam in ogni caso:
touch low/low.foam
touch reference/reference.foam
touch high/high.foam
Aprire i tre casi in ParaView e confrontare U → Magnitude.
Perché il confronto visivo abbia senso, usare lo stesso intervallo di colori per tutti e tre i dataset. Se ogni dataset viene riscalato automaticamente in modo indipendente, i tre campi possono sembrare ingannevolmente simili, anche se le loro velocità assolute differiscono di un fattore due e quattro.
La geometria delle linee di corrente resta rettilinea in tutti i casi; cambia solo il modulo della velocità. Per questo la forma delle linee di corrente non è il risultato principale di questo esercizio.
19. Criteri di accettazione
Il caso 06 è completo quando sono soddisfatte tutte le condizioni seguenti:
- i tre casi contengono esattamente 18.000 celle esaedriche;
checkMeshriportaMesh OKper ogni caso;- l’unica modifica controllata è la velocità d’ingresso
fixedValue; - tutti e tre i calcoli terminano normalmente;
- la velocità massima concorda con 1,5 Umean;
- l’errore normalizzato del profilo di velocità resta piccolo;
- il gradiente di pressione misurato concorda con il valore analitico;
- raddoppiare la velocità d’ingresso raddoppia approssimativamente sia Umax sia |dp/dx|.
20. Controlli comuni se il risultato è inatteso
Se tutti e tre i casi danno lo stesso campo di velocità:
- ispezionare
0/Uin ogni caso; - confermare che il valore d’ingresso sia effettivamente diverso;
- verificare che il solutore sia stato lanciato separatamente in ogni cartella;
- controllare che il post-processing legga il caso giusto e l’ultimo istante temporale.
Se manca il file del gradiente di pressione:
- confermare che
system/graphPressureesista; - confermare che sia presente
fields (p);; - rilanciare
foamPostProcess -func graphPressure -latestTime.
Se checkMesh dà numeri di celle diversi fra i casi, ricreare i tre casi dalla stessa sorgente validata prima di proseguire.
21. Domande di verifica
Dopo aver completato l’esercizio si dovrebbe saper rispondere a queste domande:
- Perché geometria e mesh devono restare identiche in questo studio di sensibilità?
- Perché la velocità d’ingresso è un dato fisico e non semplicemente un parametro numerico?
- Perché in questo benchmark laminare Umax raddoppia quando raddoppia Umean?
- Perché raddoppia anche il modulo del gradiente di pressione?
- Perché i tre calcoli richiedono quasi lo stesso tempo di esecuzione?
- Perché è fuorviante confrontare tre immagini di ParaView se ognuna usa un intervallo di colori riscalato automaticamente?
22. Conclusione finale
Questo esercizio mostra uno studio di sensibilità CFD controllato. Variando soltanto la velocità d’ingresso, l’effetto della condizione al contorno viene isolato dagli effetti della mesh e del solutore.
I campi di velocità e i gradienti di pressione misurati seguono lo scaling analitico di Poiseuille con errori di circa 0,05–0,06%. L’esercizio conferma quindi sia l’interpretazione fisica della condizione al contorno sia la coerenza numerica della soluzione di OpenFOAM.
Con questo si chiude il primo blocco introduttivo del percorso Imparare OpenFOAM 14. Caso precedente: calcolo parallelo con MPI, decomposePar e reconstructPar.