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 "forces.H"
00027 #include <finiteVolume/volFields.H>
00028 #include <OpenFOAM/dictionary.H>
00029 #include <OpenFOAM/Time.H>
00030
00031 #include <incompressibleTransportModels/singlePhaseTransportModel.H>
00032 #include <incompressibleRASModels/RASModel.H>
00033 #include <incompressibleLESModels/LESModel.H>
00034
00035 #include <basicThermophysicalModels/basicThermo.H>
00036 #include <compressibleRASModels/RASModel.H>
00037 #include <compressibleLESModels/LESModel.H>
00038
00039
00040
00041
00042 namespace Foam
00043 {
00044 defineTypeNameAndDebug(forces, 0);
00045 }
00046
00047
00048
00049 Foam::tmp<Foam::volSymmTensorField> Foam::forces::devRhoReff() const
00050 {
00051 if (obr_.foundObject<compressible::RASModel>("RASProperties"))
00052 {
00053 const compressible::RASModel& ras
00054 = obr_.lookupObject<compressible::RASModel>("RASProperties");
00055
00056 return ras.devRhoReff();
00057 }
00058 else if (obr_.foundObject<incompressible::RASModel>("RASProperties"))
00059 {
00060 const incompressible::RASModel& ras
00061 = obr_.lookupObject<incompressible::RASModel>("RASProperties");
00062
00063 return rho()*ras.devReff();
00064 }
00065 else if (obr_.foundObject<compressible::LESModel>("LESProperties"))
00066 {
00067 const compressible::LESModel& les =
00068 obr_.lookupObject<compressible::LESModel>("LESProperties");
00069
00070 return les.devRhoBeff();
00071 }
00072 else if (obr_.foundObject<incompressible::LESModel>("LESProperties"))
00073 {
00074 const incompressible::LESModel& les
00075 = obr_.lookupObject<incompressible::LESModel>("LESProperties");
00076
00077 return rho()*les.devBeff();
00078 }
00079 else if (obr_.foundObject<basicThermo>("thermophysicalProperties"))
00080 {
00081 const basicThermo& thermo =
00082 obr_.lookupObject<basicThermo>("thermophysicalProperties");
00083
00084 const volVectorField& U = obr_.lookupObject<volVectorField>(UName_);
00085
00086 return -thermo.mu()*dev(twoSymm(fvc::grad(U)));
00087 }
00088 else if
00089 (
00090 obr_.foundObject<singlePhaseTransportModel>("transportProperties")
00091 )
00092 {
00093 const singlePhaseTransportModel& laminarT =
00094 obr_.lookupObject<singlePhaseTransportModel>
00095 ("transportProperties");
00096
00097 const volVectorField& U = obr_.lookupObject<volVectorField>(UName_);
00098
00099 return -rho()*laminarT.nu()*dev(twoSymm(fvc::grad(U)));
00100 }
00101 else if (obr_.foundObject<dictionary>("transportProperties"))
00102 {
00103 const dictionary& transportProperties =
00104 obr_.lookupObject<dictionary>("transportProperties");
00105
00106 dimensionedScalar nu(transportProperties.lookup("nu"));
00107
00108 const volVectorField& U = obr_.lookupObject<volVectorField>(UName_);
00109
00110 return -rho()*nu*dev(twoSymm(fvc::grad(U)));
00111 }
00112 else
00113 {
00114 FatalErrorIn("forces::devRhoReff()")
00115 << "No valid model for viscous stress calculation."
00116 << exit(FatalError);
00117
00118 return volSymmTensorField::null();
00119 }
00120 }
00121
00122
00123 Foam::tmp<Foam::volScalarField> Foam::forces::rho() const
00124 {
00125 if (rhoName_ == "rhoInf")
00126 {
00127 const fvMesh& mesh = refCast<const fvMesh>(obr_);
00128
00129 return tmp<volScalarField>
00130 (
00131 new volScalarField
00132 (
00133 IOobject
00134 (
00135 "rho",
00136 mesh.time().timeName(),
00137 mesh
00138 ),
00139 mesh,
00140 dimensionedScalar("rho", dimDensity, rhoRef_)
00141 )
00142 );
00143 }
00144 else
00145 {
00146 return(obr_.lookupObject<volScalarField>(rhoName_));
00147 }
00148 }
00149
00150
00151 Foam::scalar Foam::forces::rho(const volScalarField& p) const
00152 {
00153 if (p.dimensions() == dimPressure)
00154 {
00155 return 1.0;
00156 }
00157 else
00158 {
00159 if (rhoName_ != "rhoInf")
00160 {
00161 FatalErrorIn("forces::rho(const volScalarField& p)")
00162 << "Dynamic pressure is expected but kinematic is provided."
00163 << exit(FatalError);
00164 }
00165
00166 return rhoRef_;
00167 }
00168 }
00169
00170
00171
00172
00173 Foam::forces::forces
00174 (
00175 const word& name,
00176 const objectRegistry& obr,
00177 const dictionary& dict,
00178 const bool loadFromFiles
00179 )
00180 :
00181 name_(name),
00182 obr_(obr),
00183 active_(true),
00184 log_(false),
00185 patchSet_(),
00186 pName_(word::null),
00187 UName_(word::null),
00188 rhoName_(word::null),
00189 directForceDensity_(false),
00190 fDName_(""),
00191 rhoRef_(VGREAT),
00192 pRef_(0),
00193 CofR_(vector::zero),
00194 forcesFilePtr_(NULL)
00195 {
00196
00197 if (!isA<fvMesh>(obr_))
00198 {
00199 active_ = false;
00200 WarningIn
00201 (
00202 "Foam::forces::forces"
00203 "("
00204 "const word&, "
00205 "const objectRegistry&, "
00206 "const dictionary&, "
00207 "const bool"
00208 ")"
00209 ) << "No fvMesh available, deactivating."
00210 << endl;
00211 }
00212
00213 read(dict);
00214 }
00215
00216
00217
00218
00219 Foam::forces::~forces()
00220 {}
00221
00222
00223
00224
00225 void Foam::forces::read(const dictionary& dict)
00226 {
00227 if (active_)
00228 {
00229 log_ = dict.lookupOrDefault<Switch>("log", false);
00230
00231 const fvMesh& mesh = refCast<const fvMesh>(obr_);
00232
00233 patchSet_ =
00234 mesh.boundaryMesh().patchSet(wordList(dict.lookup("patches")));
00235
00236 dict.readIfPresent("directForceDensity", directForceDensity_);
00237
00238 if (directForceDensity_)
00239 {
00240
00241 fDName_ = dict.lookupOrDefault<word>("fDName", "fD");
00242
00243
00244 if
00245 (
00246 !obr_.foundObject<volVectorField>(fDName_)
00247 )
00248 {
00249 active_ = false;
00250 WarningIn("void forces::read(const dictionary& dict)")
00251 << "Could not find " << fDName_ << " in database." << nl
00252 << " De-activating forces."
00253 << endl;
00254 }
00255 }
00256 else
00257 {
00258
00259 pName_ = dict.lookupOrDefault<word>("pName", "p");
00260 UName_ = dict.lookupOrDefault<word>("UName", "U");
00261 rhoName_ = dict.lookupOrDefault<word>("rhoName", "rho");
00262
00263
00264
00265 if
00266 (
00267 !obr_.foundObject<volVectorField>(UName_)
00268 || !obr_.foundObject<volScalarField>(pName_)
00269 || (
00270 rhoName_ != "rhoInf"
00271 && !obr_.foundObject<volScalarField>(rhoName_)
00272 )
00273 )
00274 {
00275 active_ = false;
00276
00277 WarningIn("void forces::read(const dictionary& dict)")
00278 << "Could not find " << UName_ << ", " << pName_;
00279
00280 if (rhoName_ != "rhoInf")
00281 {
00282 Info<< " or " << rhoName_;
00283 }
00284
00285 Info<< " in database." << nl << " De-activating forces."
00286 << endl;
00287 }
00288
00289
00290 rhoRef_ = readScalar(dict.lookup("rhoInf"));
00291
00292
00293 pRef_ = dict.lookupOrDefault<scalar>("pRef", 0.0);
00294 }
00295
00296
00297 CofR_ = dict.lookup("CofR");
00298 }
00299 }
00300
00301
00302 void Foam::forces::makeFile()
00303 {
00304
00305 if (forcesFilePtr_.empty())
00306 {
00307 if (debug)
00308 {
00309 Info<< "Creating forces file." << endl;
00310 }
00311
00312
00313 if (Pstream::master())
00314 {
00315 fileName forcesDir;
00316 word startTimeName =
00317 obr_.time().timeName(obr_.time().startTime().value());
00318
00319 if (Pstream::parRun())
00320 {
00321
00322
00323 forcesDir = obr_.time().path()/".."/name_/startTimeName;
00324 }
00325 else
00326 {
00327 forcesDir = obr_.time().path()/name_/startTimeName;
00328 }
00329
00330
00331 mkDir(forcesDir);
00332
00333
00334 forcesFilePtr_.reset(new OFstream(forcesDir/(type() + ".dat")));
00335
00336
00337 writeFileHeader();
00338 }
00339 }
00340 }
00341
00342
00343 void Foam::forces::writeFileHeader()
00344 {
00345 if (forcesFilePtr_.valid())
00346 {
00347 forcesFilePtr_()
00348 << "# Time" << tab
00349 << "forces(pressure, viscous) moment(pressure, viscous)"
00350 << endl;
00351 }
00352 }
00353
00354
00355 void Foam::forces::execute()
00356 {
00357
00358 }
00359
00360
00361 void Foam::forces::end()
00362 {
00363
00364 }
00365
00366
00367 void Foam::forces::write()
00368 {
00369 if (active_)
00370 {
00371
00372 makeFile();
00373
00374 forcesMoments fm = calcForcesMoment();
00375
00376 if (Pstream::master())
00377 {
00378 forcesFilePtr_() << obr_.time().value() << tab << fm << endl;
00379
00380 if (log_)
00381 {
00382 Info<< "forces output:" << nl
00383 << " forces(pressure, viscous)" << fm.first() << nl
00384 << " moment(pressure, viscous)" << fm.second() << nl
00385 << endl;
00386 }
00387 }
00388 }
00389 }
00390
00391
00392 Foam::forces::forcesMoments Foam::forces::calcForcesMoment() const
00393 {
00394 forcesMoments fm
00395 (
00396 pressureViscous(vector::zero, vector::zero),
00397 pressureViscous(vector::zero, vector::zero)
00398 );
00399
00400 if (directForceDensity_)
00401 {
00402 const volVectorField& fD = obr_.lookupObject<volVectorField>(fDName_);
00403
00404 const fvMesh& mesh = fD.mesh();
00405
00406 const surfaceVectorField::GeometricBoundaryField& Sfb =
00407 mesh.Sf().boundaryField();
00408
00409 forAllConstIter(labelHashSet, patchSet_, iter)
00410 {
00411 label patchi = iter.key();
00412
00413 vectorField Md = mesh.C().boundaryField()[patchi] - CofR_;
00414
00415 scalarField sA = mag(Sfb[patchi]);
00416
00417
00418 vectorField fN =
00419 Sfb[patchi]/sA
00420 *(
00421 Sfb[patchi] & fD.boundaryField()[patchi]
00422 );
00423
00424 fm.first().first() += sum(fN);
00425 fm.second().first() += sum(Md ^ fN);
00426
00427
00428 vectorField fT = sA*fD.boundaryField()[patchi] - fN;
00429
00430 fm.first().second() += sum(fT);
00431 fm.second().second() += sum(Md ^ fT);
00432 }
00433 }
00434 else
00435 {
00436 const volVectorField& U = obr_.lookupObject<volVectorField>(UName_);
00437 const volScalarField& p = obr_.lookupObject<volScalarField>(pName_);
00438
00439 const fvMesh& mesh = U.mesh();
00440
00441 const surfaceVectorField::GeometricBoundaryField& Sfb =
00442 mesh.Sf().boundaryField();
00443
00444 tmp<volSymmTensorField> tdevRhoReff = devRhoReff();
00445 const volSymmTensorField::GeometricBoundaryField& devRhoReffb
00446 = tdevRhoReff().boundaryField();
00447
00448
00449 scalar pRef = pRef_/rho(p);
00450
00451 forAllConstIter(labelHashSet, patchSet_, iter)
00452 {
00453 label patchi = iter.key();
00454
00455 vectorField Md = mesh.C().boundaryField()[patchi] - CofR_;
00456
00457 vectorField pf = Sfb[patchi]*(p.boundaryField()[patchi] - pRef);
00458
00459 fm.first().first() += rho(p)*sum(pf);
00460 fm.second().first() += rho(p)*sum(Md ^ pf);
00461
00462 vectorField vf = Sfb[patchi] & devRhoReffb[patchi];
00463
00464 fm.first().second() += sum(vf);
00465 fm.second().second() += sum(Md ^ vf);
00466 }
00467 }
00468
00469 reduce(fm, sumOp());
00470
00471 return fm;
00472 }
00473
00474
00475