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)
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 *
104 LinSys[1] = ((
EigenModes[0]).leftCols(numberOfModes)).transpose() * be;
107 if (projType ==
"PG")
109 LinSys[0] = (Ae * ((
EigenModes[0]).leftCols(numberOfModes))).transpose() * Ae *
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;
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());
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);
322 for (label i = 0; i < Coeff.size(); i++)
324 inputField =
reconstruct(inputField, Coeff[i], Name);
325 inputFields.append(inputField.clone());
332template<
class Type,
template<
class>
class PatchField,
class GeoMesh >
334 PtrList<GeometricField<Type, PatchField, GeoMesh >> snapshots,
335 PtrList<GeometricField<Type, PatchField, GeoMesh >>& projSnapshots,
336 PtrList<volScalarField> Volumes,
345 M_Assert(snapshots.size() == Volumes.size(),
346 "The number of snapshots and the number of volumes vectors must be equal");
347 M_Assert(numberOfModes <= this->size(),
348 "The number of Modes used for the projection cannot be bigger than the number of available modes");
349 M_Assert(innerProduct ==
"L2" || innerProduct ==
"Frobenius",
350 "The chosen inner product is not implemented");
351 projSnapshots.resize(snapshots.size());
352 label dim = std::nearbyint(
EigenModes[0].rows() /
354 Eigen::MatrixXd totVolumes(Volumes[0].size() * dim, Volumes.size());
356 for (label i = 0; i < Volumes.size(); i++)
361 totVolumes.replicate(dim, 1);
362 Eigen::MatrixXd
Modes;
364 if (numberOfModes == 0)
374 Eigen::MatrixXd projSnapI;
375 Eigen::MatrixXd projSnapCoeff;
377 for (label i = 0; i < snapshots.size(); i++)
379 GeometricField<Type, PatchField, GeoMesh> Fr = snapshots[0];
382 if (innerProduct ==
"L2")
384 M =
Modes.transpose() * (totVolumes.col(i)).asDiagonal() *
Modes;
385 projSnapI =
Modes.transpose() * (totVolumes.col(i)).asDiagonal() * F_eigen;
390 projSnapI =
Modes.transpose() * F_eigen;
393 projSnapCoeff = M.fullPivLu().solve(projSnapI);
395 projSnapshots.set(i, Fr.clone());
399template<
class Type,
template<
class>
class PatchField,
class GeoMesh>
401 PtrList<GeometricField<Type, PatchField, GeoMesh >> snapshots,
402 PtrList<GeometricField<Type, PatchField, GeoMesh >>& projSnapshots,
403 PtrList<volScalarField> Volumes, word innerProduct)
405 label numberOfModes = 0;
410template<
class Type,
template<
class>
class PatchField,
class GeoMesh>
412 PtrList<GeometricField<Type, PatchField, GeoMesh >> snapshots,
413 PtrList<GeometricField<Type, PatchField, GeoMesh >>& projSnapshots,
422 M_Assert(numberOfModes <= this->size(),
423 "The number of Modes used for the projection cannot be bigger than the number of available modes");
424 M_Assert(innerProduct ==
"L2" || innerProduct ==
"Frobenius",
425 "The chosen inner product is not implemented");
426 projSnapshots.resize(snapshots.size());
427 Eigen::MatrixXd
Modes;
429 if (numberOfModes == 0)
438 Eigen::MatrixXd M_vol;
440 Eigen::MatrixXd projSnapI;
441 Eigen::MatrixXd projSnapCoeff;
443 for (label i = 0; i < snapshots.size(); i++)
445 GeometricField<Type, PatchField, GeoMesh> Fr = snapshots[0];
448 if (innerProduct ==
"L2")
452 else if (innerProduct ==
"Frobenius")
454 M_vol = Eigen::VectorXd::Identity(F_eigen.rows(), 1);
458 Foam::Info <<
"Inner product not defined" << Foam::endl;
462 M =
Modes.transpose() * M_vol.asDiagonal() *
Modes;
463 projSnapI =
Modes.transpose() * M_vol.asDiagonal() * F_eigen;
464 projSnapCoeff = M.fullPivLu().solve(projSnapI);
466 projSnapshots.set(i, Fr.clone());
470template<
class Type,
template<
class>
class PatchField,
class GeoMesh>
472 PtrList<GeometricField<Type, PatchField, GeoMesh >> snapshots,
473 PtrList<GeometricField<Type, PatchField, GeoMesh >>& projSnapshots,
476 label numberOfModes = 0;
480template<
class Type,
template<
class>
class PatchField,
class GeoMesh>
481void Modes<Type, PatchField, GeoMesh>::operator=(
const
482 PtrList<GeometricField<Type, PatchField, GeoMesh >>& modes)
484 this->resize(modes.size());
486 for (label i = 0; i < modes.size(); i++)
488 (* this).set(i, modes[i].clone());
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::MatrixXd field2Eigen(GeometricField< Type, 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< Type, PatchField, GeoMesh > reconstruct(GeometricField< Type, PatchField, GeoMesh > &inputField, Eigen::MatrixXd Coeff, word Name)
Function to reconstruct the solution starting from the coefficients, in this case the field is passed...
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.
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.