36template<
class Type,
template<
class>
class PatchField,
class GeoMesh>
38 PtrList<GeometricField<Type, PatchField, GeoMesh >> & snapshots,
double dt)
45 redSVD =
para->ITHACAdict->lookupOrDefault<
bool>(
"redSVD",
false);
49template<
class Type,
template<
class>
class PatchField,
class GeoMesh>
59 std::string assertMessage =
"The SVD_rank is equal to: " + name(
61 ", it cannot be bigger than the number of snapshots - 1. NSnapshots is equal to: "
68 Eigen::MatrixXd Xm = SnapEigen.leftCols(
NSnaps - 1);
69 Eigen::MatrixXd Ym = SnapEigen.rightCols(
NSnaps - 1);
70 List<Eigen::MatrixXd> XmBC(SnapEigenBC.size());
71 List<Eigen::MatrixXd> YmBC(SnapEigenBC.size());
73 for (label
i = 0 ;
i < SnapEigenBC.size() ;
i++)
75 XmBC[
i] = SnapEigenBC[
i].leftCols(
NSnaps - 1);
76 YmBC[
i] = SnapEigenBC[
i].rightCols(
NSnaps - 1);
85 Info <<
"SVD using Randomized method" << endl;
86 RedSVD::RedSVD<Eigen::MatrixXd>
svd(Xm, SVD_rank);
89 S =
svd.singularValues().array().cwiseInverse();
93 Info <<
"SVD using JacobiSVD" << endl;
94 Eigen::JacobiSVD<Eigen::MatrixXd>
svd(Xm,
95 Eigen::ComputeThinU | Eigen::ComputeThinV);
96 U =
svd.matrixU().leftCols(SVD_rank);
97 V =
svd.matrixV().leftCols(SVD_rank);
98 S =
svd.singularValues().head(SVD_rank).array().cwiseInverse();
101 Eigen::MatrixXcd A_tilde =
U.transpose().conjugate() * Ym *
104 Eigen::ComplexEigenSolver<Eigen::MatrixXcd> esEg(A_tilde);
105 eigenValues = esEg.eigenvalues();
106 Eigen::VectorXd ln = eigenValues.array().log().imag().abs();
108 typedef std::pair<double, label> mypair;
109 std::vector<mypair> sortedList(ln.size());
111 for (label
i = 0;
i < ln.size();
i++)
113 sortedList[
i].first = ln(
i);
114 sortedList[
i].second =
i;
117 std::sort(sortedList.begin(), sortedList.end(),
118 std::less<std::pair<double, label >> ());
121 DMDEigenModes = Ym* V*
S.asDiagonal() * esEg.eigenvectors();
122 DMDEigenModesBC.resize(YmBC.size());
123 for (label
i = 0;
i < YmBC.size();
i++)
125 DMDEigenModesBC[
i] = YmBC[
i] * V*
S.asDiagonal() * esEg.eigenvectors();
131 Eigen::VectorXd eigenValueseigLam =
133 PODm = (Xm* V) * eigenValueseigLam.asDiagonal();
134 PODmBC.resize(XmBC.size());
136 for (label
i = 0;
i < XmBC.size();
i++)
138 PODmBC[
i] = (XmBC[
i] * V) * eigenValueseigLam.asDiagonal();
141 DMDEigenModes = PODm* esEg.eigenvectors();
142 DMDEigenModesBC.resize(PODmBC.size());
149 Amplitudes = DMDEigenModes.real().fullPivLu().solve(Xm.col(0));
153 Info <<
"exporting the DMDmodes for " <<
snapshotsDMD[0].name() << endl;
155 snapshotsDMD[0].name() +
"_Modes_" + name(SVD_rank) +
"_Real");
157 snapshotsDMD[0].name() +
"_Modes_" + name(SVD_rank) +
"_Imag");
161template<
class Type,
template<
class>
class PatchField,
class GeoMesh >
163 double tFinal,
double dt)
166 label ncols =
static_cast<label
>((tFinal - tStart) / dt ) + 1;
170 for (
double t = tStart; t <= tFinal; t += dt)
172 Eigen::VectorXcd coli = (omega * t).array().exp() *
Amplitudes.array();
179template<
class Type,
template<
class>
class PatchField,
class GeoMesh>
184 std::string path = exportFolder +
"/eigs.npy";
190template<
class Type,
template<
class>
class PatchField,
class GeoMesh>
194 PtrList<GeometricField<Type, PatchField, GeoMesh >> snapshotsrec;
198 Eigen::VectorXd vec =
col.real();
199 GeometricField<Type, PatchField, GeoMesh> tmp2(
"TMP",
203 for (label k = 0; k < tmp2.boundaryField().size(); k++)
209 snapshotsrec.append(tmp2.clone());
215template<
class Type,
template<
class>
class PatchField,
class GeoMesh>
220 GeometricField<Type, PatchField, GeoMesh> tmp2Real(
222 GeometricField<Type, PatchField, GeoMesh> tmp2Imag(
233 for (label k = 0; k < tmp2Real.boundaryField().size(); k++)
Header file of the ITHACADMD class.
#define M_Assert(Expr, Msg)
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 List< Eigen::MatrixXd > PtrList2EigenBC(PtrList< GeometricField< scalar, PatchField, GeoMesh > > &fields, label Nfields=-1)
Convert an OpenFOAM scalar field to a List of Eigen Vectors, one for each boundary.
static Eigen::MatrixXd PtrList2Eigen(PtrList< GeometricField< Type, PatchField, GeoMesh > > &fields, label Nfields=-1)
Convert a PtrList of snapshots to Eigen matrix (only internal field)
Class of the computation of the DMD, it exploits the SVD methods.
PtrList< GeometricField< Type, PatchField, GeoMesh > > snapshotsDMD
PtrList of OpenFOAM GeoometricFields where the snapshots are stored.
void convert2Foam()
Convert the EigenModes in Matrix form into OpenFOAM GeometricFields.
label SVD_rank_public
Rank of the DMD.
ITHACADMD(PtrList< GeometricField< Type, PatchField, GeoMesh > > &snapshots, double dt)
Constructs the object.
Eigen::VectorXd Amplitudes
Amplitudes of DMD.
void getDynamics(double tStart, double tFinal, double dt)
Export the dynamics of DMD given an initial time step, a final one and a time step.
double originalDT
Original time step used to acquire the snapshots.
void reconstruct(word exportFolder, word fieldName)
Reconstruct and export the solution using the computed dynamics.
Eigen::MatrixXcd dynamics
Complex Eigen::Matrix used to store the Dynamics of the DMD modes.
List< Eigen::MatrixXcd > PODmBC
void exportEigs(word exportFolder)
Export the eigenvalues in numpy format.
Modes< scalar, fvPatchField, volMesh > DMDmodesImag
List< Eigen::MatrixXcd > DMDEigenModesBC
label NSnaps
Number of snapshots.
void getModes(label SVD_rank=-1, bool exact=true, bool exportDMDmodes=false)
Get the DMD modes.
Modes< scalar, fvPatchField, volMesh > DMDmodesReal
Eigen::VectorXcd eigenValues
Eigenvalues of the dynamics mode decomposition.
bool redSVD
If true, it uses the Randomized SVD.
Eigen::MatrixXcd DMDEigenModes
DMD modes stored in a complex Eigen::Matrix, it is the object used for computations.
Class for the definition of some general parameters, the parameters must be defined from the file ITH...
static ITHACAparameters * getInstance(fvMesh &mesh, Time &localTime)
Gets an instance of ITHACAparameters, to be used if the instance is not existing.
void exportFields(PtrList< GeometricField< Type, PatchField, GeoMesh > > &field, word folder, word fieldname)
Function to export a scalar of vector field.
void assignBC(GeometricField< scalar, fvPatchField, volMesh > &s, label BC_ind, double value)
Assign uniform Boundary Condition to a volScalarField.
void save(const Eigen::Matrix< T, -1, dim > &mat, const std::string fname)
Info<< endl;Info<< "*********************************************************"<< endl;Info<< "Performing test for the parameterized BC inverse solver"<< endl;Info<< endl;word outputFolder="./ITHACAoutput/parameterizedBCtest_RBFparameter/";volScalarField gTrueField=example_paramBC.list2Field(example_paramBC.gTrue);ITHACAstream::exportSolution(gTrueField, "1", outputFolder, "gTrue");Eigen::VectorXd rbfWidth=EigenFunctions::ExpSpaced(0.001, 100, rbfWidthTest_size);ITHACAstream::exportMatrix(rbfWidth, "rbfShapeParameters", "eigen", outputFolder);Eigen::VectorXd residualNorms;residualNorms.resize(rbfWidthTest_size);Eigen::VectorXd heatFluxL2norm(rbfWidthTest_size);Eigen::VectorXd heatFluxLinfNorm=heatFluxL2norm;Eigen::VectorXd condNumber=heatFluxL2norm;Eigen::MatrixXd singVal;for(int i=0;i< rbfWidthTest_size;i++){ Info<< "*********************************************************"<< endl;Info<< "RBF parameter "<< rbfWidth(i)<< endl;Info<< "Test "<< i+1<< endl;Info<< endl;example_paramBC.set_gParametrized("rbf", rbfWidth(i));example_paramBC.parameterizedBCoffline(1);example_paramBC.parameterizedBC("fullPivLU");volScalarField gParametrizedField=example_paramBC.list2Field(example_paramBC.g);ITHACAstream::exportSolution(gParametrizedField, std::to_string(i+1), outputFolder, "gParametrized");volScalarField &T(example_paramBC._T());ITHACAstream::exportSolution(T, std::to_string(i+1), outputFolder, "T");residualNorms(i)=Foam::sqrt(example_paramBC.residual.squaredNorm());Eigen::MatrixXd A=example_paramBC.Theta.transpose() *example_paramBC.Theta;Eigen::JacobiSVD< Eigen::MatrixXd > svd(A, Eigen::ComputeThinU|Eigen::ComputeThinV)
volScalarField S(IOobject("S", runTime.timeName(), mesh, IOobject::NO_READ, IOobject::AUTO_WRITE), T.mesh(), dimensionedScalar("zero", dimensionSet(0, 0, -1, 1, 0, 0, 0), 0))