OpenFOAM: monitoring, troubleshooting and convergence assessment

by giux CFD and OpenFOAM, Featured 22 min read

This is the second operating guide on OpenFOAM installed on a Linux server and used from Windows. The first guide explains how to transfer cases with FileZilla, log in over SSH from PowerShell, run in tmux and connect ParaView to the server. This one starts from a case that already runs and covers what comes after launch: monitoring, troubleshooting and convergence assessment, with OpenFOAM Foundation 14.

Monitoring, troubleshooting and convergence assessment
From starting a run to assessing its results — OpenFOAM Foundation 14
Edition: 16 October 2026 · General operational handbook · Windows + Linux server

Purpose. This guide starts with an OpenFOAM case that already runs. It explains how to monitor execution, identify warning signs, record physical observables during the calculation, and prepare a repeatable assessment. FileZilla transfers and SSH access from PowerShell are assumed to be familiar. No particular IDE is required: Notepad++ is sufficient.

Reading path. Chapters 1–3 provide the minimum checks for every run; 4–6 add quantitative monitoring; chapter 7 is a worked exercise; chapter 8 and the references are a troubleshooting resource. The optional Background boxes are intended for readers who want to revisit a concept.

1. What does a successful simulation mean?

A run ending without a fatal error is not necessarily trustworthy. Keep at least four separate questions in view:

LevelQuestionMinimum evidence
ExecutionDid the program exit correctly?Exit status, complete log, no fatal errors
NumericalAre the discrete equations solved stably?Residuals, continuity, Courant number, no uncontrolled oscillations
PhysicalDoes the solution satisfy the problem constraints?Balances, orders of magnitude, boundary conditions, pressure drop, flow rate
CredibilityIs the result overly dependent on discretisation?Mesh, time-step, numerical scheme and model sensitivity

Checking residuals mainly addresses the second row. Accepting the solution also requires physical observables and, ultimately, a numerical sensitivity study.

Optional background — residual versus accuracy. A residual indicates how well a discrete algebraic system is satisfied in a particular solve; a small value does not establish how accurately the discretisation represents the continuum equations. A simulation can converge to a result that is consistent with an excessively coarse mesh.

Four checks in sequence: execution, numerical, physical, credibility
Four independent checks
Deep dive · Verification and validation: two different questions

The reference literature on CFD credibility (for example the AIAA G-077 guide and Roache’s work) separates two activities:

  • Verification: “am I solving the equations right?”. It concerns the code and the numerical solution: iterative convergence (residuals, balances), convergence with mesh and time step, estimation of discretisation error.
  • Validation: “am I solving the right equations?”. It compares the result with physical reality (experiments, exact solutions of representative problems) and tests the model: laminar or turbulent, boundary conditions, fluid properties.

The “Numerical” and “Credibility” rows of the table are verification; the “Physical” row bridges towards validation. This guide covers iterative convergence and balances. Mesh convergence is the next step: in case 02 of the OpenFOAM 14 path it is carried out with a comparison against the Poiseuille solution.

2. Before running: the essential checklist

Work on a copy of the case, not the reference or an ongoing calculation. Keep 0/, constant/ and system/, and record which variant you are working on. From PowerShell:

ssh USER@SERVER

On Linux, after initialising the OpenFOAM environment:

foamVersion
cd ~/cases/myCase
pwd
ls -la
grep -E '^[[:space:]]*(solver|startFrom|endTime|deltaT|adjustTimeStep|writeControl|writeInterval)' system/controlDict
checkMesh > "log.checkMesh_$(date +%Y%m%d_%H%M%S)" 2>&1
tail -n 25 log.checkMesh_*

That final command is convenient only if the folder contains few previous logs; otherwise use the specific filename printed or recorded for the check. Look for Mesh OK, as well as any warnings about skewness, non-orthogonality, negative cell volumes, unexpected patches and strongly distorted cells. Mesh OK does not mean that the resolution is sufficient.

For incompressible cases using OpenFOAM Foundation 14, the modular solver typically runs through foamRun, with solver incompressibleFluid; in system/controlDict. Do not blindly apply old solver recipes without checking the release and case.

Before starting, check geometry and SI units, patch names in constant/polyMesh/boundary, consistency of initial fields in 0/, fvSchemes/fvSolution, available disk space and write permissions. Check the dimensions of p: in standard incompressible cases it is often kinematic pressure, not pascals.

Deep dive · Reading checkMesh: the thresholds behind the warnings

Lines starting with *** are the warnings. The main ones, with checkMesh’s default thresholds:

CheckWarning whenWhat it implies
Non-orthogonalityangle above 70° (“severely non-orthogonal”)the face-normal gradient needs correction; use nNonOrthogonalCorrectors and limited schemes
Skewnessmaximum above 4interpolation to face centres loses accuracy
Aspect ratioabove 1000possible linear-solver difficulties
Volumes and determinantsnegative or zero volumes, low determinantmesh not usable: it must be fixed

For a stricter check before a long run:

checkMesh -allGeometry -allTopology > log.checkMesh_full 2>&1
grep -n '\*\*\*' log.checkMesh_full

The meaning of non-orthogonality and skewness for schemes is developed in Part 5: fvSchemes and for correctors in Part 6: fvSolution.

Deep dive · Quick pre-launch checks from the command line
foamDictionary -entry solver system/controlDict          # solver module
foamDictionary -entry dimensions 0/p                      # [0 2 -2 0 0 0 0] = kinematic pressure
grep -E '^[[:space:]]+[A-Za-z]' constant/polyMesh/boundary | head -n 20   # patch names
df -h .                                                   # free space
touch .write_ok && rm .write_ok && echo "write OK"         # permissions

Recording the output of these commands in the assessment record of section 7 makes later variants comparable.

3. Reading the log during a run

Run from the case directory in a persistent session (tmux, where available), with a new, uniquely named log:

LOG="log.foamRun_$(date +%Y%m%d_%H%M%S)"
echo "Log: $LOG"
foamRun > "$LOG" 2>&1
printf 'Exit code: %s\n' "$?"

To monitor a run already in progress, use a second SSH session:

tail -n 50 -f log.foamRun_20261016_153000

Replace the sample filename with the actual one. Ctrl+C here stops tail only, not the solver running in the other session. If you launched the solver in the foreground of the same terminal, Ctrl+C instead interrupts that solver; the distinction matters.

A typical excerpt, fabricated solely for illustration, might look like this:

Time = 120
smoothSolver: Solving for Ux, Initial residual = 0.00038, Final residual = 4.2e-07, No Iterations 3
GAMG: Solving for p, Initial residual = 0.0016, Final residual = 8.1e-06, No Iterations 5
time step continuity errors : sum local = 2.3e-07, global = -1.1e-09, cumulative = 7.0e-06
ExecutionTime = 54.12 s  ClockTime = 55 s
Log termCorrect interpretationWhat to investigate
Time = ...Simulated time or pseudo-time counter, depending on the caseDo not automatically treat this as wall-clock seconds
Initial residualResidual before the linear-system solveHigh plateau, sustained growth or unphysical oscillation
Final residualResidual at the end of that particular linear solveDoes not alone prove overall convergence
No IterationsLinear-solver iterations for a fieldRapid increases or routinely hitting an iteration limit
continuity errorsLocal/global conservation indicators for a stepAccumulating drift or persistently high global errors
Courant NumberTime-advection indicator where reportedUnexplained peaks; acceptable value depends on the scheme
ExecutionTime/ClockTimeCPU time / elapsed timeUnusual slowdown or poor scaling

Optional background — steady vs transient. In a steady case, fields and monitored observables are expected to settle. In a physically unsteady transient case, sustained oscillations can be real: judge iteration convergence per time step, balances and time-step independence, rather than demanding that residuals decrease monotonically across the entire time history.

Quick searches on Linux (when the patterns occur):

grep -nE 'FOAM FATAL|Floating point exception|nan|NaN|not converged|Courant Number|continuity errors' log.foamRun_20261016_153000 | tail -n 40
grep 'ExecutionTime' log.foamRun_20261016_153000 | tail -n 5

On Windows, download the log with FileZilla / SFTP and open it with klogg or Notepad++; to search it in PowerShell:

Select-String -Path 'C:\CFD\logs\log.foamRun_20261016_153000' -Pattern 'FOAM FATAL','Courant Number','continuity errors'

A log downloaded during a run is a partial snapshot: download it again to include later steps.

Deep dive · How OpenFOAM normalises residuals

For a linear system A x = b, OpenFOAM does not report the raw norm of b − A x, which would depend on units and problem size, but a normalised residual:

r = Σ|b − A x| / ( Σ|A x − A x̄| + Σ|b − A x̄| + 10−20 )

where x̄ is the field average. The denominator measures the amplitude of variations in the field, which is why a residual of 10−3 means roughly the same thing for pressure and velocity. Two practical consequences: a nearly uniform field (small denominator) can show high residuals even with modest errors; a small “Initial residual” at the start of a transient step says the field changes little from one step to the next, not that the solution is accurate.

Tolerances, relTol and iterations are covered in Part 6.

Deep dive · Exit status, tee and pipefail

In the guide’s command the output goes straight to the file, so $? is the exit status of foamRun: 0 when the solver ended normally, non-zero after a fatal error. If you use tee to watch and save at once, $? becomes that of tee (almost always 0) and the error would be hidden. Two bash remedies:

set -o pipefail
foamRun 2>&1 | tee "$LOG"
echo "Exit code: $?"

# oppure / or
foamRun 2>&1 | tee "$LOG"; echo "Exit code: ${PIPESTATUS[0]}"

In tmux, use one window for the solver and one for tail -f and grep: Ctrl+B then C creates the second window, Ctrl+B then N switches between them.

4. Recording residuals and probes with function objects

OpenFOAM 14 ships reusable function-object configurations. Using the files from the installed release is safer than copying snippets written for another OpenFOAM distribution or vintage.

From a test case directory, run:

foamPostProcess -list | less
foamInfo residuals
foamGet residuals
foamGet probes

The foamGet commands create the corresponding files in system/ (if files already exist, back them up and check any impending overwrite first). Edit system/probes in Notepad++ and transfer with FileZilla; use coordinates inside the domain and fields present in the case. Illustrative excerpt:

fields (p U);
probeLocations
(
    (0.010 0.000 0.000)
    (0.040 0.000 0.000)
);

The coordinates are examples, not universal valid probe positions: check them against the actual domain in ParaView. Standard probes reads values from the nearest cell; select another sampling function for interpolated or sectional measurements when required.

In system/functions (create the file if missing; if present, merge with existing entries rather than replacing them), add:

#includeFunc residuals
#includeFunc probes

Depending on run settings, typical outputs include:

postProcessing/
  residuals/0/residuals.dat
  probes/0/p
  probes/0/U

The 0 subdirectory is illustrative: it can change after a restart or with startTime. Inspect with find postProcessing -maxdepth 3 -type f | sort.

If the Linux server has a graphical display and gnuplot, you can monitor residuals on the server with:

foamMonitor -l postProcessing/residuals/0/residuals.dat

For a Windows-centred workflow you do not need foamMonitor: periodically download the file using FileZilla and plot it in Calc, Excel or Python. This is an option, not a mandatory dependency.

To inspect available operations without waiting for another run, check the installed options or perform post-processing of saved time directories, depending on the function object:

foamPostProcess -help
foamPostProcess -list

Not every observable can be reconstructed after the fact: if necessary underlying data were not saved, configure the monitor before running.

Initial pressure and velocity residuals on a log scale, synthetic data
Synthetic residual example
Deep dive · File formats and a Python script for residuals

Files under postProcessing are text with comment lines starting with #. residuals.dat has a header with column names (time and one initial residual per field, with possible N/A when a field is not solved in that step). Probe files have one comment line per probe with its coordinates; in the U file each value is a vector in brackets (Ux Uy Uz).

A script that reads the actual header instead of assuming the columns (needs Python with matplotlib on Windows):

# plot_residuals.py  -  python plot_residuals.py residuals.dat
import sys
import matplotlib.pyplot as plt

names, rows = None, []
for line in open(sys.argv[1], encoding='utf-8', errors='replace'):
    s = line.strip()
    if not s:
        continue
    if s.startswith('#'):
        tok = s.lstrip('#').split()
        if tok and tok[0] == 'Time':
            names = tok                    # last header line holding the column names
        continue
    rows.append(s.split())

for j, name in enumerate(names[1:], start=1):
    t, r = [], []
    for row in rows:
        if j < len(row) and row[j] not in ('N/A', 'nan'):
            t.append(float(row[0])); r.append(float(row[j]))
    if r:
        plt.semilogy(t, r, label=name)
plt.xlabel('Time'); plt.ylabel('Initial residual'); plt.grid(True, which='both', alpha=0.3)
plt.legend(); plt.tight_layout(); plt.savefig('residuals.png', dpi=150)
print('plot saved to residuals.png')

For the probes U file, brackets can be removed on the server before importing with sed 's/[()]//g' postProcessing/probes/0/U > U_probes.txt: each line becomes time followed by three components per probe.

Deep dive · Where the shipped configurations live

foamGet copies into the case a file taken from $FOAM_ETC/caseDicts/functions. Before using it, read its parameters with foamInfo and look at the copy:

ls $FOAM_ETC/caseDicts/functions
foamInfo probes
cat system/probes

Besides residuals and probes the same directory holds ready configurations for patch averages and flows, line sampling, forces and more. Page 7.4 Sampling and monitoring data of the v14 User Guide describes the main ones.

5. Monitor pressure drop and flow rate, not just residuals

For a channel flow problem, the operator can monitor pressure averages over inlet/outlet patches and the through-patch flow rates as the calculation advances. A suitable general OpenFOAM 14 method is surfaceFieldValue.

Add the following to system/functions, in addition to the directives above, for patches really called inlet and outlet:

pInlet
{
    type            surfaceFieldValue;
    libs            ("libfieldFunctionObjects.so");
    patch           inlet;
    operation       areaAverage;
    writeFields     false;
    fields          (p);
    writeControl    timeStep;
    writeInterval   1;
}

pOutlet
{
    type            surfaceFieldValue;
    libs            ("libfieldFunctionObjects.so");
    patch           outlet;
    operation       areaAverage;
    writeFields     false;
    fields          (p);
    writeControl    timeStep;
    writeInterval   1;
}

qInlet
{
    type            surfaceFieldValue;
    libs            ("libfieldFunctionObjects.so");
    patch           inlet;
    operation       sum;
    writeFields     false;
    fields          (phi);
    writeControl    timeStep;
    writeInterval   1;
}

qOutlet
{
    type            surfaceFieldValue;
    libs            ("libfieldFunctionObjects.so");
    patch           outlet;
    operation       sum;
    writeFields     false;
    fields          (phi);
    writeControl    timeStep;
    writeInterval   1;
}

The patch must exist, and p and phi must be available in the case. Output series will be under postProcessing/pInlet/..., pOutlet/..., qInlet/... and qOutlet/...; inspect actual filenames and column headers before analysis. This is OpenFOAM Foundation v14 syntax, not the sometimes different regionType/name syntax of other distributions.

Calculations after exporting the series:

  • Mean pressure difference: Δp = p_mean,in − p_mean,out.
  • For a standard incompressible solver with kinematic p, dimensions [0 2 -2 0 0 0 0]: ΔP [Pa] = ρ [kg/m³] × Δp [m²/s²], for constant density.
  • If p already has dimensions of pressure in Pa, do not multiply by density.
  • For volumetric phi, Q_in is usually negative since the patch normal points outward, whereas Q_out is positive. With mass-flux phi, units are kg/s: verify the field dimensions.
  • With one inlet and one outlet, relative imbalance: ε_Q = |Q_in + Q_out| / ((|Q_in|+|Q_out|)/2) × 100%. For additional open patches, include all fluid boundaries.

Purely illustrative calculation: p_in − p_out = 6.2 m²/s², ρ = 1000 kg/m³ → ΔP = 6200 Pa; Q_in = −2.500×10⁻⁴ m³/s, Q_out = +2.495×10⁻⁴ m³/s → ε_Q ≈ 0.20%. These values are not acceptance thresholds.

Optional background — which pressure? When comparing with an instrument, define matching sections and distinguish static pressure, hydraulic pressure difference, total head and local losses. Area-averaged pressures at an inlet and outlet do not always equal the irreversible pressure loss: acceleration, nonuniform velocity profiles and elevation may matter.

Kinematic pressure drop still rising, synthetic data
Different histories for different observables
Deep dive · An order-of-magnitude check on the path’s channel

In the trainingChannel of Part 3 (10 × 5 mm cross-section, uniform inlet velocity 0.05 m/s) the expected flow rate is Q = U · A = 0.05 × 5.0×10⁻⁵ = 2.5×10⁻⁶ m³/s. qInlet should therefore be close to −2.5×10⁻⁶ from the first step, because the boundary condition imposes it, while qOutlet tends to +2.5×10⁻⁶ as the field settles.

For the pressure drop between two parallel plates at distance H in developed laminar flow, Δp_kin = 12 ν L U_mean / H² (kinematic pressure): this is the relation used in case 01 for the Poiseuille validation. In a rectangular duct the coefficient changes with the aspect ratio, but the order of magnitude remains a useful check before looking at the decimals.

Deep dive · Ready-made alternatives: patchAverage and patchFlowRate

The configurations shipped with OpenFOAM 14 include functions already set up for patch averages and flow rates, callable with arguments on one line of system/functions. Before using them, read the parameters your installation accepts:

foamInfo patchAverage
foamInfo patchFlowRate

With the parameters confirmed by foamInfo, the form is like:

#includeFunc patchAverage(patch=inlet, fields=(p))
#includeFunc patchAverage(patch=outlet, fields=(p))
#includeFunc patchFlowRate(patch=inlet)
#includeFunc patchFlowRate(patch=outlet)

The result is equivalent to the four explicit blocks; the guide’s blocks remain preferable when you want to see and control every option (operation, writeControl, writeInterval).

Automatic stopping does not mean physical validation

Some steady-state cases use SIMPLE/residualControl in system/fvSolution to specify automatic stopping criteria. Inspect the local configuration:

grep -n -A 14 'residualControl' system/fvSolution

A solver convergence message means the configured stopping conditions were met: it does not replace pressure, flow balance or discretisation checks. In transient cases, iteration and stopping rules have different meanings.

Deep dive · What residualControl looks like
SIMPLE
{
    nNonOrthogonalCorrectors 0;

    residualControl
    {
        p               1e-2;
        U               1e-3;
        "(k|epsilon|omega)" 1e-3;
    }
}

Each value is the threshold on the field’s Initial residual: when every listed field falls below its threshold in the same iteration, the solver writes the last time and exits with a message like SIMPLE solution converged in ... iterations. The thresholds are not universal: with loose values the run can stop while Δp is still changing. That is why the guide asks you to compare the stop with the observables of figure 3. The SIMPLE and PIMPLE algorithms are explained in Part 6.

6. Recognising three common patterns

ObservationPossible interpretationFirst controlled response
Residuals decrease but Δp still driftsLocal algebraic convergence, global observable not settledContinue monitoring and assess Δp stability over a stated window
Residuals and continuity errors grow; Courant peaksNumerical instability, unsuitable initial/BC setup or time stepRecheck BCs, mesh, time step; compare with baseline
Low residuals and stable Δp, but poor balanceMissing patches, incorrect fluxes, setup/calculation problemsIdentify all open patches, account for Σphi and volume sources
Severe warning from checkMeshGeometry/discretisation problemFix and recheck mesh rather than random solver tolerance changes
FOAM FATAL ERROR or Floating point exceptionAbnormal termination, no valid resultKeep log/configuration; identify the first underlying causal message

Oscillations do not automatically indicate an error: they may be physical in transient flows. The right response depends on the model and its goals. Do not change mesh, schemes, relaxation and boundary conditions all at once: doing so obscures the cause.

Debugging rule: retain a baseline, change one factor at a time, create a new log and compare a consistent set of metrics.

Deep dive · Finding the first causal message and comparing two variants

In a log that ends with an error, the last message is often a consequence. Find the first occurrence and read the lines before it:

grep -n -m1 -E 'FOAM FATAL|Floating point exception|nan' log.foamRun_20261016_153000
sed -n '1180,1240p' log.foamRun_20261016_153000      # intervallo attorno alla riga trovata / range around the line found

With two copies of the case (baseline and variant), the dictionary diff shows exactly what changed:

diff -ru myCase_v01/system myCase_v02/system
diff -ru myCase_v01/constant/momentumTransport myCase_v02/constant/momentumTransport
diff -ru myCase_v01/0 myCase_v02/0

If the diff shows more than one changed factor, comparing the two logs cannot attribute the cause.

7. Worked exercise: a reproducible assessment

The exercise uses any already verified incompressible-flow case with patches named inlet/outlet; adapt the names if necessary. No new geometry is required to make use of the guide.

  1. Duplicate the case into a new folder such as myCase_monitor_v01; do not delete the earlier version’s data.
  2. Run checkMesh and keep the timestamped output.
  3. Create system/residuals and system/probes using foamGet, checking whether files already exist.
  4. Create or merge system/functions; add pressure/flow-rate monitors from chapter 5 only after checking patch names.
  5. Start foamRun in tmux or another persistent session, and record the exact new log filename.
  6. In a second session, watch tail -f ...; look for errors, continuity data, Courant (where relevant), and execution times.
  7. Download only log.* and postProcessing/ with FileZilla. Full CFD field volumes are normally unnecessary for convergence plots.
  8. On Windows, view the log in klogg; import .dat, p, and U series into LibreOffice Calc, Excel or Python, respecting comment/header formats.
  9. Produce at least three graphs: residuals (log y-axis when useful), Δp or ΔP against iteration/time, and flow imbalance ε_Q against iteration/time.
  10. Report the final window analysed, sample count and Δp variation within it, for example max–min relative to its nonzero mean. Clearly identify steady or transient runs.

Teaching pitfall. If residuals seem to have plateaued but Δp has changed by 5% over the last observation window, stability of the quantity of interest has not yet been demonstrated. Conversely, if residuals fall by another two orders of magnitude with no change in Δp, prioritise conservation and discretisation sensitivity checks. 5% is an example, not a universal cut-off.

Deep dive · A script for Δp, ε_Q and the settling window

The script reads the four series downloaded with FileZilla (the postProcessing folder copied to Windows), computes Δp and ε_Q step by step and summarises the last N rows: mean, relative variation (max−min)/|mean| and slope. It uses only the Python standard library.

# monitor_report.py  -  python monitor_report.py <downloaded postProcessing folder> [N]
import sys, re, pathlib, statistics as st

def read_series(path):
    # returns (times, values) reading the first column after time; skips '#' comments
    t, v = [], []
    for line in open(path, encoding='utf-8', errors='replace'):
        if not line.strip() or line.lstrip().startswith('#'):
            continue
        tok = line.split()
        try:
            t.append(float(tok[0])); v.append(float(tok[1]))
        except (ValueError, IndexError):
            pass
    return t, v

def find(root, name):
    files = sorted(pathlib.Path(root, name).rglob('*.dat'))
    if not files:
        sys.exit('no .dat file in ' + str(pathlib.Path(root, name)))
    return files[-1]          # the latest start subfolder (restart)

root = sys.argv[1]
N = int(sys.argv[2]) if len(sys.argv) > 2 else 100
series = {k: read_series(find(root, k)) for k in ('pInlet', 'pOutlet', 'qInlet', 'qOutlet')}
n = min(len(s[1]) for s in series.values())
pin, pout = series['pInlet'][1][:n], series['pOutlet'][1][:n]
qin, qout = series['qInlet'][1][:n], series['qOutlet'][1][:n]
t = series['pInlet'][0][:n]
dp = [a - b for a, b in zip(pin, pout)]
eps = [abs(a + b) / ((abs(a) + abs(b)) / 2) * 100 for a, b in zip(qin, qout)]
w = slice(max(0, n - N), n)
dpw, epw, tw = dp[w], eps[w], t[w]
m = st.mean(dpw)
slope = (dpw[-1] - dpw[0]) / (tw[-1] - tw[0]) if tw[-1] != tw[0] else 0.0
print(f'total samples {n}, final window {len(dpw)} samples, from t={tw[0]} to t={tw[-1]}')
print(f'mean dp {m:.6g}   (max-min)/|mean| = {(max(dpw)-min(dpw))/abs(m)*100:.3g} %   slope {slope:.3g} per unit time')
print(f'mean eps_Q {st.mean(epw):.3g} %   max {max(epw):.3g} %   Q_in {st.mean(qin[w]):.6g}   Q_out {st.mean(qout[w]):.6g}')
with open('monitor_report.csv', 'w') as f:
    f.write('time,dp,eps_Q_percent\n')
    for a, b, e in zip(t, dp, eps):
        f.write(f'{a},{b},{e}\n')
print('full series written to monitor_report.csv')

Usage: python monitor_report.py C:\CFD\logs\myCase\postProcessing 200. The slope multiplied by the window length tells how much Δp is still changing: if it is of the same order as the variation you accept, the window has not settled yet. monitor_report.csv opens directly in Excel or Calc for plotting.

Assessment record to attach to every simulation

Parameter or checkWhat to record
Case identifier and dictionary revisionName, date, location, notes
OpenFOAM version and modelfoamVersion, solver, physical regime
MeshCell count, checkMesh results, changes
Time and numerical discretisationdeltaT/maxCo, fvSchemes, fvSolution
Execution statusCompleted/interrupted, exit code, log filename
Numerical indicatorsResiduals, continuity, Courant (if applicable)
Physical quantitiesΔp / ΔP, Q_in, Q_out, ε_Q and units
Settling assessmentSelected window, means, variation
Further validationTheory/experiment and mesh/time-step studies

8. Common mistakes when analysing from Windows

Mistake: a .dat file is empty or contains just a header. The solver may not have written a valid sample yet. Check writeControl/writeInterval, warnings in the solver log, and the appropriate restart folder under postProcessing.

Mistake: FileZilla appears to show old data. A local file is a static download: re-download and check size and modification time. Editing a local dictionary does not update a running remote case until explicitly transferred.

Mistake: charts imported into Excel make no sense. Data often contain # comment lines, whitespace separators and vector values like (Ux Uy Uz). Use appropriate delimited-text import settings, or split and normalise vector components first. Do not assume the U file is a plain four-column table.

Mistake: p is always interpreted as Pa. Read the field file, for example 0/p, and inspect dimensions: [0 2 -2 0 0 0 0] denotes kinematic pressure; [1 -1 -2 0 0 0 0] is pressure in pascals.

Mistake: low ε_Q is treated as sufficient proof. A good global balance cannot exclude unresolved local flow structures, wall effects, wrong velocity distributions or an under-resolved mesh.

Mistake: a universal threshold is applied to every simulation. Residuals, Courant limits and settling must be related to the simulation goals and physical regime. Document your criteria before interpreting results.

Deep dive · Importing into Excel with non-English regional settings

OpenFOAM writes numbers with a decimal point (2.5e-06). Excel set to a locale that uses a decimal comma (Italian, German, French…) misreads them: opened with a double click, many values become text or dates. The correct procedure:

  1. Data → From Text/CSV, choose the file;
  2. file origin: UTF-8; delimiter: Space, with “treat consecutive delimiters as one”;
  3. in Transform Data (Power Query) remove the rows starting with #;
  4. change the column types with Using Locale → English (United States), so the point is read as decimal separator.

In LibreOffice Calc: Language → English (USA) in the text import dialog, space separator, “Merge delimiters”. The monitor_report.py script of section 7 avoids the issue by writing a CSV with commas as field separators and points as decimal separators, to be imported with the same setting.

9. Final checklist and references

Before calling a result reliable: check that no fatal error occurred, that the mesh is suitable, field and BC units are coherent, residuals and numerical indicators are appropriate, balances are satisfactory, quantities of interest have stabilised in the physically relevant sense, and discretisation effects have been considered.

Primary technical references (OpenFOAM Foundation 14):

  1. OpenFOAM v14 — User Guide — general structure, modular solvers, tutorials.
  2. 7.4 — Sampling and monitoring data — foamGet, probes, residuals, foamMonitor.
  3. 2.1 — Backward-facing step — execution, log and stopping criteria in a steady example.
  4. v14 API — surfaceFieldValue — patch syntax and sum/areaAverage operations.
  5. v14 API — Function objects — system/functions and execution/write controls.
  6. 7.3 — Post-processing functionality — feature list and dimensional context.
  7. klogg — optional Windows tool for searching large logs.

Plots are schematic and use synthetic teaching data, not measured CFD results. Dictionary snippets must be adapted to each case’s patch names, fields and geometry.

Further useful references

  • klogg — optional Windows viewer for large logs.

Related guides: OpenFOAM on a Linux server, working from Windows (transfers, SSH, tmux, ParaView) and the Learning OpenFOAM 14 path, in particular controlDict and fvSolution.

#CFD #convergence #functionObjects #monitoring #OpenFOAM