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/>.
24 \*---------------------------------------------------------------------------*/
28 #include "volFields.H"
29 #include "surfaceFields.H"
30 #include "slicedVolFields.H"
31 #include "slicedSurfaceFields.H"
33 #include "cyclicFvPatchFields.H"
34 #include "cyclicGgiFvPatchFields.H"
36 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
41 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
43 void fvMesh::makeSf() const
47 Info<< "void fvMesh::makeSf() const : "
48 << "assembling face areas"
52 // It is an error to attempt to recalculate
53 // if the pointer is already set
56 FatalErrorIn("fvMesh::makeSf() const")
57 << "face areas already exist"
61 SfPtr_ = new slicedSurfaceVectorField
77 void fvMesh::makeMagSf() const
81 Info<< "void fvMesh::makeMagSf() const : "
82 << "assembling mag face areas"
86 // It is an error to attempt to recalculate
87 // if the pointer is already set
90 FatalErrorIn("void fvMesh::makeMagSf() const")
91 << "mag face areas already exist"
95 // Note: Added stabilisation for faces with exactly zero area.
96 // These should be caught on mesh checking but at least this stops
97 // the code from producing NaNs. HJ, date deleted
98 magSfPtr_ = new surfaceScalarField
110 mag(Sf()) + dimensionedScalar("vs", dimArea, VSMALL)
115 void fvMesh::makeC() const
119 Info<< "void fvMesh::makeC() const : "
120 << "assembling cell centres"
124 // It is an error to attempt to recalculate
125 // if the pointer is already set
128 FatalErrorIn("fvMesh::makeC() const")
129 << "cell centres already exist"
130 << abort(FatalError);
133 CPtr_ = new slicedVolVectorField
151 // This piece of code is necessary for cyclic and cyclicGgi interfaces
152 // using a separationOffset transform.
153 // Those two interfaces will be using the method ::patchNeighbourField()
154 // to evaluate the field C on the shadow patch. For cyclic and cyclicGgi
155 // translational-only interfaces, the separationOffset transform is never
156 // applied directly in ::patchNeighbourField() because this transform is
157 // only pertinent for 3D coordinates, and the method ::patchNeighbourField()
158 // does not discriminate the type of field it is operating on.
159 // So, because the separationOffset transform is not applied, the evaluation
160 // of a 3D position field like 'C' will always be wrong on the shadow patches
161 // of translational cyclic and cyclicGgi interfaces.
162 // For cyclic and cyclicGgi interfaces using a rotational transform, the
163 // evaluation of the field C will be valid, but since we are only
164 // interested in the patch face centers for these interfaces, we can override
165 // those values as well.
167 // https://sourceforge.net/apps/mantisbt/openfoam-extend/view.php?id=42
170 // Need to correct for cyclics transformation since absolute quantity.
171 // Ok on processor patches since hold opposite cell centre (no
173 slicedVolVectorField& C = *CPtr_;
175 forAll(C.boundaryField(), patchi)
179 isA<cyclicFvPatchVectorField>(C.boundaryField()[patchi])
180 || isA<cyclicGgiFvPatchVectorField>(C.boundaryField()[patchi])
183 // Note: cyclic is not slice but proper field
184 C.boundaryField()[patchi] == static_cast<const vectorField&>
186 static_cast<const List<vector>&>
188 boundary_[patchi].patchSlice(faceCentres())
196 void fvMesh::makeCf() const
200 Info<< "void fvMesh::makeCf() const : "
201 << "assembling face centres"
205 // It is an error to attempt to recalculate
206 // if the pointer is already set
209 FatalErrorIn("fvMesh::makeCf() const")
210 << "face centres already exist"
211 << abort(FatalError);
214 CfPtr_ = new slicedSurfaceVectorField
233 void fvMesh::makePhi() const
237 Info<< "void fvMesh::makePhi() const : "
238 << "reading old time flux field if present and creating "
239 << "zero current time flux field"
243 // It is an error to attempt to recalculate
244 // if the pointer is already set
247 FatalErrorIn("fvMesh::makePhi() const")
248 << "flux field already exists"
249 << abort(FatalError);
252 // Reading old time mesh motion flux if it exists and
253 // creating zero current time mesh motion flux
255 scalar t0 = this->time().value() - this->time().deltaT().value();
257 IOobject meshPhiHeader
260 this->time().timeName(t0),
265 if (meshPhiHeader.headerOk())
269 InfoIn("void fvMesh::makePhi()")
270 << "Reading mesh fluxes" << endl;
273 phiPtr_ = new surfaceScalarField
278 this->time().timeName(t0),
288 (*phiPtr_) = dimensionedScalar("0", dimVolume/dimTime, 0.0);
290 // This mesh is moving: set the motion to true
296 InfoIn("void fvMesh::makePhi()")
297 << "Creating null mesh motion fluxes" << endl;
300 phiPtr_ = new surfaceScalarField
305 this->time().timeName(),
311 dimensionedScalar("0", dimVolume/dimTime, 0.0)
317 void fvMesh::updatePhi(const scalarField& sweptVols) const
319 // Fill in mesh motion fluxes given swept volumes for all faces
326 surfaceScalarField& phi = *phiPtr_;
328 scalar rDeltaT = 1.0/time().deltaT().value();
330 phi.internalField() = scalarField::subField(sweptVols, nInternalFaces());
331 phi.internalField() *= rDeltaT;
333 const fvPatchList& patches = boundary();
335 forAll (patches, patchI)
337 phi.boundaryField()[patchI] = patches[patchI].patchSlice(sweptVols);
338 phi.boundaryField()[patchI] *= rDeltaT;
343 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
345 const volScalarField::DimensionedInternalField& fvMesh::V() const
353 "const volScalarField::DimensionedInternalField& "
355 ) << "Calculating cell volumes." << endl;
358 VPtr_ = new DimensionedField<scalar, volMesh>
378 const volScalarField::DimensionedInternalField& fvMesh::V0() const
382 FatalErrorIn("fvMesh::V0() const")
383 << "V0 is not available"
384 << abort(FatalError);
391 DimensionedField<scalar, volMesh>& fvMesh::setV0()
393 // Delete old volume and mesh motion fluxes. setV0() must be followed by
394 // another mesh motion. HJ, 25/Feb/2009
395 deleteDemandDrivenData(phiPtr_);
396 deleteDemandDrivenData(V0Ptr_);
400 InfoIn("DimensionedField<scalar, volMesh>& fvMesh::setV0()")
401 << "Setting old cell volumes" << endl;
404 V0Ptr_ = new DimensionedField<scalar, volMesh>
421 const volScalarField::DimensionedInternalField& fvMesh::V00() const
425 V00Ptr_ = new DimensionedField<scalar, volMesh>
438 // If V00 is used then V0 should be stored for restart
439 V0Ptr_->writeOpt() = IOobject::AUTO_WRITE;
446 tmp<volScalarField::DimensionedInternalField> fvMesh::Vsc() const
448 if (moving() && time().subCycling())
450 const TimeState& ts = time();
451 const TimeState& ts0 = time().prevTimeState();
455 ts.value() - (ts0.value() - ts0.deltaTValue())
458 if (tFrac < (1 - SMALL))
460 return V0() + tFrac*(V() - V0());
474 tmp<volScalarField::DimensionedInternalField> fvMesh::Vsc0() const
476 if (moving() && time().subCycling())
478 const TimeState& ts = time();
479 const TimeState& ts0 = time().prevTimeState();
483 (ts.value() - ts.deltaTValue())
484 - (ts0.value() - ts0.deltaTValue())
489 return V0() + t0Frac*(V() - V0());
503 const surfaceVectorField& fvMesh::Sf() const
514 const surfaceScalarField& fvMesh::magSf() const
525 const volVectorField& fvMesh::C() const
536 const surfaceVectorField& fvMesh::Cf() const
547 const surfaceScalarField& fvMesh::phi() const
554 // Set zero current time
555 // mesh motion fluxes if the time has been incremented
556 if (phiPtr_->timeIndex() != time().timeIndex())
562 InfoIn("const surfaceScalarField& fvMesh::phi() const")
563 << "Resetting mesh motion fluxes to zero" << endl;
566 (*phiPtr_) = dimensionedScalar("0", dimVolume/dimTime, 0.0);
573 surfaceScalarField& fvMesh::setPhi()
584 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
586 } // End namespace Foam
588 // ************************************************************************* //