Troubleshooting Guide

OpenFOAM manualInjection Is Not Compatible With Steady State: Why, and the Fix

You have a converged steady incompressible field and you want to release a set of particles from known positions and trace their paths. You set transient false and coupled false in your cloud properties, patchInjection runs fine, but manualInjection dies with "the manualInjection injection model is not compatible with steady state solution". This is not a bug and it is not your case. It is a design limitation that tells you something real about how steady particle tracking works, and there is a clean way to get exactly what you want.

Verified against the OpenFOAM 13 (Foundation, openfoam.org) source, and it holds for the ESI fork (openfoam.com) too: the injection model design is shared. The one fork difference is the dedicated tracking tool, covered in section 4, where the function object is named particles in the Foundation fork and icoUncoupledKinematicCloud in the ESI fork.

By CFDpilot · Updated June 2026

1. What the error actually means

The message comes from the base injection model when it sets up in steady cloud mode. With transient false, the cloud does not advance physical time the way a transient run does. Injection is interpreted as a rate that gets integrated over the steady solution, so every steady-compatible injector has to supply a massFlowRate. If it cannot, you get:

--> FOAM FATAL ERROR:
The manualInjection injection model is not compatible with steady state solution

So the solver is not refusing the file or your positions. It is telling you that this type of injector has no steady-state meaning.

2. One-shot vs rate: why patchInjection works and manualInjection does not

The two injectors describe fundamentally different things.

Steady cloud mode needs a rate to integrate. A continuous stream gives it one; a fixed list of parcels dumped at one instant does not. That is the whole reason one is accepted and the other is rejected. The limitation is consistent, not arbitrary.

3. The fix: track the cloud transient over the frozen field

Here is the part that solves your actual problem. You do not need steady cloud mode to get steady-state trajectories. A particle path depends only on the velocity field it moves through. If that field is frozen and converged, a cloud released into it traces exactly the steady pathlines you are after.

So run the cloud transient on top of your converged field:

solution
{
    active          true;
    // transient cloud, no feedback to the flow
    transient       true;
    coupled         false;
    cellValueSourceCorrection off;

    interpolationSchemes
    {
        U               cellPoint;
    }

    integrationSchemes
    {
        U               Euler;
    }
}

With transient true, manualInjection is allowed and your parcels are released from the exact positions in your positionsFile. One point to be clear about: coupled false only stops the parcels feeding momentum back to the flow, it does not by itself stop a solver from re-solving the carrier each step. To keep the field genuinely frozen you advect the cloud without solving the flow equations again. That is exactly what an uncoupled cloud does, which is the next section. Read U from your converged time, do not re-solve it, and because the field never changes the trajectories are the steady-state pathlines you wanted in the first place.

4. The dedicated tool: track the cloud without touching the flow

Rather than freezing the field by hand, the purpose-built way to do this is a function object that advects parcels through a specified velocity field with strictly one-way coupling, so the flow is never affected.

Both run the cloud in transient mode, which is exactly why manualInjection is accepted there: the parcels are released from your positionsFile at SOI and tracked through the fixed field, with no feedback to the flow.

5. If you really want to stay in steady cloud mode

You can, but only with a rate-based injector: patchInjection, patchFlowRateInjection, or coneInjection with a massFlowRate. These define a continuous stream entering at a patch or nozzle. The catch is that they throw away the one thing manualInjection gave you: precise, user-specified release points. If your release positions matter, steady mode is the wrong place and the transient cloud is the answer.

6. How to confirm the trajectories are right

Write the cloud positions over time and load them in ParaView as a particle track. Because the carrier field is steady, parcels released from the same point at different times should follow the same path. If two parcels from the same release point diverge, your field is not actually frozen, so check that the carrier solver is not still updating U between cloud steps.

Stop losing hours to cloud and injection config traps

CFDpilot reads your OpenFOAM case in the terminal, explains errors like this one, and tells you the fix and the reasoning behind it. No upload, it runs where your case lives.

Diagnose my case →
Official documentation

Frequently Asked Questions

Why is manualInjection not compatible with steady state in OpenFOAM?

It is a one-shot injector: it reads a positionsFile and releases every parcel at a single instant (SOI) with a fixed total mass, with no rate. Steady cloud mode interprets injection as a massFlowRate integrated over the steady solution, so it needs a rate to integrate. manualInjection has none, so it is rejected by design.

Why does patchInjection work in steady state but manualInjection does not?

patchInjection is rate-based (parcelsPerSecond, massFlowRate, duration), which describes a continuous stream and has a clean steady-state meaning. manualInjection is a fixed list of positions injected at one instant, which has no rate. Steady mode needs a rate, so the rate-based injector is accepted and the one-shot one is not.

How do I track particles in an already-converged steady flow field?

Run the cloud transient (transient true, coupled false) over the frozen converged field, using an uncoupled cloud so the flow is not re-solved. Note that coupled false only removes the feedback to the flow, it does not freeze it on its own; an uncoupled cloud advects parcels through the existing field without solving the carrier again. The trajectories are then the steady pathlines you want, and manualInjection works because transient mode is where it belongs.

What is an uncoupled kinematic cloud?

A cloud that advects parcels through a specified velocity field with one-way coupling, never feeding back to the flow. In the Foundation fork (incl. OpenFOAM 13) it is the particles function object, which tracks a cloud in a given incompressible velocity field without affecting the flow. In the ESI fork the equivalent is the icoUncoupledKinematicCloud function object. Both run transient, so manualInjection is allowed.

Can I keep steady cloud mode and still pick exact particle positions?

No. Steady mode only accepts rate-based injectors (patchInjection, patchFlowRateInjection, coneInjection with a massFlowRate). Those define a continuous stream, not a fixed list of positions. Exact release points require a transient cloud.

Will running the cloud transient give different trajectories than steady mode?

No, as long as the carrier field is frozen and converged. A trajectory depends only on the velocity field the parcel moves through. If that field is steady, a transient cloud traces the same pathlines, with the bonus that manualInjection lets you place parcels exactly where you want them.