OpenFOAM-OpenFOAM FSI coupling

Hi @Makis,
Some news coming from this FSI experiment !

I have been working on the Solid code for quite a bit of time, it’s better, and now I am coming back once again to the FSI interactions. I’ve not reached what I want but I think I’m getting there.

To start off, let me do a quick recap of my framework:

  • A vertex-centred FVM solid mechanics code based on OpenFoam-6,
  • Any simple CFD solver from OpenFoam-6 (pimpleFoam will do),
  • The openfoam-adapter, more especially the branch of @JSeuffert
  • I want to reproduce the perpendicular flap problem.

I would like to achieve first a one-way coupling; namely and in simple words, I would like to solve a prescribed motion on the Solid side, and pass the displacements to my Fluid solver, so its velocity field is updated accordingly.

At the moment, I am able to make preCICE run both simulations in conjunction. Following is the content of the files of interest:

precice.config.xml

<?xml version="1.0"?>

<precice-configuration>

  <log>
    <sink filter="%Severity% > debug and %Rank% = 0" format="---[precice] %ColorizedSeverity% %Message%" enabled="true"/>
  </log>

  <solver-interface dimensions="3">

    <data:vector name="Forces"/>
    <data:vector name="Displacements"/>

    <mesh name="Fluid-Mesh-Faces"> <use-data name="Forces"/> </mesh>
    <mesh name="Fluid-Mesh-Nodes"> <use-data name="Displacements"/> </mesh>
    <mesh name="Solid-Mesh-Nodes"> <use-data name="Forces"/> <use-data name="Displacements"/> </mesh>

    <participant name="Fluid">
      <use-mesh name="Fluid-Mesh-Faces" provide="yes"/>
      <use-mesh name="Fluid-Mesh-Nodes" provide="yes"/>
      <use-mesh name="Solid-Mesh-Nodes" from="Solid"/>
      <write-data name="Forces" mesh="Fluid-Mesh-Faces"/>
      <read-data name="Displacements" mesh="Fluid-Mesh-Nodes"/>
      <mapping:rbf-thin-plate-splines direction="write" from="Fluid-Mesh-Faces" to="Solid-Mesh-Nodes" constraint="conservative"/>
      <mapping:rbf-thin-plate-splines direction="read" from="Solid-Mesh-Nodes" to="Fluid-Mesh-Nodes" constraint="consistent"/>
    </participant>

    <participant name="Solid">
      <use-mesh name="Solid-Mesh-Nodes" provide="yes"/>
      <read-data name="Forces" mesh="Solid-Mesh-Nodes"/>
      <write-data name="Displacements" mesh="Solid-Mesh-Nodes"/>
      <!--watch-point mesh="Solid" name="point1" coordinate="0.6;0.2;0." /-->
    </participant>

    <m2n:sockets from="Fluid" to="Solid"/>

    <coupling-scheme:serial-implicit>
      <time-window-size value="0.01" />
      <max-time value="0.25"/>
      <participants first="Fluid" second="Solid"/>
      <exchange data="Forces" mesh="Solid-Mesh-Nodes" from="Fluid" to="Solid"/>
      <exchange data="Displacements" mesh="Solid-Mesh-Nodes" from="Solid" to="Fluid" initialize="0" />

      <max-iterations value="50"/>
      <relative-convergence-measure limit="1e-4" data="Displacements" mesh="Solid-Mesh-Nodes"/>
      <relative-convergence-measure limit="1e-4" data="Forces" mesh="Solid-Mesh-Nodes"/>
      <extrapolation-order value="2"/>

      <acceleration:IQN-ILS>
        <data name="Displacements" mesh="Solid-Mesh-Nodes"/>
        <preconditioner type="residual-sum"/>
        <filter type="QR1" limit="1e-6"/>
        <initial-relaxation value="0.1"/>
        <max-used-iterations value="50"/>
        <time-windows-reused value="10"/>
      </acceleration:IQN-ILS>

    </coupling-scheme:serial-implicit>


  </solver-interface>

</precice-configuration>

Fluid/system/preciceDict

FoamFile
{
    version     2.0;
    format      ascii;
    class       dictionary;
    location    "system";
    object      preciceDict;
}

preciceConfig "precice-config.xml";

participant Fluid;

modules (FSI);

interfaces
{
  Interface1
  {
    mesh              Fluid-Mesh-Faces;
    patches           (interface);
    locations         faceCenters;

    readData ( );

    writeData ( Forces );
  };

  Interface2
  {
    mesh             Fluid-Mesh-Nodes;
    patches          (interface);
    locations        faceNodes;

    readData ( Displacements );

    writeData ( );
  };
};

FSI
{
  rho rho [1 -3 0 0 0 0 0] 1100;
}

Solid/system/preciceDict

FoamFile
{
    version     2.0;
    format      ascii;
    class       dictionary;
    location    "system";
    object      preciceDict;
}

preciceConfig "precice-config.xml";

participant Solid;

modules (FSI);

interfaces
{
  Interface1
  {
    mesh              Solid-Mesh-Nodes;
    patches           (interface);
    locations         faceNodes;

    readData ( Forces );

    writeData ( Displacements ); //Displacements //u
  };
};

FSI
{
  solverType incompressible;
  namePointDisplacement u;
  rho rho [1 -3 0 0 0 0 0] 1100;
}

Note: actually at the moment ./Allrun starts both solvers but they stay stuck at

—[preciceAdapter] [DEBUG] Initalizing the preCICE solver interface…
—[precice] Setting up master communication to coupling partner/s

The problem might come from a misreading of the data by the solver and/or preCICE, but I’m not comfortable at all with the setup of the coupling ( the 3 files above ).

I don’t want to clutter my post much more so do not hesitate to ask me for logs, setup files and whatsoever.

If both solvers are at this state, the most common reason is that they are trying to connect to wrong addresses, left-over from a previous run. There must be a directory precice-run/ next to your precice-config.xml, remove it and try again. This should also be in the Allclean script.

Indeed it was just a silly mistake…

Now I am facing another error: When I hit the run, the Solid.log prints

Time Step =1
 deltaT = 0.0001 s
 Time = 0.0001 s
 Simulation completed = 2.220446e-18% - Clock = 2s
---[preciceAdapter] [DEBUG] Writing coupling data...


--> FOAM FATAL ERROR:
Attempt to cast type calculated to type fixedValue

    From function To& Foam::refCast(From&) [with To = Foam::fixedValuePointPatchField<Foam::Vector<double> >; From = Foam::pointPatchField<Foam::Vector<double> >]
    in file /home/thomas/OpenFOAM/OpenFOAM-6/src/OpenFOAM/lnInclude/typeInfo.H at line 114.

FOAM aborting

It looks like a problem with ‘pointDisplacement’ in my Fluid solver (as I do not use pointDisplacement in my solid solver). My initial and boundary conditions are as follows:

internalField   uniform (0 0 0);

boundaryField
{
    interface
    {
        type fixedValue;
        value $internalField;
    }

    "(inlet|outlet)"
    {
        type            fixedValue;
        value           uniform (0 0 0);
    }

    "(sides|top|bottom)"
    {
        type slip;
    }

}

I am inspired from the flap_perp tutorial.

As I want to perform a one-way coupling, I may have to review the precice-config.xml.

This is (as you already guessed) related to the boundary conditions and only related to the adapter (not preCICE). We currently don’t have force reading (and displacement writing) implemented in the adapter, so I guess you already extended the adapter to do this? Then you would need to set compatible types for the boundary conditions, but I cannot help much without looking at the additional code.

This topic is already quite long and old, so please excuse me if I am missing details. Please recap any important related details in the next posts. :slightly_smiling_face:

I see now that in your Fluid/system/preciceDict you have somewhere:

this will not work by default (it should complain that it is not implemented).

No problem at all! I just did not want to clutter my post with a lot of information.
So I am actually using this branch together with OF-6. @JSeuffert took care of the implementation of the Forces (but not stress) reading.

Note: I changed to an explicit coupling and the Fluid runs until the end, then detects an error in the solid part:

---[preciceAdapter] [DEBUG] Writing coupling data...
---[preciceAdapter] [DEBUG] Advancing preCICE...
---[precice]  Time window completed
---[precice]  it 1 | dt# 26 | t 0.25 of 0.25 | dt 0.01 | max dt 0.01 | ongoing no | dt complete yes |
---[preciceAdapter] [DEBUG] Reading coupling data...
---[preciceAdapter] [DEBUG] Adjusting the solver's timestep...
---[preciceAdapter] [DEBUG] The solver's timestep is the same as the coupling timestep.
---[preciceAdapter] The coupling completed.
---[preciceAdapter] [DEBUG] Finalizing the preCICE solver interface...
---[precice] ERROR:  Receive using sockets failed with system error: read: End of file

The Solid.log yielded:

--> FOAM FATAL ERROR:
Attempt to cast type calculated to type fixedValue

    From function To& Foam::refCast(From&) [with To = Foam::fixedValuePointPatchField<Foam::Vector<double> >; From = Foam::pointPatchField<Foam::Vector<double> >]
    in file /home/thomas/OpenFOAM/OpenFOAM-6/src/OpenFOAM/lnInclude/typeInfo.H at line 114.

FOAM aborting

#0  Foam::error::printStack(Foam::Ostream&) at ??:?
#1  Foam::error::abort() at ??:?
#2  preciceAdapter::FSI::Displacement::write(double*, bool, unsigned int) at ??:?
#3  preciceAdapter::Interface::writeCouplingData() at ??:?
#4  preciceAdapter::Adapter::writeCouplingData() at ??:?
#5  preciceAdapter::Adapter::execute() at ??:?
#6  Foam::functionObjects::preciceAdapterFunctionObject::execute() at ??:?
#7  Foam::functionObjectList::execute() at ??:?
#8  Foam::Time::run() const at ??:?
#9  Foam::Time::loop() at ??:?

which, I suppose, is a complaint about the BC of ‘pointDisplacement’ at the interface. As a recall, this BC is defined as

interface
{
    type fixedValue;
    value $internalField;
}

I tried changing it to ‘calculated’, but the error in my Solid.log remains + Fluid.log throws me

--> FOAM FATAL ERROR:
cannot be called for a calculatedFvPatchField
    on patch interface of field cellDisplacement in file "./Fluid/0/cellDisplacement"
    You are probably trying to solve for a field with a default boundary condition.

    From function Foam::tmp<Foam::Field<Type> > Foam::calculatedFvPatchField<Type>::gradientInternalCoeffs() const [with Type = Foam::Vector<double>]
    in file fields/fvPatchFields/basic/calculated/calculatedFvPatchField.C at line 187.

Note 2: Actually a few days ago I was able to run a simulation with a uniform (0 0 0) velocity and without error.

I switch to this post:

So I got another idea. I am not using ‘pointDispacement’ but ‘u’ to move my nodes in my Solid code. Its conditions are defined as:

{
    version     2.0;
    format      ascii;
    class       pointVectorField;
    location    "0";
    object      u;
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //

dimensions      [0 1 0 0 0 0 0];

internalField   uniform (0 0 0);

boundaryField
{
    interface
    {
        type            calculated;
    }
    bottom
    {
        type            calculated;
    }
}

In the preciceDict of my Solid code, I do specify that this file is my pointDisplacement:

FSI
{
  solverType incompressible;
  namePointDisplacement u;
  rho rho [1 -3 0 0 0 0 0] 1100;
}

I think that the openfoam-adapter is expecting my ‘u’ to be ‘fixedValue’ on the interface…
EDIT: Doing so, the simulation works and both codes are running in parallel. I’ll come back once I have read the logs.

EDIT 2: I have been able to do my one-way coupling. I will post here the git repo with all of my setup once I clean everything. It’s a big leap as it’s a first successful one-way coupling ‘Solid to Fluid’.

I collected the test case and the openfoam-adapter there:
vcALE/FSI at master · dashqua/vcALE (github.com)

The test case works as follows:

  • The solid motion is solved independently using an in-house solver.
  • preCICE passes interpolated displacements from the solid to the fluid solver.
  • The fluid is solved accordingly.

The openfoam-adapter is based on the PR that I mentionned. The modifications are straight forward. I also added an option ‘nameForce’ for Force and Stress.

I would now like to tackle the exchange of forces. So far, I think I correctly set the precice-config.xml file but there is no force fields in the directories of my solid solver.
I added a test in openfoam-adapter/FSI.C +75 which is not passed when I check the logs. It makes me think I am not using the right version of the adapter. How can I check this ?

EDIT: To use the adapter, I just run (successfully) the Allwmake script and I run my test case.

To solve the issue I mention in the previous post, just wget all the 4 FSI/volDisplacement* files in there. For some reason, the author removed these files in the last commit but they are still needed for the compilation to succeed.

EDIT: another possible solution is to directly pull the penultimate commit of the PR, I suppose.

So, what is now still open? :smiley:

This should only work by accident, if at all. The adapter will still try to find an object u, but it will treat it as if it was pointDisplacement.

On the fluid side, the adapter expects u to be movingWallVelocity on the interface.

The adapter will be built (by default) in your $FOAM_USER_LIBBIN, which is different for each OpenFOAM installation and user. As you already noticed, always make sure that you first successfully build it (using Allwmake).

I think that your case now relies on several specific commits of forks, so it gets more and more difficult for me (or I guess anyone else now) to help you. But I understand also how it feels from your side. :sweat_smile: Keep documenting what you are doing and it would be nice to make a summary once you manage to make it working. I hope I can help in the way.

Hi @Makis !
I realised that I may have been working with the default openfoam-adapter from the very beginning. That said, there are a few points that have to be highlighted from the recent progress:

This is mandatory for me because my solid solver is using a displacement field called u, which has the same function as pointDisplacement, just the name changes.

Indeed ! However, I was referring to the solid side: my u is completely calculated within the solver and no BC are provided. Therefore, its BCs are calculated on all patches. To circumvent this issue, I initialized a field uD with fixedValue `uniform (0 0 0) on all patches.

Note: Actually uD is read from 0/uD, but I could have also initialized this field uniquely from the code, by setting up the wanted BCs (I think there is a simple way to change BCs during runTime in openfoam).

So here is the thing: I just noticed a problem with the branch of the adapter.

  • I compiled adapter’s library (libpreciceAdapterFunctionObject.so, located in $FOAM_USER_LIBBIN).
  • I did my modifications in openfoam-adapter/FSI/ based on the PR.
  • I re-compiled

The wmake.log ALWAYS prompted a successful compilation, however I noticed that the ldd.log was showing unsuccessful linking, because of the lack of volDisplacement* files in the directory. Indeed in the last commit of the PR, these files disappeared so the lib was never updated. I have not investigated this issue but now I have to address the compilation of the PR, which does not work presently.

I understand that one would have to read most of the messages at once to perhaps understand what’s at stake there :grin:. A coarse summary of my progress is that I have been working on the penultimate commit of the PR, which I am now trying to compile.

Note: I don’t want to keep quoting the PR’s URL and its author to avoid cluttering their notifications, as well as the git bot. Am I doing good ?

I am aware my posts can be very long. They are deliberately so, because I aim to be exhaustive in case somebody is trying to reproduce the same thing. Meanwhile, you can also keep track of parts of the files I’m working with on my github page.

Finally, to summarize:
What is my problem:

  • Performing a 2-way pure OpenFOAM FSI coupling

What did I do:

  • A one-way coupling: The solid is solved independently and send displacements at the interface to the fluid, which adapts correctly.

What I still have to do:

  • Correctly implement preciceAdapter::FSI::Force::read (possibly also preciceAdapter::FSI::Stress::read) and preciceAdapter::FSI::Displacement::write (possibly also preciceAdapter::FSI::DisplacementDelta::write)
  • Make the solid solver correctly read the passed Forces
  • Review the configuration of preCICE to activate exchange of Forces

and I’ll be in business ! I’ll let you know on this thread when I have progress.

Meanwhile: :christmas_tree:
Je vous souhaite un joyeux Noël et une bonne année.
I wish you a happy Christmas and a happy New Year.
Wünsche ich Ihnen fröhliche Weihnachten und einen guten Rutsch ins neue Jahr.

Hey @dashqua,

maybe check out my openfoam-adapter fork: https://github.com/JSeuffert/openfoam-adapter/tree/master/FSI.
I also tried to implement a OF-OF coupling and played around a little bit with the adapter so far ( read forces, write dispalcements etc.).

To make the solid solver read the forces, I adjusted the tractionDisplacement boundary to read the force field created by the adapter.

Maybe we can talk about this during the preCICE-workshop?

Cheers, Julian