36template<
class Type,
template<
class>
class PatchField,
class GeoMesh>
38 PtrList<GeometricField<Type, PatchField, GeoMesh>>& snapshots,
double dt)
40 snapshotsDMD(snapshots),
41 NSnaps(snapshots.size()),
49template<
class Type,
template<
class>
class PatchField,
class GeoMesh>
56 SVD_rank = NSnaps - 1;
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: "
63 SVD_rank_public = SVD_rank;
64 M_Assert(SVD_rank < NSnaps, assertMessage.c_str());
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>>());
122 DMDEigenModes = Ym * V *
S.asDiagonal() * esEg.eigenvectors();
123 DMDEigenModesBC.resize(YmBC.size());
125 for (label
i = 0;
i < YmBC.size();
i++)
127 DMDEigenModesBC[
i] = YmBC[
i] * V *
S.asDiagonal() * esEg.eigenvectors();
132 Eigen::VectorXd eigenValueseigLam =
134 PODm = (Xm * V) * eigenValueseigLam.asDiagonal();
135 PODmBC.resize(XmBC.size());
137 for (label
i = 0;
i < XmBC.size();
i++)
139 PODmBC[
i] = (XmBC[
i] * V) * eigenValueseigLam.asDiagonal();
142 DMDEigenModes = PODm * esEg.eigenvectors();
143 DMDEigenModesBC.resize(PODmBC.size());
145 for (label
i = 0;
i < PODmBC.size();
i++)
147 DMDEigenModesBC[
i] = PODmBC[
i] * esEg.eigenvectors();
151 Amplitudes = DMDEigenModes.real().fullPivLu().solve(Xm.col(0));
156 Info <<
"exporting the DMDmodes for " << snapshotsDMD[0].name() << endl;
158 snapshotsDMD[0].name() +
"_Modes_" + name(SVD_rank) +
"_Real");
160 snapshotsDMD[0].name() +
"_Modes_" + name(SVD_rank) +
"_Imag");
164template<
class Type,
template<
class>
class PatchField,
class GeoMesh>
166 double tFinal,
double dt)
168 Eigen::VectorXcd omega = eigenValues.array().log() / originalDT;
169 label ncols =
static_cast<label
>((tFinal - tStart) / dt ) + 1;
170 dynamics.resize(SVD_rank_public, ncols);
173 for (
double t = tStart; t <= tFinal; t += dt)
175 Eigen::VectorXcd coli = (omega * t).array().exp() * Amplitudes.array();
176 dynamics.col(
i) = coli;
182template<
class Type,
template<
class>
class PatchField,
class GeoMesh>
185 Eigen::MatrixXcd eigs = eigenValues;
187 std::string path = exportFolder +
"/eigs.npy";
193template<
class Type,
template<
class>
class PatchField,
class GeoMesh>
197 PtrList<GeometricField<Type, PatchField, GeoMesh>> snapshotsrec;
199 for (label
i = 0;
i < dynamics.cols();
i++)
201 Eigen::MatrixXcd
col = DMDEigenModes * dynamics.col(
i);
202 Eigen::VectorXd vec =
col.real();
203 GeometricField<Type, PatchField, GeoMesh> tmp2(
"TMP",
204 snapshotsDMD[0] * 0);
207 for (label k = 0; k < tmp2.boundaryField().size(); k++)
209 Eigen::VectorXd vecBC = (DMDEigenModesBC[k] * dynamics.col(
i)).real();
213 snapshotsrec.append(tmp2.clone());
218template<
class Type,
template<
class>
class PatchField,
class GeoMesh>
221 DMDmodesReal.resize(DMDEigenModes.cols());
222 DMDmodesImag.resize(DMDEigenModes.cols());
223 GeometricField<Type, PatchField, GeoMesh> tmp2Real(
224 snapshotsDMD[0].name(), snapshotsDMD[0] * 0);
225 GeometricField<Type, PatchField, GeoMesh> tmp2Imag(
226 snapshotsDMD[0].name(), snapshotsDMD[0] * 0);
228 for (label
i = 0;
i < DMDmodesReal.size();
i++)
230 Eigen::VectorXd vecReal = DMDEigenModes.col(
i).real();
231 Eigen::VectorXd vecImag = DMDEigenModes.col(
i).imag();
236 for (label k = 0; k < tmp2Real.boundaryField().size(); k++)
242 DMDmodesReal.set(
i, tmp2Real.clone());
243 DMDmodesImag.set(
i, tmp2Imag.clone());
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.
void convert2Foam()
Convert the EigenModes in Matrix form into OpenFOAM GeometricFields.
ITHACADMD(PtrList< GeometricField< Type, PatchField, GeoMesh > > &snapshots, double dt)
Constructs the object.
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.
void reconstruct(word exportFolder, word fieldName)
Reconstruct and export the solution using the computed dynamics.
void exportEigs(word exportFolder)
Export the eigenvalues in numpy format.
void getModes(label SVD_rank=-1, bool exact=true, bool exportDMDmodes=false)
Get the DMD modes.
bool redSVD
If true, it uses the Randomized SVD.
Class for the definition of some general parameters, the parameters must be defined from the file ITH...
IOdictionary * ITHACAdict
Dictionary for input objects from file.
static ITHACAparameters * getInstance()
Gets an instance of ITHACAparameters, to be used if the instance is already 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))