In this tutorial we implement a test where we use the Discrete Empirical Interpolation Method for a case where we have a non-linear dependency with respect to the input parameters.
The following image illustrates the computational domain which is the same as the previous example
The physical problem is given by a heat transfer problem which is described by the Poisson equation:
In this case, even if the problem is linear, due to non-linearity with respect to the input parameter of the conductivity constant it is not possible to have an affine decomposition of the discretized differential operator.
We seek therefore an approximate affine expansion of the differential operator of this type:
#include "fvCFD.H"
#include "IOmanip.H"
#include "fvOptions.H"
#include "simpleControl.H"
#include <chrono>
#include "fvMeshSubset.H"
#include <chrono>
#include <Eigen/SVD>
#include <Eigen/SparseLU>
{
public:
{
volScalarField
yPos =
T.mesh().C().component(vector::Y).ref();
volScalarField
xPos =
T.mesh().C().component(vector::X).ref();
for (
auto i = 0;
i <
nu.size();
i++)
{
nu[
i] = std::exp( - 2 * std::pow(
xPos[
i] - mu(0) - 1,
2) - 2 * std::pow(
yPos[
i] - mu(1) - 0.5, 2)) + 1;
}
nu.correctBoundaryConditions();
fvScalarMatrix TiEqn22
(
fvm::laplacian(
nu,
T,
"Gauss linear")
);
return TiEqn22;
}
{
Eigen::SparseMatrix<double> Mr;
Eigen::VectorXd br;
{
theta(
i) = Mr.coeffRef(ind_row, ind_col);
}
}
{
Eigen::SparseMatrix<double> Mr;
Eigen::VectorXd br;
{
}
}
autoPtr<volScalarField>
fieldA;
autoPtr<volScalarField>
fieldB;
};
{
public:
:
{
(
IOobject
(
"ITHACAdict",
"./system",
IOobject::MUST_READ,
IOobject::NO_WRITE
)
);
}
PtrList<fvScalarMatrix>
Mlist;
{
{
}
else
{
for (
int i = 0;
i < par.rows();
i++)
{
Teqn.solve();
Mlist.append((Teqn).clone());
}
}
};
{
auto t1 = std::chrono::high_resolution_clock::now();
auto t2 = std::chrono::high_resolution_clock::now();
auto time_span = std::chrono::duration_cast<std::chrono::duration<double>>
(t2 - t1);
for (
int i = 0;
i < par.rows();
i++)
{
t1 = std::chrono::high_resolution_clock::now();
Teqn.solve();
t2 = std::chrono::high_resolution_clock::now();
time_span = std::chrono::duration_cast<std::chrono::duration<double>>(t2 - t1);
}
};
{
}
{
fvMesh&
mesh =
const_cast<fvMesh&
>(
T.mesh());
{
}
{
}
};
{
auto t1 = std::chrono::high_resolution_clock::now();
auto t2 = std::chrono::high_resolution_clock::now();
auto time_span = std::chrono::duration_cast<std::chrono::duration<double>>
(t2 - t1);
for (
int i = 0;
i < par_new.rows();
i++)
{
t1 = std::chrono::high_resolution_clock::now();
Eigen::VectorXd x =
A.fullPivLu().solve(B);
t2 = std::chrono::high_resolution_clock::now();
time_span = std::chrono::duration_cast<std::chrono::duration<double>>(t2 - t1);
volScalarField Tred(
"Tred",
T);
}
}
};
int main(
int argc,
char* argv[])
{
example._runTime());
example.OfflineSolve(example.mu, "Offline");
example.podex, 0, 0, 20);
example.PODDEIM();
example.OnlineSolve(par_new1, "Online_red");
example_new.OnlineSolveFull(par_new1, "Online_full");
std::cout << std::endl << "The FOM Solve took: " << example_new.time_full <<
" seconds." << std::endl;
std::cout << std::endl << "The ROM Solve took: " << example.time_rom <<
" seconds." << std::endl;
std::cout << std::endl << "The Speed-up is: " << example_new.time_full /
example.time_rom << std::endl << std::endl;
example.Tonline);
std::cout << "The mean L2 error is: " << error.mean() << std::endl;
exit(0);
}
Header file of the EigenFunctions class.
Header file of the Foam2Eigen class.
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 ITHACAutilities namespace.
PtrList< fvScalarMatrix > Mlist
std::vector< Eigen::MatrixXd > ReducedMatricesA
std::vector< Eigen::MatrixXd > ReducedVectorsB
DEIMLaplacian(int argc, char *argv[])
DEIM_function * DEIMmatrice
void OnlineSolve(Eigen::MatrixXd par_new, word Folder)
void OnlineSolveFull(Eigen::MatrixXd par, word Folder)
Eigen::MatrixXd ModesTEig
void OfflineSolve(Eigen::MatrixXd par, word Folder)
Eigen::MatrixXd onlineCoeffsA(Eigen::MatrixXd mu)
PtrList< volScalarField > fieldsB
static volScalarField evaluate_expression(volScalarField &S, Eigen::MatrixXd mu)
Eigen::MatrixXd onlineCoeffsB(Eigen::MatrixXd mu)
autoPtr< volScalarField > fieldB
autoPtr< volScalarField > fieldA
PtrList< volScalarField > fieldsA
autoPtr< IOList< label > > magicPointsAcol
List< label > localMagicPointsAcol
S generateSubmeshMatrix(label layers, const fvMesh &mesh, S field, label secondTime=0)
Function to generate the submesh for the nonlinear matrix function case (RHS)
Eigen::MatrixXd MatrixOnlineB
Online Matrices.
List< label > localMagicPointsB
S generateSubmeshVector(label layers, const fvMesh &mesh, S field, label secondTime=0)
Function to generate the submesh for the nonlinear matrix function case (LHS)
autoPtr< IOList< label > > xyz_Acol
DEIM(PtrList< T > &SnapShotsMatrix, label MaxModes, word FunctionName, word FieldName)
Construct DEIM for non-linear function.
List< label > localMagicPointsArow
autoPtr< IOList< label > > xyz_Arow
List< Eigen::SparseMatrix< double > > MatrixOnlineA
Online Matrices.
autoPtr< IOList< label > > xyz_B
autoPtr< IOList< label > > magicPointsB
static GeometricField< scalar, PatchField, GeoMesh > Eigen2field(GeometricField< scalar, PatchField, GeoMesh > &field, Eigen::VectorXd &eigen_vector, bool correctBC=true)
Convert a vector in Eigen format into an OpenFOAM scalar GeometricField.
static Eigen::MatrixXd PtrList2Eigen(PtrList< GeometricField< Type, PatchField, GeoMesh > > &fields, label Nfields=-1)
Convert a PtrList of snapshots to Eigen matrix (only internal field)
static void fvMatrix2Eigen(fvMatrix< type_foam_matrix > foam_matrix, type_A &A, type_B &b)
Convert a FvMatrix OpenFOAM matrix (Linear System) into a Eigen Matrix A and a source vector b.
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.
Class to implement a full order laplacian parametrized problem.
PtrList< volScalarField > Tonline
List of snapshots for the solution.
autoPtr< volScalarField > _T
Temperature field.
autoPtr< volScalarField > _nu
Diffusivity.
autoPtr< fvMesh > _mesh
Mesh.
volScalarModes Tmodes
List of POD modes.
autoPtr< volScalarField > _S
Source Term.
PtrList< volScalarField > Tfield
List of snapshots for the solution.
bool offline
Boolean variable, it is 1 if the Offline phase has already been computed, else 0.
IOdictionary * ITHACAdict
dictionary to store input output infos
Header file of the laplacianProblem class.
Eigen::SparseMatrix< T > MVproduct(List< Eigen::SparseMatrix< T > > &A, Eigen::DenseBase< Eigen::Matrix< T, Eigen::Dynamic, Eigen::Dynamic > > &C)
Sparse Matrix-Vector product between a list of sparse matrices and a vector of coefficients.
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 exportSolution(GeometricField< Type, PatchField, GeoMesh > &s, fileName subfolder, fileName folder, word fieldName)
Export a field to file in a certain folder and subfolder.
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.
Eigen::MatrixXd rand(label rows, label cols, double min, double max)
Generates random matrix with random values in an interval.
double errorL2Abs(GeometricField< vector, fvPatchField, volMesh > &field1, GeometricField< vector, fvPatchField, volMesh > &field2, volScalarField &Volumes)