Introduction
The problem consists of an unsteady Navier-Stokes problem coupled with heat transport in a mixing elbow geometry. The physical setup involves fluid flow with parameterized inlet velocities and temperatures, demonstrating reduced order modeling for non-isothermal flows.
The geometry is a mixing elbow where two inlets with different velocities and temperatures merge, and the outlet conditions are simulated. The tutorial showcases the application of POD-based reduction to both momentum and energy equations.
A detailed look into the code
This section explains the main steps necessary to construct the tutorial N°7.
The necessary header files
First of all let's have a look into the header files which have to be included, indicating what they are responsible for:
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 reducedUnsteadyNST class.
Header file of the reducedUnsteadyNS class.
Header file of the unsteadyNST class.
<unsteadyNST.H> is the base class for unsteady Navier-Stokes with temperature problems. <ITHACAPOD.H> is for the computation of the POD modes. <ReducedUnsteadyNS.H> and <ReducedUnsteadyNST.H> are for the reduced-order unsteady NS and NST problems. <ITHACAstream.H> is responsible for reading and exporting the fields and other sorts of data.
Additional standard libraries:
#include <chrono>
#include <math.h>
#include <iomanip>
Chrono is useful to compute execution times, math.h is used for mathematical functions, and iomanip for output formatting.
Implementation of the tutorial07 class
We define the tutorial07 class as a child of the unsteadyNST class. The constructor is defined with members that are the fields required to be manipulated during the resolution of the full order problem. Such fields are also initialized with the same initial conditions in the solver.
{
public:
:
U(_U()),
p(_p()),
T(_T())
{}
volVectorField& U;
volScalarField& p;
volScalarField& T;
Implementation of a parametrized full order unsteady NS problem weakly coupled with the energy equat...
Inside the tutorial07 class we define the offlineSolve method. If the offline solve has been previously performed, then the method just reads the existing snapshots from the Offline directory. If not, it loops over all the parameter samples and performs the full-order simulations.
void offlineSolve()
{
Vector<double> inl(0, 0, 0);
List<scalar> mu_now(1);
Info << "here" << endl;
if (offline)
{
mu_samples =
}
else
{
for (label i = 0; i < mu.cols(); i++)
{
mu_now[0] = mu(0, i);
truthSolve(mu_now);
}
}
}
List< Eigen::MatrixXd > readMatrix(word folder, word mat_name)
Read a three dimensional matrix from a txt file in Eigen format.
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.
Definition of the main function
The main function sets up the problem parameters, performs the offline phase, computes POD modes, and solves the online reduced problem.
First, the tutorial object is constructed and parameters are read from the ITHACA dictionary:
example._runTime());
int NmodesUout = para->ITHACAdict->lookupOrDefault<int>("NmodesUout", 5);
Class for the definition of some general parameters, the parameters must be defined from the file ITH...
static ITHACAparameters * getInstance()
Gets an instance of ITHACAparameters, to be used if the instance is already existing.
Then, problem-specific settings are configured:
example.Pnumber = 1;
example.Tnumber = 1;
example.setParameters();
example.mu_range(0, 0) = 0.1;
example.mu_range(0, 1) = 0.1;
example.genEquiPar();
example.inletIndex.resize(2, 2);
example.inletIndex << 3, 0, 2, 1;
example.inletIndexT.resize(3, 1);
example.inletIndexT << 3, 2, 0;
example.startTime = 0;
example.finalTime = 50;
example.timeStep = 0.05;
example.writeEvery = 0.1;
The offline solve is performed:
Supremizer and lift functions are then computed. Note that the lift function is assigned for both the velocity and the temperature (liftSolveT and computeLiftT).
example.solvesupremizer();
example.liftSolve();
example.liftSolveT();
example.computeLift(example.Ufield, example.liftfield, example.Uomfield);
example.computeLiftT(example.Tfield, example.liftfieldT, example.Tomfield);
POD modes are extracted:
example.podex, 0, 0, NmodesUout);
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.
The reduced problem is set up and solved online:
reduced.nu = 0.1;
reduced.tstart = 0;
reduced.finalTime = 50;
reduced.dt = 0.05;
reduced.DT = 1e-06;
Eigen::MatrixXd vel_now(2, 1);
vel_now << 0.6, 1.2;
Eigen::MatrixXd temp_now(3, 1);
temp_now << 60, 70, 60;
reduced.solveOnline_sup(vel_now, temp_now);
Class where it is implemented a reduced problem for the unsteady Navier-stokes weakly coupled with t...
The reduced solution is then reconstructed and exported:
reduced.reconstruct_sup("./ITHACAoutput/ReconstructionSUP/", 2);
reduced.reconstruct_supt("./ITHACAoutput/ReconstructionSUP/", 2);
This completes the tutorial, demonstrating the full workflow from full-order snapshots to reduced-order online solution.
The plain code is available here.