# My third tutorial: `beamInCrossFlow`

## Tutorial Aims

- Demonstrate the solution of an external flow fluid-solid interaction problem;
- Explain how to run a fluid-solid interaction simulation in solids4foam.

## Case Overview

This case consists of a thick elastic plate attached to the bottom surface of a rectangular channel (see the figure above). Due to symmetry, only half of the spatial domain is considered. An incompressible viscous fluid with a density of 1000 kg/m3 and kinematic viscosity of 0.001 m2/s enters the channel from the left-hand side with a parabolic velocity profile.

This case can be analysed in two forms:

- The original form, proposed by Richter: The peak inlet velocity is 0.2 m/s, corresponding to Re = 40 with respect to the plate height (h = 0.2 m). The peak inlet velocity gradually increases from zero at t = 0 s to its maximum value at t = 4 s using the following transition function \(0.2 [1 − \cos(\pi t/4)]/2\). A constant pressure is imposed at the channel outlet, and a no-slip boundary condition is applied on the channel walls. The elastic plate has a density of 1000 kg/m3, Young's modulus of 1.4 MPa (shear modulus of 0.5 MPa), and a Poisson's ratio of 0.4.
- A modified form, analysed by Gillebaart et al. and Tuković et al.: The peak inlet velocity is increased to 0.3 m/s, and the Young's modulus of the solid beam is reduced to 10 kPa. In addition, the velocity reaches its maximum value at 1 s, and the simulation continues until the beam reaches steady-state. The purpose of these changes is to demonstrate large solid displacements and fluid mesh motion.

The fluid is described by incompressible Newtonian isothermal laminar flow, where the Navier-Stokes governing equations take the form:

For the solid, we assume finite strains (though a small strain assumption would be OK in the the original form of the case) with the material behaviour described by the neo-Hookean hyperelastic law:

Kinematic and dynamic conditions hold at the interface between the fluid and solid regions. The kinematic conditions state that the velocity and displacement must be continuous across the interface: The dynamic conditions follow from linear momentum conservation and state that the forces are in equilibrium:

A partitioned approach is adopted for enforcing these interface conditions where the fluid and solid regions are solved separately. A strongly-coupled Dirichlet-Neumann coupling algorithm is used:

```
for all time-steps
do
solve fluid domain
pass fluid interface forces to the solid interface
solve solid domain
pass solid interface velocities to the fluid
interface using under-relaxation
update the fluid mesh
while not converged
end
```

## Expected Results

The incoming flow imparts pressure and viscous forces on the plate, causing it to bend. Following some initial transient effects, the flow and beam reach a steady-state. In the modified form of the case, with an increased peak inlet velocity of 0.3 m/s and reduced Young's modulus of 10 kPa, displacement of point A is pexected to be (0.01463, 0.005, −0.000447) m at steady state. Further details of the case can be found in Ž. Tuković, A. Karač, P. Cardiff, H. Jasak, A. Ivanković (2018) OpenFOAM Finite Volume Solver for Fluid-Solid Interaction; in particular, see Fig. 28 therein. The figure below shows the displacement field in the beam, the fluid velocity streamlines, and the fluid pressure on the channel ground, wall and outlet.

## Running the Case

The tutorial case can be run using the included `Allrun`

script, i.e. `> ./Allrun`

. In this case, the `Allrun`

script is

```
#!/bin/bash
# Source tutorial run functions
. $WM_PROJECT_DIR/bin/tools/RunFunctions
# Source solids4Foam scripts
source solids4FoamScripts.sh
# Check case version is correct
solids4Foam::convertCaseFormat .
# Create meshes
solids4Foam::runApplication -s solid blockMesh -region solid
solids4Foam::runApplication -s fluid blockMesh -region fluid
# Run solver
if [[ "$1" == "parallel" ]]; then
# Run parallel
solids4Foam::runApplication -s fluid decomposePar -region fluid
solids4Foam::runApplication -s solid decomposePar -region solid
solids4Foam::runParallel solids4Foam
solids4Foam::runApplication -s fluid reconstructPar -region fluid
solids4Foam::runApplication -s solid reconstructPar -region solid
else
# Run serial
solids4Foam::runApplication solids4Foam
fi
# Create plots
if command -v gnuplot &> /dev/null
then
echo "Generating deflection.pdf using gnuplot"
gnuplot deflection.gnuplot &> /dev/null
echo "Generating force.pdf using gnuplot"
gnuplot force.gnuplot &> /dev/null
else
echo "Please install gnuplot if you would like to generate the plots"
fi
```

where the `solids4Foam::convertCaseFormat .`

script makes minor changes to the case to make it compatible with your version of OpenFOAM/foam-extend. As can be seen, if the argument "parallel" is passed to the `Allrun`

script (i.e. `> ./Allrun parallel`

) it will run the case in parallel. After the solver has finished, `force.pdf`

and `deflection.pdf`

plots are generated if the `gnuplot`

program is installed.

Remember that a tutorial case can be cleaned and reset using the included `Allrun`

script, i.e. `> ./Allclean`

.

## Analysing the Results

In the ParaView, both the solid and fluid regions are loaded by default. The *Extract Block* filter in ParaView can be used to extract the solid region, and a second instance of the *Extract Block* filter for the fluid region. In that way, the fluid region can be coloured by a fluid field (e.g. `p`

or `U`

) and the solid region by a solid field (e.g. `D`

or `sigmaEq`

). As an alternative to using the *Extract Block* filter, two instances of the case can be opened (File -> Open -> case.foam), where one opens the "fluid/internalMesh" and the other opens the "solid/internalMesh".

# Delving Deeper

If you would like to learn more about the case, please continue; if not, how about you check out another tutorial.

## Case Structure

The case follows the typical multi-region (e.g. as used by `chtMultiRegionSimpleFoam`

) case structure:

```
beamInCrossFlow
├── 0
│ ├── fluid
│ │ └── ...
│ └── solid
│ │ └── ...
├── Allclean
├── Allrun
├── constant
│ ├── fluid
│ │ └── ...
│ ├── fsiProperties
│ ├── physicsProperties
│ └── solid
│ └── ...
└── system
├── fluid
│ └── ...
└── solid
└── ...
```

where `fluid`

and `solid' sub-directories are present in the `

0`, `

constant` and `

system` directories.

As in all solids4foam cases, the `constant/physicsProperties`

dictionary must be present, where, in this case, a fluid-solid interaction analysis is specified:

```
type fluidSolidInteraction;
```

As a fluid-solid interaction, a `constant/fsiProperties`

dictionary must also be present, where, in this case, the Aitken's accelerated coupling algorithm is specified:

```
fluidSolidInterface Aitken;
AitkenCoeffs
{
// ...
}
```

Coupling algorithm parameters are given here, e.g. solid interface patch(es), fluid interface patch(es), maximum number of FSI correctors, FSI tolerance, etc.

## Solver Output

During a partitioned fluid-solid interaction analysis, the `solids4Foam`

solver will perform multiple outer FSI iterations per time-step, where both the fluid and solid and solved within each FSI iteration. Several types of information will be printed to the log, including

- Fluid model residual information, e.g.
`U`

and`p`

residuals and iteractions - Fluid mesh motion information
- Solid model residual information
- FSI residual and iteration numbers
- Force(s) on the FSI interface(s)

For example:

```
Time = 0.1, iteration: 15
Current fsi under-relaxation factor (Aitken): 0.980175
Maximal accumulated displacement of interface points: 8.51423e-07
Evolving fluid model: icoFluid
Courant Number mean: 0.00184822 max: 0.0346019 velocity magnitude: 0.00487047
time step continuity errors : sum local = 9.26048e-10, global = -2.65049e-11, cumulative = -2.74836e-09
time step continuity errors : sum local = 2.0302e-10, global = -1.72198e-11, cumulative = -2.76558e-09
time step continuity errors : sum local = 1.11805e-10, global = 6.68802e-12, cumulative = -2.7589e-09
Setting traction on solid patch
Total force (fluid) = (-0.147015 0.378642 -0.38067)
Total force (solid) = (0.146715 -0.378943 0.380941)
Evolving solid solver
Solving the updated Lagrangian form of the momentum equation for DD
Corr, res, relRes, matRes, iters
Both residuals have converged
2, 5.23068e-07, 7.10068e-07, 0, 2
Current fsi relative residual norm: 5.70921e-07
Alternative fsi residual: 5.70555e-07
```

## Tips for Fluid-Solid Analyses

### Problem: when I view the fluid and solid in ParaView, there is a gap between the fluid and solid interface: the solid domain does not align with the fluid domain.

**Solution 1**: some of the solidModels use a non-moving mesh formulation so, by default, some solids may not move at all when shown in ParaView. To show the solid domain deformation/motion in ParaView, select the solid case and use the “Warp By Vector” filter with the displacement (“D” or “pointD”) field. If there is still a gap between the fluid and solid, see Solution 2 below.

**Solution 2**: if the FSI loop does not converge then the FSI interface constraints (see below) may not be strictly enforced; examine the “fsi residual” in the log file and check if the maximum number of FSI iterations is being reached. If the FSI method is not converging to the required tolerance, then increases the maximum number of FSI correctors and/or decrease the initial relaxation factor (in fsiProperties). In addition, you can try a different FSI coupling procedure. If the FSI loop is converging but there is still a gap between the fluid and solid, see the next points on the following slide.

**Solution 3**: if the FSI loop is converging but there is still a gap between the fluid and solid, then try increase the FSI solution tolerance (in fsiProperties); you may also need to increase the maximum number of FSI correctors to achieve a tighter tolerance. If this still does not help, see Solution 4 below.

**Solution 4**: try create a conformal fluid-to-solid interface i.e. make the fluid interface patch mesh exactly the same as the solid interface patch mesh.

**Solution 5**: if the FSI method is still struggling to converge, try make the problem “easier” by setting the solid to be temporarily stiffer and denser (in mechanicalProperties) by e.g. multiple orders of magnitude. If the problem works with the artificially stiff/dense solid, then slowly decrease the solid properties towards the real ones until you find the point at which the FSI methods breaks; then try decreasing the starting FSI relaxation factor and/or maximum number of FSI correctors and/or FSI coupling algorithm to determine the critical/optimal algorithm variables.

### Problem: the solid model is not converging.

**Solution 1**: try use a lower under-relaxation factor in the solid fvSolution relaxationFactors sub-dict; use a value of 0.1-1.0 for the “D” or “DD” fields and/or 0.9-1.0 for the “D” or “DD” equations.

**Solution 2**: try a different (more robust) solid model e.g. linear geometry solid models, such as linGeomTotalDispSolid and coupledUnsLinGeomLinearElasticSolid, tend to converge better than the non-linear geometry models.

### General Tips

Perform independent analyses on the solid and fluid domains separately, before enabling FSI coupling, to ensure all fluid and solid properties, meshes, schemes, etc. are reasonable.

If you are having convergence issues, try prepare a more simple - but representative - version of your case and make sure that works: it may provide understanding of critical settings.

If you are having convergence issues, try use a conformal mesh at the fluid-to-solid interface.

**Tip**: if you are having convergence issues, try a different (more robust) fluid model and/or a different (more robust) solid model; the pUCoupledFoam fluidModel tends to converge well and the linear geometry solid models (e.g. linGeomTotalDispSolid or coupledUnsLinGeomLinearElasticSolid) tend to converge better than the non-linear geometry models

## Code

`fluidSolidInterface`

For the `cylinderInChannel`

test case, we have selected a "fluidSolidInterface" analysis in the `physicsProperties`

dictionary: this means a `fluidSolidInterface`

class will be selected; then, we specify the actual `fluidSolidInterface`

class to be the `AitkenCouplingInterface`

class.

The code for the `AitkenCouplingInterface`

class is located at:

```
solids4foam/src/solids4FoamModels/fluidSolidInterfaces/AitkenCouplingInterface/AitkenCouplingInterface.C
```

Let us examine the code, in particular, the "evolve" function of this class, to see how the FSI procedure is implemented.

```
bool AitkenCouplingInterface::evolve()
{
initializeFields();
updateInterpolator();
scalar residualNorm = 0;
if (predictSolid_)
{
updateForce();
solid().evolve();
residualNorm = updateResidual();
}
do
{
outerCorr()++;
// Transfer the displacement from the solid to the fluid
updateDisplacement();
// Move the fluid mesh
moveFluidMesh();
// Solve fluid
fluid().evolve();
// Transfer the force from the fluid to the solid
updateForce();
// Solve solid
solid().evolve();
// Calculate the FSI residual
residualNorm = updateResidual();
}
while (residualNorm > outerCorrTolerance() && outerCorr() < nOuterCorr());
solid().updateTotalFields();
return 0;
}
```