37template<
class Type,
template<
class>
class PatchField,
class GeoMesh>
42 for (label
i = 0;
i < (this->first()).boundaryFieldRef().size();
i++)
44 if ((this->first()).boundaryFieldRef()[
i].type() !=
"processor")
54 for (label
i = 0;
i <
NBC;
i++)
62template<
class Type,
template<
class>
class PatchField,
class GeoMesh>
64 fvMatrix<Type>& Af, label numberOfModes,
67 M_Assert(projType ==
"G" || projType ==
"PG",
68 "Projection type can be G for Galerkin or PG for Petrov-Galerkin");
69 List<Eigen::MatrixXd> LinSys;
77 Eigen::SparseMatrix<double> Ae;
81 if (numberOfModes == 0)
91 LinSys[0] = (Ae * EigenModes[0]).transpose() * Ae * EigenModes[0];
92 LinSys[1] = (Ae * EigenModes[0]).transpose() * be;
97 M_Assert(numberOfModes <= EigenModes[0].cols(),
98 "Number of required modes for projection is higher then the number of available ones");
102 LinSys[0] = ((EigenModes[0]).leftCols(numberOfModes)).transpose() * Ae *
103 (EigenModes[0]).leftCols(numberOfModes);
104 LinSys[1] = ((EigenModes[0]).leftCols(numberOfModes)).transpose() * be;
107 if (projType ==
"PG")
109 LinSys[0] = (Ae * ((EigenModes[0]).leftCols(numberOfModes))).transpose() * Ae *
110 (EigenModes[0]).leftCols(numberOfModes);
111 LinSys[1] = (Ae * ((EigenModes[0]).leftCols(numberOfModes))).transpose() * be;
118template<
class Type,
template<
class>
class PatchField,
class GeoMesh>
120 GeometricField<Type, PatchField, GeoMesh>&
121 field, label numberOfModes, word projType, fvMatrix<Type>* Af)
123 M_Assert(projType ==
"F" || projType ==
"G" || projType ==
"PG",
124 "Projection type can be F for Frobenius, G for Galerkin or PG for Petrov-Galerkin");
127 Eigen::MatrixXd projField;
136 if (numberOfModes == 0)
140 vol = Eigen::VectorXd::Ones(vol.size());
141 b = EigenModes[0].transpose() * vol.asDiagonal() * fieldEig;
142 M = EigenModes[0].transpose() * EigenModes[0].transpose();
143 projField = M.fullPivLu().solve(b);
145 else if (projType ==
"G")
147 projField = EigenModes[0].transpose() * vol.asDiagonal() * fieldEig;
149 else if (projType ==
"PG")
152 "Using a Petrov-Galerkin projection you have to provide also the system matrix");
153 Eigen::SparseMatrix<double> Ae;
156 projField = (Ae *
EigenModes[0]).transpose() * vol.asDiagonal() * fieldEig;
161 M_Assert(numberOfModes <= EigenModes[0].cols(),
162 "Number of required modes for projection is higher then the number of available ones");
166 vol = Eigen::VectorXd::Ones(vol.size());
167 M = EigenModes[0].leftCols(numberOfModes).transpose() * EigenModes[0].leftCols(
169 b = ((
EigenModes[0]).leftCols(numberOfModes)).transpose() *
170 vol.asDiagonal() * fieldEig;
171 projField = M.fullPivLu().solve(b);
173 else if (projType ==
"G")
175 projField = ((EigenModes[0]).leftCols(numberOfModes)).transpose() *
176 vol.asDiagonal() * fieldEig;
178 else if (projType ==
"PG")
181 "Using a Petrov-Galerkin projection you have to provide also the system matrix");
182 Eigen::SparseMatrix<double> Ae;
185 projField = (Ae * ((
EigenModes[0]).leftCols(numberOfModes))).transpose() *
186 vol.asDiagonal() * fieldEig;
193template<
class Type,
template<
class>
class PatchField,
class GeoMesh>
194GeometricField<Type, PatchField, GeoMesh>
196 GeometricField<Type, PatchField, GeoMesh>&
197 field, label numberOfModes, word projType, fvMatrix<Type>* Af)
199 Eigen::MatrixXd proj =
project(field, numberOfModes, projType, Af);
200 GeometricField<Type, PatchField, GeoMesh> projSnap = field;
205template<
class Type,
template<
class>
class PatchField,
class GeoMesh>
207 PtrList<GeometricField<Type, PatchField, GeoMesh >> &
209 label numberOfModes, word projType, fvMatrix<Type>* Af)
211 M_Assert(projType ==
"G" || projType ==
"PG",
212 "Projection type can be G for Galerking or PG for Petrov-Galerkin");
215 Eigen::MatrixXd projField;
222 if (numberOfModes == 0)
226 vol = Eigen::VectorXd::Ones(vol.size());
227 projField =
EigenModes[0].transpose() * vol.asDiagonal() * fieldEig;
229 else if (projType ==
"G")
231 projField =
EigenModes[0].transpose() * vol.asDiagonal() * fieldEig;
233 else if (projType ==
"PG")
236 "Using a Petrov-Galerkin projection you have to provide also the system matrix");
237 Eigen::SparseMatrix<double> Ae;
240 projField = (Ae *
EigenModes[0]).transpose() * vol.asDiagonal() * fieldEig;
245 M_Assert(numberOfModes <= EigenModes[0].cols(),
246 "Number of required modes for projection is higher then the number of available ones");
250 vol = Eigen::VectorXd::Ones(vol.size());
251 projField = ((
EigenModes[0]).leftCols(numberOfModes)).transpose() *
252 vol.asDiagonal() * fieldEig;
254 else if (projType ==
"G")
256 projField = ((EigenModes[0]).leftCols(numberOfModes)).transpose() *
257 vol.asDiagonal() * fieldEig;
259 else if (projType ==
"PG")
262 "Using a Petrov-Galerkin projection you have to provide also the system matrix");
263 Eigen::SparseMatrix<double> Ae;
266 projField = (Ae * ((EigenModes[0]).leftCols(numberOfModes))).transpose() *
267 vol.asDiagonal() * fieldEig;
274template<
class Type,
template<
class>
class PatchField,
class GeoMesh>
275GeometricField<Type, PatchField, GeoMesh>
277 GeometricField<Type, PatchField, GeoMesh>& inputField,
278 Eigen::MatrixXd Coeff,
286 label Nmodes = Coeff.rows();
287 Eigen::VectorXd InField =
EigenModes[0].leftCols(Nmodes) * Coeff;
289 if (inputField.name() ==
"nut")
291 InField = (InField.array() < 0).select(0, InField);
295 inputField.rename(Name);
297 for (label
i = 0;
i <
NBC;
i++)
299 Eigen::VectorXd BF =
EigenModes[
i + 1].leftCols(Nmodes) * Coeff;
301 if (inputField.name() ==
"nut")
303 BF = (BF.array() < 0).select(0, BF);
312template<
class Type,
template<
class>
class PatchField,
class GeoMesh>
313PtrList<GeometricField<Type, PatchField, GeoMesh >>
315 GeometricField<Type, PatchField, GeoMesh>& inputField,
316 List < Eigen::MatrixXd> Coeff,
319 PtrList<GeometricField<Type, PatchField, GeoMesh >> inputFields;
320 inputFields.resize(0);
321 for (label
i = 0;
i < Coeff.size();
i++)
324 inputFields.append(inputField.clone());
331template<
class Type,
template<
class>
class PatchField,
class GeoMesh >
333 PtrList<GeometricField<Type, PatchField, GeoMesh >> snapshots,
334 PtrList<GeometricField<Type, PatchField, GeoMesh >>& projSnapshots,
335 PtrList<volScalarField> Volumes,
344 M_Assert(snapshots.size() == Volumes.size(),
345 "The number of snapshots and the number of volumes vectors must be equal");
346 M_Assert(numberOfModes <= this->size(),
347 "The number of Modes used for the projection cannot be bigger than the number of available modes");
348 M_Assert(innerProduct ==
"L2" || innerProduct ==
"Frobenius",
349 "The chosen inner product is not implemented");
350 projSnapshots.resize(snapshots.size());
351 label dim = std::nearbyint(
EigenModes[0].rows() /
353 Eigen::MatrixXd totVolumes(Volumes[0].size() * dim, Volumes.size());
355 for (label
i = 0;
i < Volumes.size();
i++)
360 totVolumes.replicate(dim, 1);
361 Eigen::MatrixXd
Modes;
363 if (numberOfModes == 0)
373 Eigen::MatrixXd projSnapI;
374 Eigen::MatrixXd projSnapCoeff;
376 for (label
i = 0;
i < snapshots.size();
i++)
378 GeometricField<Type, PatchField, GeoMesh> Fr = snapshots[0];
381 if (innerProduct ==
"L2")
383 M =
Modes.transpose() * (totVolumes.col(
i)).asDiagonal() *
Modes;
384 projSnapI =
Modes.transpose() * (totVolumes.col(
i)).asDiagonal() * F_eigen;
389 projSnapI =
Modes.transpose() * F_eigen;
392 projSnapCoeff = M.fullPivLu().solve(projSnapI);
394 projSnapshots.set(
i, Fr.clone());
398template<
class Type,
template<
class>
class PatchField,
class GeoMesh>
400 PtrList<GeometricField<Type, PatchField, GeoMesh >> snapshots,
401 PtrList<GeometricField<Type, PatchField, GeoMesh >>& projSnapshots,
402 PtrList<volScalarField> Volumes, word innerProduct)
404 label numberOfModes = 0;
409template<
class Type,
template<
class>
class PatchField,
class GeoMesh>
411 PtrList<GeometricField<Type, PatchField, GeoMesh >> snapshots,
412 PtrList<GeometricField<Type, PatchField, GeoMesh >>& projSnapshots,
421 M_Assert(numberOfModes <= this->size(),
422 "The number of Modes used for the projection cannot be bigger than the number of available modes");
423 M_Assert(innerProduct ==
"L2" || innerProduct ==
"Frobenius",
424 "The chosen inner product is not implemented");
425 projSnapshots.resize(snapshots.size());
426 Eigen::MatrixXd
Modes;
428 if (numberOfModes == 0)
437 Eigen::MatrixXd M_vol;
439 Eigen::MatrixXd projSnapI;
440 Eigen::MatrixXd projSnapCoeff;
442 for (label
i = 0;
i < snapshots.size();
i++)
444 GeometricField<Type, PatchField, GeoMesh> Fr = snapshots[0];
447 if (innerProduct ==
"L2")
451 else if (innerProduct ==
"Frobenius")
453 M_vol = Eigen::VectorXd::Identity(F_eigen.rows(), 1);
457 std::cout <<
"Inner product not defined" << endl;
461 M =
Modes.transpose() * M_vol.asDiagonal() *
Modes;
462 projSnapI =
Modes.transpose() * M_vol.asDiagonal() * F_eigen;
463 projSnapCoeff = M.fullPivLu().solve(projSnapI);
465 projSnapshots.set(
i, Fr.clone());
469template<
class Type,
template<
class>
class PatchField,
class GeoMesh>
471 PtrList<GeometricField<Type, PatchField, GeoMesh >> snapshots,
472 PtrList<GeometricField<Type, PatchField, GeoMesh >>& projSnapshots,
475 label numberOfModes = 0;
479template<
class Type,
template<
class>
class PatchField,
class GeoMesh>
481 PtrList<GeometricField<Type, PatchField, GeoMesh >> & modes)
483 this->
resize(modes.size());
484 for (label
i = 0;
i < modes.size();
i++)
486 (* this).set(
i, modes[
i].clone());
#define M_Assert(Expr, Msg)
Header file of the Modes class.
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::VectorXd field2Eigen(GeometricField< tensor, PatchField, GeoMesh > &field)
Convert a vector OpenFOAM field into an Eigen Vector.
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)
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.
Implementation of a container class derived from PtrList.
GeometricField< scalar, fvPatchField, volMesh > reconstruct(GeometricField< scalar, fvPatchField, volMesh > &inputField, Eigen::MatrixXd Coeff, word Name)
List< Eigen::MatrixXd > EigenModes
List of Matrices that contains the internalField and the additional matrices for the boundary patches...
List< Eigen::MatrixXd > toEigen()
Method that convert a PtrList of modes into Eigen matrices filling the EigenModes object.
label NBC
Number of patches.
List< Eigen::MatrixXd > project(fvMatrix< Type > &Af, label numberOfModes=0, word projType="G")
A function that project an FvMatrix (OpenFoam linear System) on the modes.
void projectSnapshots(PtrList< GeometricField< Type, PatchField, GeoMesh > > snapshots, PtrList< GeometricField< Type, PatchField, GeoMesh > > &projSnapshots, label numberOfModes=0, word innerProduct="L2")
Function to project a list of fields into the modes manifold.
PtrList< GeometricField< Type, PatchField, GeoMesh > > & toPtrList()
Function that returns the Modes object as a standard PtrList.
GeometricField< Type, PatchField, GeoMesh > projectSnapshot(GeometricField< Type, PatchField, GeoMesh > &field, label numberOfModes=0, word projType="G", fvMatrix< Type > *Af=NULL)
A function that project and reconstruct a snapshot on the modes.
void operator=(const PtrList< GeometricField< Type, PatchField, GeoMesh > > &modes)
Eigen::VectorXd getMassMatrixFV(GeometricField< Type, PatchField, GeoMesh > &snapshot)
Gets a vector containing the volumes of each cell of the mesh.
void assignBC(GeometricField< scalar, fvPatchField, volMesh > &s, label BC_ind, double value)
Assign uniform Boundary Condition to a volScalarField.