1 /*---------------------------------------------------------------------------*\
3 \\ / F ield | foam-extend: Open Source CFD
4 \\ / O peration | Version: 3.2
5 \\ / A nd | Web: http://www.foam-extend.org
6 \\/ M anipulation | For copyright notice see file Copyright
7 -------------------------------------------------------------------------------
9 This file is part of foam-extend.
11 foam-extend 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 3 of the License, or (at your
14 option) any later version.
16 foam-extend is distributed in the hope that it will be useful, but
17 WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 General Public License for more details.
21 You should have received a copy of the GNU General Public License
22 along with foam-extend. If not, see <http://www.gnu.org/licenses/>.
29 \*---------------------------------------------------------------------------*/
31 #include "scalarTransportPOD.H"
33 #include "addToRunTimeSelectionTable.H"
35 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
39 defineTypeNameAndDebug(scalarTransportPOD, 0);
41 addToRunTimeSelectionTable
50 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
52 void Foam::scalarTransportPOD::calcOrthoBase() const
58 "scalarTransportPOD::calcOrthoBase()"
59 ) << "Orthogonal base already calculated"
63 // Create ortho-normal base
64 scalar accuracy = readScalar(dict().lookup("accuracy"));
67 Time& runTime = const_cast<Time&>(mesh().time());
69 // Remember time index to restore it after the scan
70 label origTimeIndex = runTime.timeIndex();
72 instantList Times = runTime.times();
74 // Create a list of snapshots
75 PtrList<volScalarField> fields(Times.size());
81 if (Times[i].value() < SMALL || Times[i] == runTime.constant())
83 Info << "Skipping time " << Times[i] << endl;
88 runTime.setTime(Times[i], i);
90 Info<< "Time = " << runTime.timeName() << endl;
100 if (phiHeader.headerOk())
102 Info<< " Reading " << phiName_ << endl;
104 fields.set(nSnapshots, new volScalarField(phiHeader, mesh()));
107 fields[nSnapshots].rename(phiName_ + name(i));
112 Info<< " No " << phiName_ << endl;
116 // Reset time index to initial state
117 runTime.setTime(Times[origTimeIndex], origTimeIndex);
124 "scalarTransportPOD::calcOrthoBase()"
125 ) << "Insufficient number of snapshots: " << nSnapshots
126 << abort(FatalError);
129 Info << "Number of snapshots: " << nSnapshots << endl;
131 fields.setSize(nSnapshots);
133 // Create ortho-normal base for transported variable
134 orthoBasePtr_ = new scalarPODOrthoNormalBase(fields, accuracy);
138 void Foam::scalarTransportPOD::calcDerivativeCoeffs() const
140 if (derivativeMatrixPtr_)
144 "void scalarTransportPOD::calcDerivativeCoeffs() const"
145 ) << "Derivative matrix already calculated"
146 << abort(FatalError);
149 // Calculate coefficients for differential equation
151 Time& runTime = const_cast<Time&>(this->mesh().time());
153 // Remember time index to restore it
154 label origTimeIndex = runTime.timeIndex();
158 IOdictionary transportProperties
162 "transportProperties",
170 Info<< "Reading diffusivity D\n" << endl;
174 transportProperties.lookup("DT")
177 // Find velocity field
179 word Uname(this->dict().lookup("velocity"));
181 instantList Times = runTime.times();
183 volVectorField* Uptr = NULL;
187 runTime.setTime(Times[i], i);
189 Info<< "Time = " << runTime.timeName() << endl;
199 if (Uheader.headerOk())
201 Info<< " Reading " << Uname << endl;
203 Uptr = new volVectorField(Uheader, this->mesh());
208 Info<< " No " << Uname << endl;
212 // Reset time index to initial state
213 runTime.setTime(Times[origTimeIndex], origTimeIndex);
219 "void scalarTransportPOD::calcDerivativeCoeffs() const"
220 ) << "Cannot find velocity: " << Uname
221 << abort(FatalError);
224 volVectorField& U = *Uptr;
226 // Create derivative matrix
228 const scalarPODOrthoNormalBase& b = orthoBase();
230 derivativeMatrixPtr_ = new scalarSquareMatrix(b.baseSize(), 0.0);
231 scalarSquareMatrix& derivative = *derivativeMatrixPtr_;
233 for (label i = 0; i < b.baseSize(); i++)
235 const volScalarField& snapI = b.orthoField(i);
237 volVectorField gradSnapI = fvc::grad(snapI);
239 for (label j = 0; j < b.baseSize(); j++)
241 const volScalarField& snapJ = b.orthoField(j);
243 volVectorField gradSnapJ = fvc::grad(snapJ);
246 DT.value()*POD::projection(fvc::div(gradSnapJ), snapI)
247 - POD::projection((U & gradSnapJ), snapI);
252 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
254 // Construct from components
255 Foam::scalarTransportPOD::scalarTransportPOD
258 const dictionary& dict
262 phiName_(dict.lookup("field")),
264 derivativeMatrixPtr_(NULL),
268 // Grab coefficients from the first snapshot of the ortho-normal base
269 coeffs_.setSize(orthoBase().baseSize());
271 const scalarRectangularMatrix& orthoBaseCoeffs =
272 orthoBase().interpolationCoeffs();
276 coeffs_[i] = orthoBaseCoeffs[0][i];
281 // * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
283 Foam::scalarTransportPOD::~scalarTransportPOD()
285 deleteDemandDrivenData(derivativeMatrixPtr_);
292 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
294 Foam::label Foam::scalarTransportPOD::nEqns() const
296 return coeffs().size();
300 Foam::scalarField& Foam::scalarTransportPOD::coeffs()
306 const Foam::scalarField& Foam::scalarTransportPOD::coeffs() const
312 void Foam::scalarTransportPOD::derivatives
315 const scalarField& y,
319 if (!derivativeMatrixPtr_)
321 calcDerivativeCoeffs();
324 const scalarSquareMatrix& derivative = *derivativeMatrixPtr_;
332 dydx[i] += derivative[i][j]*y[j];
338 void Foam::scalarTransportPOD::jacobian
341 const scalarField& y,
343 scalarSquareMatrix& dfdy
346 derivatives(x, y, dfdx);
351 const Foam::scalarPODOrthoNormalBase&
352 Foam::scalarTransportPOD::orthoBase() const
359 return *orthoBasePtr_;
363 void Foam::scalarTransportPOD::clearBase() const
365 deleteDemandDrivenData(orthoBasePtr_);
369 const Foam::volScalarField& Foam::scalarTransportPOD::field() const
380 void Foam::scalarTransportPOD::updateFields() const
391 mesh().time().timeName(),
400 orthoBase().orthoField(0).dimensions(),
406 volScalarField& phi = *fieldPtr_;
408 const scalarPODOrthoNormalBase& b = orthoBase();
410 phi = dimensionedScalar("zero", b.orthoField(0).dimensions(), 0);
414 phi += coeffs_[i]*b.orthoField(i);
419 void Foam::scalarTransportPOD::clearFields() const
421 deleteDemandDrivenData(fieldPtr_);
425 void Foam::scalarTransportPOD::write() const
427 // Recalculate field and force a write
433 // * * * * * * * * * * * * * * * Friend Operators * * * * * * * * * * * * * //
436 // ************************************************************************* //