Fluid–Structure Interaction

The fsi module couples laminar, single-species flow to a structural solver through preCICE.

Basic Coupled Case

Use a Stream build with preCICE and a structural solver with a preCICE adapter. Load both modules and update these entries in case.vars, using your moving-wall name in place of rod:

FSI settings in case.vars
 loadModule: gridMotion
 loadModule: fsi
 {

 // Boundary conditions
 boundary_conditions: <rod=noslip(adiabatic,moving,fsi=rodSolid)>

 // Time-stepping
 timeStep: 1.0e-2
 numTimeSteps: 10
 convergenceRelativeTolerance: <default=1.0e-4,pressure=1.0e-5>
 maxIterationsPerTimeStep: 200

 // FSI coupling
 meshCouplingMode: delayed
 fsiAdapterBackend: precice
 fsiPreCICEConfigFile: ../precice-config.xml
 }

rodSolid labels the fluid interface. moving enables mesh motion. Use the same label on adjoining FSI boundaries. Stream sends forces after the fluid equations meet their convergence tolerances.

Place precice-config.xml in the parent of the fluid and solid run directories. Configure the structural adapter as participant Solid with mesh SolidSurface. Use coordinates in metres and supply the solid surface connectivity through its adapter.

precice-config.xml
 <precice-configuration xmlns:data="urn:precice:data"
   xmlns:mapping="urn:precice:mapping" xmlns:m2n="urn:precice:m2n"
   xmlns:coupling-scheme="urn:precice:coupling-scheme">
   <data:vector name="Displacement" />
   <data:vector name="Force" />

   <mesh name="StreamNodes" dimensions="3">
     <use-data name="Displacement" />
     <use-data name="Force" />
   </mesh>
   <mesh name="SolidSurface" dimensions="3">
     <use-data name="Displacement" />
     <use-data name="Force" />
   </mesh>

   <participant name="Stream">
     <provide-mesh name="StreamNodes" />
     <read-data name="Displacement" mesh="StreamNodes" />
     <write-data name="Force" mesh="StreamNodes" />
   </participant>
   <participant name="Solid">
     <provide-mesh name="SolidSurface" />
     <receive-mesh name="StreamNodes" from="Stream" />
     <mapping:nearest-projection direction="write" from="SolidSurface"
       to="StreamNodes" constraint="consistent" />
     <mapping:nearest-projection direction="read" from="StreamNodes"
       to="SolidSurface" constraint="conservative" />
     <write-data name="Displacement" mesh="SolidSurface" />
     <read-data name="Force" mesh="SolidSurface" />
   </participant>

   <m2n:sockets acceptor="Stream" connector="Solid" exchange-directory=".." />

   <coupling-scheme:serial-explicit>
     <participants first="Stream" second="Solid" />
     <time-window-size value="1.0e-2" />
     <max-time-windows value="10" />
     <exchange data="Displacement" mesh="StreamNodes"
       from="Solid" to="Stream" initialize="on" />
     <exchange data="Force" mesh="StreamNodes"
       from="Stream" to="Solid" initialize="off" />
   </coupling-scheme:serial-explicit>
 </precice-configuration>

The example uses ten coupling steps of 0.01 s, matching timeStep and numTimeSteps in the fluid file. Displacement is the nodal displacement from the reference mesh in m. Force contains nodal loads in N acting from the fluid onto the solid.

Start the structural solver with this configuration. In a second terminal, run Stream from the fluid case directory:

stream -q solution case

Coupling Options

For loads relative to an ambient pressure of 1 atm, set fsiPressureReference: 101325.0. The value is in Pa. The default 0 uses absolute fluid pressure.

Use these inputs to match a different preCICE configuration:

preCICE names and configuration

Input

Default

Meaning

fsiParticipantName

Stream

Fluid participant

fsiPreCICEConfigFile

precice-config.xml

Configuration path

fsiReadMeshName

StreamNodes

Displacement mesh

fsiWriteMeshName

StreamNodes

Force mesh

fsiReadDataName

Displacement

Data read from the solid

fsiWriteDataName

Force

Data sent to the solid

Prescribed Displacement

For prescribed motion, select debugFile (the default) and set the boundary displacement from the reference mesh:

Prescribed-motion settings in case.vars
 {
 // Boundary conditions
 boundary_conditions: <
   rod=noslip(adiabatic,moving,fsi=rodSolid,
   fsiMockDisplacement=[0 m,1.0e-4 m,0 m])
 >

 // FSI coupling
 fsiAdapterBackend: debugFile
 }

To override individual nodes, write fsi_read_displacement.rankN.dat in fsiAdapterOutputDir. N is the MPI rank, or 0 for a serial run. Use node IDs from that rank’s fsi_interface_nodes.rankN.dat. Each row contains node-id dx dy dz, with displacement in metres. For node 1234:

1234 0 1.0e-4 0

Blank lines and # comments are allowed. Nodes omitted from the file use fsiMockDisplacement, whose default is zero.

Output

Add fsi to diagnostics to write interface and load files:

diagnostics: <fsi>

debugFile writes these files automatically. They use fsiAdapterOutputDir (default output), which also holds prescribed displacement files. Load files append; use a fresh output directory per run.

FSI output files

File

Contents

fsi_interface_nodes.rankN.dat

Node IDs and reference positions

fsi_interface_faces.rankN.dat

Reference faces and node connectivity

fsi_write_nodes.rankN.dat

Nodal positions and forces

fsi_write_mechanical.rankN.dat

Face loads, areas and wall velocities