Multiple fluid domains interacting with a shell structure - preCICE configuration on the OpenFOAM side

Hi Satish,

I would indeed recommend to use two instances of the same fluid solver:

<participant name="Fluid-Inner"> ... </participant>
<participant name="Fluid-Outer"> ... </participant>
<participant name="Solid"> ... </participant>

Simply, because your two fluid domains have no direct interaction. I could imagine that some numerical solvers do not even like this full block structure. Also, using two fluid solver, you have much more flexibility on how to configure both. As you describe above you want water and air. Maybe you also want different numerical setting for both in the long run.

As you use OpenFOAM, both fluid participants then have their own preciceDict file.

Coupling scheme

For implicit coupling, you should then use a multi-coupling scheme:

<coupling-scheme:multi>
  <participant name="Solid" control="yes"/>
  <participant name="Fluid-Inner" />
  <participant name="Fluid-Outer" />
  ...
</coupling-scheme:multi>

You should give control to the Solid participant as it has connections to both other solvers. Since preCICE v2.3, also one of the fluid participants could be in control, but this comes with restrictions and is presumably less efficient in your case.

For explicit coupling, you could simply combine two explicit coupling schemes:

<coupling-scheme:parallel-explicit>
  <participants first="Fluid1" second="Solid"/>
  ...
</coupling-scheme:parallel-explicit>
<coupling-scheme:parallel-explicit>
  <participants first="Fluid2" second="Solid"/>
  ...
</coupling-scheme:parallel-explicit>

You could also do two serial-explicit schemes. Then both fluid participants would still run in parallel, but both staggered with the solid participant.

Boundary conditions

The tricky part here is the solid ball. Somewhere on the surface of the ball, you need a Dirichlet boundary condition, otherwise it is mathematically ill-defined. As an intermediate step, you could mount the ball, meaning to set displacements on some part to zero. Then, on the rest of the surface, you could use Neumann boundary conditions (setting forces).

Without this mounting, things become complicated. Then, you need to turn one fluid solver around: it then needs to read forces (or stresses) and write displacements. I am not sure if the OpenFOAM adapter can already handle this. The recent extension to also support solids4foam goes in this direction.

Let’s assume for the moment that you mount the ball. The participants could then look like this:

<participant name="Fluid-Inner">
  <use-mesh name="Fluid-Inner-Mesh" provide="yes" />
  <write-data name="Force-Inner" mesh="Fluid-Inner-Mesh" />
  <read-data name="Displacement-Inner" mesh="Fluid-Inner-Mesh" />
  
  <use-mesh name="Solid-Mesh-Inner" from="Solid" />
  <mapping:nearest-neighbor 
    direction="write"
    from="Fluid-Inner-Mesh"
    to="Solid-Mesh-Inner"
    constraint="conservative" />
  <mapping:nearest-neighbor
    direction="read"
    from="Solid-Mesh-Inner"
    to="Fluid-Inner-Mesh"
    constraint="consistent" />
</participant>

<participant name="Fluid-Outer">
  <use-mesh name="Fluid-Outer-Mesh" provide="yes" />
  <write-data name="Force-Outer" mesh="Fluid-Outer-Mesh" />
  <read-data name="Displacement-Outer" mesh="Fluid-Outer-Mesh" />
  
  <use-mesh name="Solid-Mesh-Outer" from="Solid" />
  <mapping:nearest-neighbor 
    direction="write"
    from="Fluid-Outer-Mesh"
    to="Solid-Mesh-Outer"
    constraint="conservative" />
  <mapping:nearest-neighbor
    direction="read"
    from="Solid-Mesh-Outer"
    to="Fluid-Outer-Mesh"
    constraint="consistent" />
</participant>

The complete config:
config.xml (4.4 KB)

Required changes in solid solver

Probably obvious: The solid solver then needs to be able to define two interfaces.

int innerMeshID = precice.getMeshID("Solid-Mesh-Inner");
int outerMeshID = precice.getMeshID("Solid-Mesh-Outer");
...
precice.setMeshVertices(innerMeshID, innerVertexSize, innerCoords, innerVertexIDs);
precice.setMeshVertices(outerMeshID, outerVertexSize, outerCoords, outerVertexIDs);

More

we are currently using preCICE version 2.2.0.

This should not be a problem, but I would still recommend to update preCICE. There are a few bugs we fixed and other things that are simply more efficient. Updating should be very easy. Let me know if you do not know how.

FEBio

Did you know that there is also some effort coupling FEBio here?