1 /*---------------------------------------------------------------------------*\
3 \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
5 \\ / A nd | Copyright (C) 1991-2009 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 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
25 \*----------------------------------------------------------------------------*/
27 #include "porousZone.H"
29 #include "fvMatrices.H"
32 // * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * * //
34 // adjust negative resistance values to be multiplier of max value
35 void Foam::porousZone::adjustNegativeResistance(dimensionedVector& resist)
37 scalar maxCmpt = max(0, cmptMax(resist.value()));
43 "Foam::porousZone::porousZone::adjustNegativeResistance"
44 "(dimensionedVector&)"
45 ) << "negative resistances! " << resist
50 vector& val = resist.value();
51 for (label cmpt=0; cmpt < vector::nComponents; ++cmpt)
55 val[cmpt] *= -maxCmpt;
62 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
64 Foam::porousZone::porousZone
68 const dictionary& dict
74 cellZoneID_(mesh_.cellZones().findZoneID(name)),
75 coordSys_(dict, mesh),
79 D_("D", dimensionSet(0, -2, 0, 0, 0), tensor::zero),
80 F_("F", dimensionSet(0, -1, 0, 0, 0), tensor::zero)
82 Info<< "Creating porous zone: " << name_ << endl;
84 if (cellZoneID_ == -1 && !Pstream::parRun())
88 "Foam::porousZone::porousZone"
89 "(const fvMesh&, const word&, const dictionary&)"
90 ) << "cannot find porous cellZone " << name_
95 if (dict_.readIfPresent("porosity", porosity_))
97 if (porosity_ <= 0.0 || porosity_ > 1.0)
101 "Foam::porousZone::porousZone"
102 "(const fvMesh&, const word&, const dictionary&)",
105 << "out-of-range porosity value " << porosity_
106 << exit(FatalIOError);
110 // powerLaw coefficients
111 if (const dictionary* dictPtr = dict_.subDictPtr("powerLaw"))
113 dictPtr->readIfPresent("C0", C0_);
114 dictPtr->readIfPresent("C1", C1_);
117 // Darcy-Forchheimer coefficients
118 if (const dictionary* dictPtr = dict_.subDictPtr("Darcy"))
120 // local-to-global transformation tensor
121 const tensor& E = coordSys_.R();
123 dimensionedVector d(vector::zero);
124 if (dictPtr->readIfPresent("d", d))
126 if (D_.dimensions() != d.dimensions())
130 "Foam::porousZone::porousZone"
131 "(const fvMesh&, const word&, const dictionary&)",
133 ) << "incorrect dimensions for d: " << d.dimensions()
134 << " should be " << D_.dimensions()
135 << exit(FatalIOError);
138 adjustNegativeResistance(d);
140 D_.value().xx() = d.value().x();
141 D_.value().yy() = d.value().y();
142 D_.value().zz() = d.value().z();
143 D_.value() = (E & D_ & E.T()).value();
146 dimensionedVector f(vector::zero);
147 if (dictPtr->readIfPresent("f", f))
149 if (F_.dimensions() != f.dimensions())
153 "Foam::porousZone::porousZone"
154 "(const fvMesh&, const word&, const dictionary&)",
156 ) << "incorrect dimensions for f: " << f.dimensions()
157 << " should be " << F_.dimensions()
158 << exit(FatalIOError);
161 adjustNegativeResistance(f);
163 // leading 0.5 is from 1/2 * rho
164 F_.value().xx() = 0.5*f.value().x();
165 F_.value().yy() = 0.5*f.value().y();
166 F_.value().zz() = 0.5*f.value().z();
167 F_.value() = (E & F_ & E.T()).value();
171 // provide some feedback for the user
172 // writeDict(Info, false);
174 // it is an error not to define anything
178 && magSqr(D_.value()) <= VSMALL
179 && magSqr(F_.value()) <= VSMALL
184 "Foam::porousZone::porousZone"
185 "(const fvMesh&, const word&, const dictionary&)",
187 ) << "neither powerLaw (C0/C1) "
188 "nor Darcy-Forchheimer law (d/f) specified"
189 << exit(FatalIOError);
194 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
196 void Foam::porousZone::addResistance(fvVectorMatrix& UEqn) const
198 if (cellZoneID_ == -1)
203 bool compressible = false;
204 if (UEqn.dimensions() == dimensionSet(1, 1, -2, 0, 0))
209 const labelList& cells = mesh_.cellZones()[cellZoneID_];
210 const scalarField& V = mesh_.V();
211 scalarField& Udiag = UEqn.diag();
212 vectorField& Usource = UEqn.source();
213 const vectorField& U = UEqn.psi();
219 addPowerLawResistance
224 mesh_.lookupObject<volScalarField>("rho"),
230 addPowerLawResistance
241 const tensor& D = D_.value();
242 const tensor& F = F_.value();
244 if (magSqr(D) > VSMALL || magSqr(F) > VSMALL)
248 addViscousInertialResistance
254 mesh_.lookupObject<volScalarField>("rho"),
255 mesh_.lookupObject<volScalarField>("mu"),
261 addViscousInertialResistance
268 mesh_.lookupObject<volScalarField>("nu"),
276 void Foam::porousZone::addResistance
278 const fvVectorMatrix& UEqn,
283 if (cellZoneID_ == -1)
288 bool compressible = false;
289 if (UEqn.dimensions() == dimensionSet(1, 1, -2, 0, 0))
294 const labelList& cells = mesh_.cellZones()[cellZoneID_];
295 const vectorField& U = UEqn.psi();
301 addPowerLawResistance
305 mesh_.lookupObject<volScalarField>("rho"),
311 addPowerLawResistance
321 const tensor& D = D_.value();
322 const tensor& F = F_.value();
324 if (magSqr(D) > VSMALL || magSqr(F) > VSMALL)
328 addViscousInertialResistance
332 mesh_.lookupObject<volScalarField>("rho"),
333 mesh_.lookupObject<volScalarField>("mu"),
339 addViscousInertialResistance
344 mesh_.lookupObject<volScalarField>("nu"),
352 // Correct the boundary conditions of the tensorial diagonal to ensure
353 // processor boundaries are correctly handled when AU^-1 is interpolated
354 // for the pressure equation.
355 AU.correctBoundaryConditions();
360 void Foam::porousZone::writeDict(Ostream& os, bool subDict) const
364 os << indent << token::BEGIN_BLOCK << incrIndent << nl;
365 os.writeKeyword("name") << zoneName() << token::END_STATEMENT << nl;
369 os << indent << zoneName() << nl
370 << indent << token::BEGIN_BLOCK << incrIndent << nl;
373 if (dict_.found("note"))
375 os.writeKeyword("note") << string(dict_.lookup("note"))
376 << token::END_STATEMENT << nl;
379 coordSys_.writeDict(os, true);
381 if (dict_.found("porosity"))
383 os.writeKeyword("porosity") << porosity() << token::END_STATEMENT << nl;
386 // powerLaw coefficients
387 if (const dictionary* dictPtr = dict_.subDictPtr("powerLaw"))
389 os << indent << "powerLaw";
393 // Darcy-Forchheimer coefficients
394 if (const dictionary* dictPtr = dict_.subDictPtr("Darcy"))
396 os << indent << "Darcy";
400 os << decrIndent << indent << token::END_BLOCK << endl;
404 // * * * * * * * * * * * * * * * IOstream Operators * * * * * * * * * * * * //
406 Foam::Ostream& Foam::operator<<(Ostream& os, const porousZone& pZone)
412 // ************************************************************************* //