FreeFOAM The Cross-Platform CFD Toolkit
Hosted by SourceForge:
Get FreeFOAM at SourceForge.net.
            Fast, secure and Free Open Source software downloads

porousZone.C

Go to the documentation of this file.
00001 /*---------------------------------------------------------------------------*\
00002   =========                 |
00003   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
00004    \\    /   O peration     |
00005     \\  /    A nd           | Copyright (C) 1991-2010 OpenCFD Ltd.
00006      \\/     M anipulation  |
00007 -------------------------------------------------------------------------------
00008 License
00009     This file is part of OpenFOAM.
00010 
00011     OpenFOAM is free software: you can redistribute it and/or modify it
00012     under the terms of the GNU General Public License as published by
00013     the Free Software Foundation, either version 3 of the License, or
00014     (at your option) any later version.
00015 
00016     OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
00017     ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
00018     FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
00019     for more details.
00020 
00021     You should have received a copy of the GNU General Public License
00022     along with OpenFOAM.  If not, see <http://www.gnu.org/licenses/>.
00023 
00024 \*----------------------------------------------------------------------------*/
00025 
00026 #include "porousZone.H"
00027 #include <finiteVolume/fvMesh.H>
00028 #include <finiteVolume/fvMatrices.H>
00029 #include <OpenFOAM/geometricOneField.H>
00030 
00031 // * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * * //
00032 
00033 // adjust negative resistance values to be multiplier of max value
00034 void Foam::porousZone::adjustNegativeResistance(dimensionedVector& resist)
00035 {
00036     scalar maxCmpt = max(0, cmptMax(resist.value()));
00037 
00038     if (maxCmpt < 0)
00039     {
00040         FatalErrorIn
00041         (
00042             "Foam::porousZone::porousZone::adjustNegativeResistance"
00043             "(dimensionedVector&)"
00044         )   << "negative resistances! " << resist
00045             << exit(FatalError);
00046     }
00047     else
00048     {
00049         vector& val = resist.value();
00050         for (label cmpt=0; cmpt < vector::nComponents; ++cmpt)
00051         {
00052             if (val[cmpt] < 0)
00053             {
00054                 val[cmpt] *= -maxCmpt;
00055             }
00056         }
00057     }
00058 }
00059 
00060 
00061 // * * * * * * * * * * * * * * * * Constructors  * * * * * * * * * * * * * * //
00062 
00063 Foam::porousZone::porousZone
00064 (
00065     const word& name,
00066     const fvMesh& mesh,
00067     const dictionary& dict
00068 )
00069 :
00070     name_(name),
00071     mesh_(mesh),
00072     dict_(dict),
00073     cellZoneID_(mesh_.cellZones().findZoneID(name)),
00074     coordSys_(dict, mesh),
00075     porosity_(1),
00076     C0_(0),
00077     C1_(0),
00078     D_("D", dimensionSet(0, -2, 0, 0, 0), tensor::zero),
00079     F_("F", dimensionSet(0, -1, 0, 0, 0), tensor::zero)
00080 {
00081     Info<< "Creating porous zone: " << name_ << endl;
00082 
00083     bool foundZone = (cellZoneID_ != -1);
00084     reduce(foundZone, orOp<bool>());
00085 
00086     if (!foundZone && Pstream::master())
00087     {
00088         FatalErrorIn
00089         (
00090             "Foam::porousZone::porousZone"
00091             "(const fvMesh&, const word&, const dictionary&)"
00092         )   << "cannot find porous cellZone " << name_
00093             << exit(FatalError);
00094     }
00095 
00096 
00097     // porosity
00098     if (dict_.readIfPresent("porosity", porosity_))
00099     {
00100         if (porosity_ <= 0.0 || porosity_ > 1.0)
00101         {
00102             FatalIOErrorIn
00103             (
00104                 "Foam::porousZone::porousZone"
00105                 "(const fvMesh&, const word&, const dictionary&)",
00106                 dict_
00107             )
00108                 << "out-of-range porosity value " << porosity_
00109                 << exit(FatalIOError);
00110         }
00111     }
00112 
00113     // powerLaw coefficients
00114     if (const dictionary* dictPtr = dict_.subDictPtr("powerLaw"))
00115     {
00116         dictPtr->readIfPresent("C0", C0_);
00117         dictPtr->readIfPresent("C1", C1_);
00118     }
00119 
00120     // Darcy-Forchheimer coefficients
00121     if (const dictionary* dictPtr = dict_.subDictPtr("Darcy"))
00122     {
00123         // local-to-global transformation tensor
00124         const tensor& E = coordSys_.R();
00125 
00126         dimensionedVector d(vector::zero);
00127         if (dictPtr->readIfPresent("d", d))
00128         {
00129             if (D_.dimensions() != d.dimensions())
00130             {
00131                 FatalIOErrorIn
00132                 (
00133                     "Foam::porousZone::porousZone"
00134                     "(const fvMesh&, const word&, const dictionary&)",
00135                     dict_
00136                 )   << "incorrect dimensions for d: " << d.dimensions()
00137                     << " should be " << D_.dimensions()
00138                     << exit(FatalIOError);
00139             }
00140 
00141             adjustNegativeResistance(d);
00142 
00143             D_.value().xx() = d.value().x();
00144             D_.value().yy() = d.value().y();
00145             D_.value().zz() = d.value().z();
00146             D_.value() = (E & D_ & E.T()).value();
00147         }
00148 
00149         dimensionedVector f(vector::zero);
00150         if (dictPtr->readIfPresent("f", f))
00151         {
00152             if (F_.dimensions() != f.dimensions())
00153             {
00154                 FatalIOErrorIn
00155                 (
00156                     "Foam::porousZone::porousZone"
00157                     "(const fvMesh&, const word&, const dictionary&)",
00158                     dict_
00159                 )   << "incorrect dimensions for f: " << f.dimensions()
00160                     << " should be " << F_.dimensions()
00161                     << exit(FatalIOError);
00162             }
00163 
00164             adjustNegativeResistance(f);
00165 
00166             // leading 0.5 is from 1/2 * rho
00167             F_.value().xx() = 0.5*f.value().x();
00168             F_.value().yy() = 0.5*f.value().y();
00169             F_.value().zz() = 0.5*f.value().z();
00170             F_.value() = (E & F_ & E.T()).value();
00171         }
00172     }
00173 
00174     // provide some feedback for the user
00175     // writeDict(Info, false);
00176 
00177     // it is an error not to define anything
00178     if
00179     (
00180         C0_ <= VSMALL
00181      && magSqr(D_.value()) <= VSMALL
00182      && magSqr(F_.value()) <= VSMALL
00183     )
00184     {
00185         FatalIOErrorIn
00186         (
00187             "Foam::porousZone::porousZone"
00188             "(const fvMesh&, const word&, const dictionary&)",
00189             dict_
00190         )   << "neither powerLaw (powerLaw C0/C1) "
00191                "nor Darcy-Forchheimer law (Darcy d/f) specified"
00192             << exit(FatalIOError);
00193     }
00194 }
00195 
00196 
00197 // * * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * //
00198 
00199 void Foam::porousZone::addResistance(fvVectorMatrix& UEqn) const
00200 {
00201     if (cellZoneID_ == -1)
00202     {
00203         return;
00204     }
00205 
00206     bool compressible = false;
00207     if (UEqn.dimensions() == dimensionSet(1, 1, -2, 0, 0))
00208     {
00209         compressible = true;
00210     }
00211 
00212     const labelList& cells = mesh_.cellZones()[cellZoneID_];
00213     const scalarField& V = mesh_.V();
00214     scalarField& Udiag = UEqn.diag();
00215     vectorField& Usource = UEqn.source();
00216     const vectorField& U = UEqn.psi();
00217 
00218     if (C0_ > VSMALL)
00219     {
00220         if (compressible)
00221         {
00222             addPowerLawResistance
00223             (
00224                 Udiag,
00225                 cells,
00226                 V,
00227                 mesh_.lookupObject<volScalarField>("rho"),
00228                 U
00229             );
00230         }
00231         else
00232         {
00233             addPowerLawResistance
00234             (
00235                 Udiag,
00236                 cells,
00237                 V,
00238                 geometricOneField(),
00239                 U
00240             );
00241         }
00242     }
00243 
00244     const tensor& D = D_.value();
00245     const tensor& F = F_.value();
00246 
00247     if (magSqr(D) > VSMALL || magSqr(F) > VSMALL)
00248     {
00249         if (compressible)
00250         {
00251             addViscousInertialResistance
00252             (
00253                 Udiag,
00254                 Usource,
00255                 cells,
00256                 V,
00257                 mesh_.lookupObject<volScalarField>("rho"),
00258                 mesh_.lookupObject<volScalarField>("mu"),
00259                 U
00260             );
00261         }
00262         else
00263         {
00264             addViscousInertialResistance
00265             (
00266                 Udiag,
00267                 Usource,
00268                 cells,
00269                 V,
00270                 geometricOneField(),
00271                 mesh_.lookupObject<volScalarField>("nu"),
00272                 U
00273             );
00274         }
00275     }
00276 }
00277 
00278 
00279 void Foam::porousZone::addResistance
00280 (
00281     const fvVectorMatrix& UEqn,
00282     volTensorField& AU,
00283     bool correctAUprocBC
00284 ) const
00285 {
00286     if (cellZoneID_ == -1)
00287     {
00288         return;
00289     }
00290 
00291     bool compressible = false;
00292     if (UEqn.dimensions() == dimensionSet(1, 1, -2, 0, 0))
00293     {
00294         compressible = true;
00295     }
00296 
00297     const labelList& cells = mesh_.cellZones()[cellZoneID_];
00298     const vectorField& U = UEqn.psi();
00299 
00300     if (C0_ > VSMALL)
00301     {
00302         if (compressible)
00303         {
00304             addPowerLawResistance
00305             (
00306                 AU,
00307                 cells,
00308                 mesh_.lookupObject<volScalarField>("rho"),
00309                 U
00310             );
00311         }
00312         else
00313         {
00314             addPowerLawResistance
00315             (
00316                 AU,
00317                 cells,
00318                 geometricOneField(),
00319                 U
00320             );
00321         }
00322     }
00323 
00324     const tensor& D = D_.value();
00325     const tensor& F = F_.value();
00326 
00327     if (magSqr(D) > VSMALL || magSqr(F) > VSMALL)
00328     {
00329         if (compressible)
00330         {
00331             addViscousInertialResistance
00332             (
00333                 AU,
00334                 cells,
00335                 mesh_.lookupObject<volScalarField>("rho"),
00336                 mesh_.lookupObject<volScalarField>("mu"),
00337                 U
00338             );
00339         }
00340         else
00341         {
00342             addViscousInertialResistance
00343             (
00344                 AU,
00345                 cells,
00346                 geometricOneField(),
00347                 mesh_.lookupObject<volScalarField>("nu"),
00348                 U
00349             );
00350         }
00351     }
00352 
00353     if (correctAUprocBC)
00354     {
00355         // Correct the boundary conditions of the tensorial diagonal to ensure
00356         // processor boundaries are correctly handled when AU^-1 is interpolated
00357         // for the pressure equation.
00358         AU.correctBoundaryConditions();
00359     }
00360 }
00361 
00362 
00363 void Foam::porousZone::writeDict(Ostream& os, bool subDict) const
00364 {
00365     if (subDict)
00366     {
00367         os  << indent << token::BEGIN_BLOCK << incrIndent << nl;
00368         os.writeKeyword("name") << zoneName() << token::END_STATEMENT << nl;
00369     }
00370     else
00371     {
00372         os  << indent << zoneName() << nl
00373             << indent << token::BEGIN_BLOCK << incrIndent << nl;
00374     }
00375 
00376     if (dict_.found("note"))
00377     {
00378         os.writeKeyword("note") << string(dict_.lookup("note"))
00379             << token::END_STATEMENT << nl;
00380     }
00381 
00382     coordSys_.writeDict(os, true);
00383 
00384     if (dict_.found("porosity"))
00385     {
00386         os.writeKeyword("porosity") << porosity() << token::END_STATEMENT << nl;
00387     }
00388 
00389     // powerLaw coefficients
00390     if (const dictionary* dictPtr = dict_.subDictPtr("powerLaw"))
00391     {
00392         os << indent << "powerLaw";
00393         dictPtr->write(os);
00394     }
00395 
00396     // Darcy-Forchheimer coefficients
00397     if (const dictionary* dictPtr = dict_.subDictPtr("Darcy"))
00398     {
00399         os << indent << "Darcy";
00400         dictPtr->write(os);
00401     }
00402 
00403     os << decrIndent << indent << token::END_BLOCK << endl;
00404 }
00405 
00406 
00407 // * * * * * * * * * * * * * * * IOstream Operators  * * * * * * * * * * * * //
00408 
00409 Foam::Ostream& Foam::operator<<(Ostream& os, const porousZone& pZone)
00410 {
00411     pZone.writeDict(os);
00412     return os;
00413 }
00414 
00415 // ************************ vim: set sw=4 sts=4 et: ************************ //
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines