1 /*---------------------------------------------------------------------------*\
3 \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
5 \\ / A nd | Copyright (C) 2004-2011 OpenCFD Ltd.
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
13 the Free Software Foundation, either version 3 of the License, or
14 (at your 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, see <http://www.gnu.org/licenses/>.
24 \*----------------------------------------------------------------------------*/
26 #include "porousZone.H"
28 #include "fvMatrices.H"
29 #include "geometricOneField.H"
31 // * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * * //
33 // adjust negative resistance values to be multiplier of max value
34 void Foam::porousZone::adjustNegativeResistance(dimensionedVector& resist)
36 scalar maxCmpt = max(0, cmptMax(resist.value()));
42 "Foam::porousZone::porousZone::adjustNegativeResistance"
43 "(dimensionedVector&)"
44 ) << "negative resistances! " << resist
49 vector& val = resist.value();
50 for (label cmpt=0; cmpt < vector::nComponents; ++cmpt)
54 val[cmpt] *= -maxCmpt;
61 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
63 Foam::porousZone::porousZone
67 const dictionary& dict
73 cellZoneIds_(mesh_.cellZones().findIndices(key_)),
74 coordSys_(dict, mesh),
80 D_("D", dimensionSet(0, -2, 0, 0, 0), tensor::zero),
81 F_("F", dimensionSet(0, -1, 0, 0, 0), tensor::zero)
83 Info<< "Creating porous zone: " << key_ << endl;
85 bool foundZone = !cellZoneIds_.empty();
86 reduce(foundZone, orOp<bool>());
88 if (!foundZone && Pstream::master())
92 "Foam::porousZone::porousZone"
93 "(const keyType&, const fvMesh&, const dictionary&)"
94 ) << "cannot find porous cellZone " << key_
102 dict_.readIfPresent("porosity", porosity_)
103 && (porosity_ <= 0.0 || porosity_ > 1.0)
108 "Foam::porousZone::porousZone"
109 "(const keyType&, const fvMesh&, const dictionary&)",
112 << "out-of-range porosity value " << porosity_
113 << exit(FatalIOError);
116 // turbulent intensity
119 dict_.readIfPresent("intensity", intensity_)
120 && (intensity_ <= 0.0 || intensity_ > 1.0)
125 "Foam::porousZone::porousZone"
126 "(const keyType&, const fvMesh&, const dictionary&)",
129 << "out-of-range turbulent intensity value " << intensity_
130 << exit(FatalIOError);
133 // turbulent length scale
136 dict_.readIfPresent("mixingLength", mixingLength_)
137 && (mixingLength_ <= 0.0)
142 "Foam::porousZone::porousZone"
143 "(const keyType&, const fvMesh&, const dictionary&)",
146 << "out-of-range turbulent length scale " << mixingLength_
147 << exit(FatalIOError);
151 // powerLaw coefficients
152 if (const dictionary* dictPtr = dict_.subDictPtr("powerLaw"))
154 dictPtr->readIfPresent("C0", C0_);
155 dictPtr->readIfPresent("C1", C1_);
158 // Darcy-Forchheimer coefficients
159 if (const dictionary* dictPtr = dict_.subDictPtr("Darcy"))
161 // local-to-global transformation tensor
162 const tensor& E = coordSys_.R();
164 dimensionedVector d(vector::zero);
165 if (dictPtr->readIfPresent("d", d))
167 if (D_.dimensions() != d.dimensions())
171 "Foam::porousZone::porousZone"
172 "(const keyType&, const fvMesh&, const dictionary&)",
174 ) << "incorrect dimensions for d: " << d.dimensions()
175 << " should be " << D_.dimensions()
176 << exit(FatalIOError);
179 adjustNegativeResistance(d);
181 D_.value().xx() = d.value().x();
182 D_.value().yy() = d.value().y();
183 D_.value().zz() = d.value().z();
184 D_.value() = (E & D_ & E.T()).value();
187 dimensionedVector f(vector::zero);
188 if (dictPtr->readIfPresent("f", f))
190 if (F_.dimensions() != f.dimensions())
194 "Foam::porousZone::porousZone"
195 "(const keyType&, const fvMesh&, const dictionary&)",
197 ) << "incorrect dimensions for f: " << f.dimensions()
198 << " should be " << F_.dimensions()
199 << exit(FatalIOError);
202 adjustNegativeResistance(f);
204 // leading 0.5 is from 1/2 * rho
205 F_.value().xx() = 0.5*f.value().x();
206 F_.value().yy() = 0.5*f.value().y();
207 F_.value().zz() = 0.5*f.value().z();
208 F_.value() = (E & F_ & E.T()).value();
212 // it is an error not to define anything
216 && magSqr(D_.value()) <= VSMALL
217 && magSqr(F_.value()) <= VSMALL
222 "Foam::porousZone::porousZone"
223 "(const keyType&, const fvMesh&, const dictionary&)",
225 ) << "neither powerLaw (C0/C1) "
226 "nor Darcy-Forchheimer law (d/f) specified"
227 << exit(FatalIOError);
230 // feedback for the user
231 if (dict.lookupOrDefault("printCoeffs", false))
233 writeDict(Info, false);
238 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
240 void Foam::porousZone::addResistance(fvVectorMatrix& UEqn) const
242 if (cellZoneIds_.empty())
247 bool compressible = false;
248 if (UEqn.dimensions() == dimensionSet(1, 1, -2, 0, 0))
253 const scalarField& V = mesh_.V();
254 scalarField& Udiag = UEqn.diag();
255 vectorField& Usource = UEqn.source();
256 const vectorField& U = UEqn.psi();
262 addPowerLawResistance
266 mesh_.lookupObject<volScalarField>("rho"),
272 addPowerLawResistance
282 const tensor& D = D_.value();
283 const tensor& F = F_.value();
285 if (magSqr(D) > VSMALL || magSqr(F) > VSMALL)
289 addViscousInertialResistance
294 mesh_.lookupObject<volScalarField>("rho"),
295 mesh_.lookupObject<volScalarField>("mu"),
301 addViscousInertialResistance
307 mesh_.lookupObject<volScalarField>("nu"),
315 void Foam::porousZone::addResistance
317 const fvVectorMatrix& UEqn,
322 if (cellZoneIds_.empty())
327 bool compressible = false;
328 if (UEqn.dimensions() == dimensionSet(1, 1, -2, 0, 0))
333 const vectorField& U = UEqn.psi();
339 addPowerLawResistance
342 mesh_.lookupObject<volScalarField>("rho"),
348 addPowerLawResistance
357 const tensor& D = D_.value();
358 const tensor& F = F_.value();
360 if (magSqr(D) > VSMALL || magSqr(F) > VSMALL)
364 addViscousInertialResistance
367 mesh_.lookupObject<volScalarField>("rho"),
368 mesh_.lookupObject<volScalarField>("mu"),
374 addViscousInertialResistance
378 mesh_.lookupObject<volScalarField>("nu"),
386 // Correct the boundary conditions of the tensorial diagonal to ensure
387 // processor boundaries are correctly handled when AU^-1 is interpolated
388 // for the pressure equation.
389 AU.correctBoundaryConditions();
394 void Foam::porousZone::writeDict(Ostream& os, bool subDict) const
398 os << indent << token::BEGIN_BLOCK << incrIndent << nl;
399 os.writeKeyword("name")
400 << zoneName() << token::END_STATEMENT << nl;
404 os << indent << zoneName() << nl
405 << indent << token::BEGIN_BLOCK << incrIndent << nl;
408 if (dict_.found("note"))
410 os.writeKeyword("note")
411 << string(dict_.lookup("note")) << token::END_STATEMENT << nl;
414 coordSys_.writeDict(os, true);
416 if (dict_.found("porosity"))
418 os.writeKeyword("porosity")
419 << porosity() << token::END_STATEMENT << nl;
422 if (dict_.found("intensity"))
424 os.writeKeyword("intensity")
425 << intensity() << token::END_STATEMENT << nl;
428 if (dict_.found("mixingLength"))
430 os.writeKeyword("mixingLength")
431 << mixingLength() << token::END_STATEMENT << nl;
434 // powerLaw coefficients
435 if (const dictionary* dictPtr = dict_.subDictPtr("powerLaw"))
437 os << indent << "powerLaw";
441 // Darcy-Forchheimer coefficients
442 if (const dictionary* dictPtr = dict_.subDictPtr("Darcy"))
444 os << indent << "Darcy";
449 if (const dictionary* dictPtr = dict_.subDictPtr("thermalModel"))
451 os << indent << "thermalModel";
455 os << decrIndent << indent << token::END_BLOCK << endl;
459 // * * * * * * * * * * * * * * * IOstream Operators * * * * * * * * * * * * //
461 Foam::Ostream& Foam::operator<<(Ostream& os, const porousZone& pz)
467 // ************************************************************************* //