Introduction
This tutorial shows a fluid–structure interaction (FSI) problem where a cylinder moves in a viscous flow. The ITHACA-FV implementation leverages the fsiBasic base class and constructs a reduced order model capturing both the fluid velocity and the solid point displacement.
A detailed look into the code
Let's have a look at the code of tutorial 25.
Header files
Key includes for this tutorial are:
#include "dynamicFvMesh.H"
#include "ReducedFsi.H"
Header file of the ITHACAPOD class.
Header file of the ITHACAstream class, it contains the implementation of several methods for input ou...
Header file of the reducedProblem class.
Header file of the fsiBasic class.
Additional headers support mesh motion, point constraints and math constants.
Implementation of tutorial25 class
The tutorial25 class inherits from fsiBasic and holds references to the velocity U, pressure p and point displacement pd fields.
{
public:
U(_U()),
p(_p()),
pd(_pointDisplacement())
{}
volVectorField& U;
volScalarField& p;
pointVectorField& pd;
Implementation of a parametrized full order unsteady NS problem and preparation of the the reduced ...
The offlineSolve method either loads existing snapshots or iterates over parameter samples, updating a damping parameter and running the coupled solver (updateStiffnessAndRebuildSolver(mu(i, 0)). After each simulation the code exports force and centre-of-mass data for post–processing.
void offlineSolve(word folder = "./ITHACAoutput/Offline/")
{
if (offline )
{
}
else
{
for (label i = 0; i < mu.rows(); i++)
{
word param_name = "damping";
updateStiffnessAndRebuildSolver(mu(i, 0), param_name);
startTime = 0;
finalTime = 30;
timeStep = 0.003;
writeEvery = 1e-01;
truthSolve(i, folder);
word localFolder = folder + "../" + "/DataFromFoam_" + name(i + 1);
prepareFoamData(localFolder);
restart();
fomforcex.clear();
fomforcey.clear();
centerofmassy.clear();
}
}
}
};
void readMiddleFields(PtrList< GeometricField< Type, PatchField, GeoMesh > > &Lfield, GeometricField< Type, PatchField, GeoMesh > &field, fileName casename)
Funtion to read a list of volVectorField from name of the field including all the intermediate snapsh...
The main
The main routine reads offline parameter files (parsOff_mat.txt):
std::ifstream exFileOff("./parsOff_mat.txt");
sets the number of modes for velocity, pressure and displacement:
int NmodesUout = para->ITHACAdict->lookupOrDefault<int>("NmodesUout", 40);
int NmodesPout = para->ITHACAdict->lookupOrDefault<int>("NmodesPout", 40);
int NmodesDout = para->ITHACAdict->lookupOrDefault<int>("NmodesDout", 40);
int NmodesUproj = para->ITHACAdict->lookupOrDefault<int>("NmodesUproj", 15);
int NmodesPproj = para->ITHACAdict->lookupOrDefault<int>("NmodesPproj", 5);
int NmodesDproj = para->ITHACAdict->lookupOrDefault<int>("NmodesDproj", 1);
and optionally performs offline runs:
POD modes are computed unless they already exist:
if (example.podex == 0 )
{
example.podex, 0, 0, NmodesUout);
example.podex, 0, 0, NmodesPout);
example._pointDisplacement().name(),
example.podex, 0, 0, NmodesDout);
}
else
{
"./ITHACAoutput/POD/");
"./ITHACAoutput/POD/");
"./ITHACAoutput/POD/");
}
void getModes(PtrList< GeometricField< Type, PatchField, GeoMesh > > &snapshots, PtrList< GeometricField< Type, PatchField, GeoMesh > > &modes, word fieldName, bool podex, bool supex, bool sup, label nmodes, bool correctBC)
Computes the bases or reads them for a field.
void read_fields(PtrList< GeometricField< Type, PatchField, GeoMesh > > &Lfield, word Name, fileName casename, int first_snap, int n_snap)
Function to read a list of fields from the name of the field and casename.
and additional testing data for online evaluation (parameters sampling, FOM counterpart) are generated using a second instance of the tutorial object.
Eigen::MatrixXd parsOn;
std::ifstream exFileOn("./parsOn_mat.txt");
if (exFileOn)
{
}
word test_folder = "./ITHACAoutput/TestingOff/";
{
testkOff.mu = parsOn;
testkOff.offline = false;
for (label k = 0; k < parsOn.rows(); k++)
{
word param_name = "damping";
testkOff.updateStiffnessAndRebuildSolver(parsOn(k, 0), param_name);
testkOff.startTime = 0;
testkOff.finalTime = 30;
testkOff.timeStep = 0.003;
testkOff.writeEvery = 1e-01;
testkOff.truthSolve(k, test_folder);
word localFolder = test_folder + "/DataFromFoam_" + name(k + 1);
testkOff.prepareFoamData(localFolder);
testkOff.restart();
testkOff.Ufield.clear();
testkOff.Pfield.clear();
testkOff.Dfield.clear();
testkOff.fomforcex.clear();
testkOff.fomforcey.clear();
testkOff.centerofmassy.clear();
}
...
}
List< Eigen::MatrixXd > readMatrix(word folder, word mat_name)
Read a three dimensional matrix from a txt file in Eigen format.
bool check_folder(word folder)
Checks if a folder exists.
Online reduction is performed with the ReducedFsi class
It is solving the reduced PIMPLE system for each test parameter set and exporting coefficients and reconstructions.
if (exFileOn)
{
}
word folder = "./ITHACAoutput/Online/";
for (label i = 0; i < parsOn.rows(); i++)
{
word param_name = "damping";
example.updateStiffnessAndRebuildSolver(parsOn(i, 0), param_name);
reduced.startTime = 0;
reduced.finalTime = 30;
reduced.timeStep = 0.003;
reduced.writeEvery = 1e-1;
reduced.solveOnline_Pimple(NmodesUproj,
NmodesPproj,
NmodesDproj,
folder);
word localFolder = folder + name(i + 1);
for (int k = 0; k < reduced.UredFields.size(); ++k)
{
localFolder);
localFolder);
localFolder);
name(k + 1) + "/polyMesh/");
}
word DataRom = folder + "../" + "/DataFromRom_" + name(i + 1);
reduced.prepareRomData(DataRom);
example.restart();
reduced.UredFields.clear();
reduced.PredFields.clear();
reduced.Dfield.clear();
reduced.romforcey.clear();
reduced.romforcex.clear();
reduced.centerofmassy.clear();
}
void writePoints(pointField points, fileName folder, fileName subfolder)
Write points of a mesh to a file.
void exportSolution(GeometricField< Type, PatchField, GeoMesh > &s, fileName subfolder, fileName folder, word fieldName)
Export a field to file in a certain folder and subfolder.
void createSymLink(word folder)
Creates symbolic links to 0, system and constant.
Error metrics comparing reduced and full-order solutions (energy norms, centre-of-mass displacement, forces) are computed and stored for post-processing:
reduced.UredFields);
reduced.PredFields);
cnpy::save(errL2U, "./ITHACAoutput/DataFromRom/errL2U_" + name(
NmodesUproj) + "_" + name(NmodesPproj) + ".npy");
cnpy::save(errL2P, "./ITHACAoutput/DataFromRom/errL2P_" + name(
NmodesUproj) + "_" + name(NmodesPproj) + ".npy");
double errorL2Rel(GeometricField< T, fvPatchField, volMesh > &field1, GeometricField< T, fvPatchField, volMesh > &field2, List< label > *labels)
Computes the relative error between two geometric Fields in L2 norm.
Usage
Python scripts plotCentreMass.py, plotDrag.py and plotLift.py can be used to visualize the outputs.
This tutorial demonstrates building a coupled fluid-structure reduced model with parameterized structural damping and moving mesh handling.
The plain code
The plain code is available here.