1 /*---------------------------------------------------------------------------*\
3 \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
5 \\ / A nd | Copyright held by original author
7 -------------------------------------------------------------------------------
9 This file is part of OpenFOAM.
11 OpenFOAM is free software; you can redistribute it and/or modify it
12 under the terms of the GNU General Public License as published by the
13 Free Software Foundation; either version 2 of the License, or (at your
14 option) any later version.
16 OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
17 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
18 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
21 You should have received a copy of the GNU General Public License
22 along with OpenFOAM; if not, write to the Free Software Foundation,
23 Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
30 \*---------------------------------------------------------------------------*/
32 #include "scalarTransportPOD.H"
34 #include "addToRunTimeSelectionTable.H"
36 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
40 defineTypeNameAndDebug(scalarTransportPOD, 0);
42 addToRunTimeSelectionTable
51 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
53 void Foam::scalarTransportPOD::calcOrthoBase() const
59 "scalarTransportPOD::calcOrthoBase()"
60 ) << "Orthogonal base already calculated"
64 // Create ortho-normal base
65 scalar accuracy = readScalar(dict().lookup("accuracy"));
68 Time& runTime = const_cast<Time&>(mesh().time());
70 // Remember time index to restore it after the scan
71 label origTimeIndex = runTime.timeIndex();
73 instantList Times = runTime.times();
75 // Create a list of snapshots
76 PtrList<volScalarField> fields(Times.size());
82 if (Times[i].value() < SMALL || Times[i] == runTime.constant())
84 Info << "Skipping time " << Times[i] << endl;
89 runTime.setTime(Times[i], i);
91 Info<< "Time = " << runTime.timeName() << endl;
101 if (phiHeader.headerOk())
103 Info<< " Reading " << phiName_ << endl;
105 fields.set(nSnapshots, new volScalarField(phiHeader, mesh()));
108 fields[nSnapshots].rename(phiName_ + name(i));
113 Info<< " No " << phiName_ << endl;
117 // Reset time index to initial state
118 runTime.setTime(Times[origTimeIndex], origTimeIndex);
125 "scalarTransportPOD::calcOrthoBase()"
126 ) << "Insufficient number of snapshots: " << nSnapshots
127 << abort(FatalError);
130 Info << "Number of snapshots: " << nSnapshots << endl;
132 fields.setSize(nSnapshots);
134 // Create ortho-normal base for transported variable
135 orthoBasePtr_ = new scalarPODOrthoNormalBase(fields, accuracy);
139 void Foam::scalarTransportPOD::calcDerivativeCoeffs() const
141 if (derivativeMatrixPtr_)
145 "void scalarTransportPOD::calcDerivativeCoeffs() const"
146 ) << "Derivative matrix already calculated"
147 << abort(FatalError);
150 // Calculate coefficients for differential equation
152 Time& runTime = const_cast<Time&>(this->mesh().time());
154 // Remember time index to restore it
155 label origTimeIndex = runTime.timeIndex();
159 IOdictionary transportProperties
163 "transportProperties",
171 Info<< "Reading diffusivity D\n" << endl;
175 transportProperties.lookup("DT")
178 // Find velocity field
180 word Uname(this->dict().lookup("velocity"));
182 instantList Times = runTime.times();
184 volVectorField* Uptr = NULL;
188 runTime.setTime(Times[i], i);
190 Info<< "Time = " << runTime.timeName() << endl;
200 if (Uheader.headerOk())
202 Info<< " Reading " << Uname << endl;
204 Uptr = new volVectorField(Uheader, this->mesh());
209 Info<< " No " << Uname << endl;
213 // Reset time index to initial state
214 runTime.setTime(Times[origTimeIndex], origTimeIndex);
220 "void scalarTransportPOD::calcDerivativeCoeffs() const"
221 ) << "Cannot find velocity: " << Uname
222 << abort(FatalError);
225 volVectorField& U = *Uptr;
227 // Create derivative matrix
229 const scalarPODOrthoNormalBase& b = orthoBase();
231 derivativeMatrixPtr_ = new scalarSquareMatrix(b.baseSize(), 0.0);
232 scalarSquareMatrix& derivative = *derivativeMatrixPtr_;
234 for (label i = 0; i < b.baseSize(); i++)
236 const volScalarField& snapI = b.orthoField(i);
238 volVectorField gradSnapI = fvc::grad(snapI);
240 for (label j = 0; j < b.baseSize(); j++)
242 const volScalarField& snapJ = b.orthoField(j);
244 volVectorField gradSnapJ = fvc::grad(snapJ);
247 DT.value()*POD::projection(fvc::div(gradSnapJ), snapI)
248 - POD::projection((U & gradSnapJ), snapI);
253 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
255 // Construct from components
256 Foam::scalarTransportPOD::scalarTransportPOD
259 const dictionary& dict
263 phiName_(dict.lookup("field")),
265 derivativeMatrixPtr_(NULL),
269 // Grab coefficients from the first snapshot of the ortho-normal base
270 coeffs_.setSize(orthoBase().baseSize());
272 const scalarRectangularMatrix& orthoBaseCoeffs =
273 orthoBase().interpolationCoeffs();
277 coeffs_[i] = orthoBaseCoeffs[0][i];
282 // * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
284 Foam::scalarTransportPOD::~scalarTransportPOD()
286 deleteDemandDrivenData(derivativeMatrixPtr_);
293 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
295 Foam::label Foam::scalarTransportPOD::nEqns() const
297 return coeffs().size();
301 Foam::scalarField& Foam::scalarTransportPOD::coeffs()
307 const Foam::scalarField& Foam::scalarTransportPOD::coeffs() const
313 void Foam::scalarTransportPOD::derivatives
316 const scalarField& y,
320 if (!derivativeMatrixPtr_)
322 calcDerivativeCoeffs();
325 const scalarSquareMatrix& derivative = *derivativeMatrixPtr_;
333 dydx[i] += derivative[i][j]*y[j];
339 void Foam::scalarTransportPOD::jacobian
342 const scalarField& y,
344 scalarSquareMatrix& dfdy
347 derivatives(x, y, dfdx);
352 const Foam::scalarPODOrthoNormalBase&
353 Foam::scalarTransportPOD::orthoBase() const
360 return *orthoBasePtr_;
364 void Foam::scalarTransportPOD::clearBase() const
366 deleteDemandDrivenData(orthoBasePtr_);
370 const Foam::volScalarField& Foam::scalarTransportPOD::field() const
381 void Foam::scalarTransportPOD::updateFields() const
392 mesh().time().timeName(),
401 orthoBase().orthoField(0).dimensions(),
407 volScalarField& phi = *fieldPtr_;
409 const scalarPODOrthoNormalBase& b = orthoBase();
411 phi = dimensionedScalar("zero", b.orthoField(0).dimensions(), 0);
415 phi += coeffs_[i]*b.orthoField(i);
420 void Foam::scalarTransportPOD::clearFields() const
422 deleteDemandDrivenData(fieldPtr_);
426 void Foam::scalarTransportPOD::write() const
428 // Recalculate field and force a write
434 // * * * * * * * * * * * * * * * Friend Operators * * * * * * * * * * * * * //
437 // ************************************************************************* //