00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 #include "porousZone.H"
00027 #include <finiteVolume/fvMesh.H>
00028 #include <finiteVolume/fvMatrices.H>
00029 #include <OpenFOAM/geometricOneField.H>
00030
00031
00032
00033
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
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
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
00114 if (const dictionary* dictPtr = dict_.subDictPtr("powerLaw"))
00115 {
00116 dictPtr->readIfPresent("C0", C0_);
00117 dictPtr->readIfPresent("C1", C1_);
00118 }
00119
00120
00121 if (const dictionary* dictPtr = dict_.subDictPtr("Darcy"))
00122 {
00123
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
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
00175
00176
00177
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
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
00356
00357
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
00390 if (const dictionary* dictPtr = dict_.subDictPtr("powerLaw"))
00391 {
00392 os << indent << "powerLaw";
00393 dictPtr->write(os);
00394 }
00395
00396
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
00408
00409 Foam::Ostream& Foam::operator<<(Ostream& os, const porousZone& pZone)
00410 {
00411 pZone.writeDict(os);
00412 return os;
00413 }
00414
00415