Skip to content

Solid–Fluid Interaction ​

Overview ​

The InteractionSolidFluid class handles the coupling between fluid (LBM) and solid (phase-field) regions. It computes the velocities of solid particles induced by fluid forces and distributes the corresponding solid-body velocity field back into the Velocities object, which is then used by the advection and LBM modules.

Defined in openphase/include/FluidDynamics/InteractionSolidFluid.h.


Class declaration ​

cpp
struct InteractionSolidFluid : public OPObject
{
    InteractionSolidFluid(Settings& locSettings,
                          std::string InputFileName = DefaultInputFileName);

    void Initialize(Settings& locSettings,
                    std::string ObjectNameSuffix = "") override;
    void ReadInput(std::string InputFileName) override;

    void CalculateSolidVelocities(PhaseField& Phase, Velocities& Vel,
                                  const BoundaryConditions& BC,
                                  const double dt) const;

    static dVector3 LocalGrainVelocity(long i, long j, long k,
                                       const Grain& grain,
                                       const BoundaryConditions& BC,
                                       const PhaseField& Phase);
};

Bounce-back boundary condition ​

The fundamental solid–fluid boundary condition in LBM is bounce-back: a population that would stream into a solid node is reflected back in the opposite direction.

Standard bounce-back ​

text
If node (i,j,k) is solid:
    f_{-x,-y,-z}(i,j,k) ← f_{x,y,z}(i,j,k)

This implements a no-slip (zero velocity) condition at the solid surface. In OpenPhase the bounce-back is applied in FlowSolverLBM::BounceBack() and Propagation().

Elastic bounce-back ​

When Do_BounceBackElastic = true, populations are reflected using the moving boundary correction:

(1)f−x,−y,−z(x,t+1)=fxyz(x,t)−2wxyzexyz⋅uwcs2ρ

where uw is the solid wall velocity. This is energy-conserving and essential for mobile solid particles.


Drag force ​

When Do_Drag = true, the solver computes a viscous drag force at the diffuse solid–fluid interface:

cpp
void CalculateForceDrag(int i, int j, int k,
                        PhaseField& Phase,
                        const Velocities& Vel);

The drag contribution to the force density is proportional to the velocity difference between the fluid and the solid:

(2)Fdrag(x)=h∗ϕs(x)[us(x)−uf(x)]

where h∗ is the dimensionless drag parameter (h_star), ϕs is the solid fraction, us is the solid velocity, and uf is the fluid velocity.


Rigid body dynamics ​

InteractionSolidFluid computes translational and rotational velocities of solid particles using Newton's law for rigid bodies, driven by the forces that the fluid exerts on them.

With inertia (DoInertia = true) ​

The grain velocity is updated by integrating:

(3)mv˙=Ffluid

(4)Iω˙=τfluid

where m is the grain mass, I is the moment of inertia, Ffluid is the net fluid force, and τfluid is the fluid torque.

Without inertia (DoInertia = false) ​

A damped (quasi-static) model is used instead:

(5)v=τtransFfluid

(6)ω=τrotτfluid

where τtrans and τrot are the translational and rotational relaxation parameters.

Velocity limit ​

When DoLimitVelocity = true, solid body velocities are clipped to VelocityLimit to prevent numerical blow-up when solid particles collide.


Grain geometry helpers ​

Internally, the class computes center-of-mass and moment of inertia for each grain using domain-summed integrals:

cpp
static void CalculateCenterOfMass(PhaseField& Phase,
                                   const BoundaryConditions& BC);
static void CalculateMomentOfInertia(PhaseField& Phase,
                                      const BoundaryConditions& BC);

These computations include OpenMP and MPI reduction, making them efficient on HPC systems.


Obstacle state tracking ​

FlowSolverLBM tracks changes in obstacle nodes to correctly conserve fluid mass:

StateMeaning
AbsentFluid node
PresentSolid node
AppearedNewly solidified (fluid → solid)
VanishedNewly melted (solid → fluid)
ChangedDensitySolid changed density (e.g. due to composition change)

When a solid node appears, the fluid it displaced must be redistributed. When a solid node vanishes, new populations are initialized from the neighboring fluid state via SetFluidNodesNearObstacle().


Parameters ​

ParameterTypeDescription
TauTranslationdoubleTranslational relaxation time (no-inertia model)
TauRotationdoubleRotational relaxation time (no-inertia model)
VelocityLimitdoubleMaximum solid body velocity
DoInertiaboolEnable inertial rigid body dynamics
DoRotationsboolEnable rotational degrees of freedom
DoLimitVelocityboolEnable velocity clamping
DoEnforceZeroTotalMomentumboolConserve total linear momentum
DoEnforceZeroTotalAngularMomentumboolConserve total angular momentum

Typical usage ​

cpp
InteractionSolidFluid ISF(OPSettings, InputFile);

// each timestep:
ISF.CalculateSolidVelocities(Phase, Vel, BC, dt);
FL.Solve(Phase, Vel, BC);

CalculateSolidVelocities must be called before FlowSolverLBM::Solve() so that the solid velocities are available for the elastic bounce-back computation.


Numerical considerations ​

  • For sintering simulations where grains continuously merge and split, the grain tracking inside InteractionSolidFluid relies on stable grain IDs from the PhaseField module.
  • The moment of inertia calculation assumes isotropic grain density; anisotropic grains may require a custom implementation.
  • DoEnforceZeroTotalMomentum prevents net drift of the solid ensemble in periodic domains but should not be combined with an imposed flow.

Released under the GNU GPLv3 License.