mirror of
https://develop.openfoam.com/Development/openfoam.git
synced 2025-11-28 03:28:01 +00:00
ENH: forces/forceCoeffs: refactor function objects
- enables runtime selection of operand coefficients by 'coefficients' entry - removes binning - now handled using the new 'binField' FO Co-authored-by: Kutalmis Bercin <kutalmis.bercin@esi-group.com>
This commit is contained in:
committed by
Andrew Heather
parent
78c984f8f4
commit
6a4f7c9c68
@ -6,7 +6,7 @@
|
|||||||
\\/ M anipulation |
|
\\/ M anipulation |
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
Copyright (C) 2011-2016 OpenFOAM Foundation
|
Copyright (C) 2011-2016 OpenFOAM Foundation
|
||||||
Copyright (C) 2015-2020 OpenCFD Ltd.
|
Copyright (C) 2015-2022 OpenCFD Ltd.
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
License
|
License
|
||||||
This file is part of OpenFOAM.
|
This file is part of OpenFOAM.
|
||||||
@ -50,47 +50,121 @@ namespace functionObjects
|
|||||||
|
|
||||||
// * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * //
|
// * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * //
|
||||||
|
|
||||||
void Foam::functionObjects::forceCoeffs::createFiles()
|
void Foam::functionObjects::forceCoeffs::initialise()
|
||||||
{
|
{
|
||||||
// Note: Only possible to create bin files after bins have been initialised
|
if (initialised_)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (writeToFile() && !coeffFilePtr_)
|
initialised_ = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Foam::functionObjects::forceCoeffs::reset()
|
||||||
|
{
|
||||||
|
Cf_.reset();
|
||||||
|
Cm_.reset();
|
||||||
|
|
||||||
|
forceCoeff_ == dimensionedVector(dimless, Zero);
|
||||||
|
momentCoeff_ == dimensionedVector(dimless, Zero);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Foam::HashTable<Foam::functionObjects::forceCoeffs::coeffDesc>
|
||||||
|
Foam::functionObjects::forceCoeffs::selectCoeffs() const
|
||||||
|
{
|
||||||
|
HashTable<coeffDesc> coeffs(16);
|
||||||
|
|
||||||
|
coeffs.insert("Cd", coeffDesc("Drag force", "Cd", 0, 0));
|
||||||
|
coeffs.insert("Cs", coeffDesc("Side force", "Cs", 1, 2));
|
||||||
|
coeffs.insert("Cl", coeffDesc("Lift force", "Cl", 2, 1));
|
||||||
|
|
||||||
|
// Add front/rear options
|
||||||
|
const auto frontRearCoeffs(coeffs);
|
||||||
|
forAllConstIters(frontRearCoeffs, iter)
|
||||||
|
{
|
||||||
|
const auto& fr = iter.val();
|
||||||
|
coeffs.insert(fr.frontName(), fr.front());
|
||||||
|
coeffs.insert(fr.rearName(), fr.rear());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add moments
|
||||||
|
coeffs.insert("CmRoll", coeffDesc("Roll moment", "CmRoll", 0, -1));
|
||||||
|
coeffs.insert("CmPitch", coeffDesc("Pitch moment", "CmPitch", 1, -1));
|
||||||
|
coeffs.insert("CmYaw", coeffDesc("Yaw moment", "CmYaw", 2, -1));
|
||||||
|
|
||||||
|
return coeffs;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Foam::functionObjects::forceCoeffs::calcForceCoeffs()
|
||||||
|
{
|
||||||
|
// Calculate scaling factors
|
||||||
|
const scalar pDyn = 0.5*rhoRef_*sqr(magUInf_);
|
||||||
|
const dimensionedScalar forceScaling
|
||||||
|
(
|
||||||
|
dimless/dimForce,
|
||||||
|
scalar(1)/(Aref_*pDyn + SMALL)
|
||||||
|
);
|
||||||
|
|
||||||
|
const auto& coordSys = coordSysPtr_();
|
||||||
|
|
||||||
|
// Calculate force coefficients
|
||||||
|
forceCoeff_ = forceScaling*force_;
|
||||||
|
|
||||||
|
Cf_.reset
|
||||||
|
(
|
||||||
|
forceScaling.value()*coordSys.localVector(sumPatchForcesV_),
|
||||||
|
forceScaling.value()*coordSys.localVector(sumPatchForcesP_),
|
||||||
|
forceScaling.value()*coordSys.localVector(sumInternalForces_)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Foam::functionObjects::forceCoeffs::calcMomentCoeffs()
|
||||||
|
{
|
||||||
|
// Calculate scaling factors
|
||||||
|
const scalar pDyn = 0.5*rhoRef_*sqr(magUInf_);
|
||||||
|
const dimensionedScalar momentScaling
|
||||||
|
(
|
||||||
|
dimless/(dimForce*dimLength),
|
||||||
|
scalar(1)/(Aref_*pDyn*lRef_ + SMALL)
|
||||||
|
);
|
||||||
|
|
||||||
|
const auto& coordSys = coordSysPtr_();
|
||||||
|
|
||||||
|
// Calculate moment coefficients
|
||||||
|
momentCoeff_ = momentScaling*moment_;
|
||||||
|
|
||||||
|
Cm_.reset
|
||||||
|
(
|
||||||
|
momentScaling.value()*coordSys.localVector(sumPatchMomentsP_),
|
||||||
|
momentScaling.value()*coordSys.localVector(sumPatchMomentsV_),
|
||||||
|
momentScaling.value()*coordSys.localVector(sumInternalMoments_)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Foam::functionObjects::forceCoeffs::createIntegratedDataFile()
|
||||||
|
{
|
||||||
|
if (!coeffFilePtr_.valid())
|
||||||
{
|
{
|
||||||
coeffFilePtr_ = createFile("coefficient");
|
coeffFilePtr_ = createFile("coefficient");
|
||||||
writeIntegratedHeader("Coefficients", coeffFilePtr_());
|
writeIntegratedDataFileHeader("Coefficients", coeffFilePtr_());
|
||||||
|
|
||||||
if (nBin_ > 1)
|
|
||||||
{
|
|
||||||
CdBinFilePtr_ = createFile("CdBin");
|
|
||||||
writeBinHeader("Drag coefficient bins", CdBinFilePtr_());
|
|
||||||
|
|
||||||
CsBinFilePtr_ = createFile("CsBin");
|
|
||||||
writeBinHeader("Side coefficient bins", CsBinFilePtr_());
|
|
||||||
|
|
||||||
ClBinFilePtr_ = createFile("ClBin");
|
|
||||||
writeBinHeader("Lift coefficient bins", ClBinFilePtr_());
|
|
||||||
|
|
||||||
CmRollBinFilePtr_ = createFile("CmRollBin");
|
|
||||||
writeBinHeader("Roll moment coefficient bins", CmRollBinFilePtr_());
|
|
||||||
|
|
||||||
CmPitchBinFilePtr_ = createFile("CmPitchBin");
|
|
||||||
writeBinHeader("Moment coefficient bins", CmPitchBinFilePtr_());
|
|
||||||
|
|
||||||
CmYawBinFilePtr_ = createFile("CmYawBin");
|
|
||||||
writeBinHeader("Yaw moment coefficient bins", CmYawBinFilePtr_());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void Foam::functionObjects::forceCoeffs::writeIntegratedHeader
|
void Foam::functionObjects::forceCoeffs::writeIntegratedDataFileHeader
|
||||||
(
|
(
|
||||||
const word& header,
|
const word& header,
|
||||||
Ostream& os
|
OFstream& os
|
||||||
) const
|
) const
|
||||||
{
|
{
|
||||||
const auto& coordSys = coordSysPtr_();
|
const auto& coordSys = coordSysPtr_();
|
||||||
writeHeader(os, "Force coefficients");
|
|
||||||
|
writeHeader(os, "Force and moment coefficients");
|
||||||
writeHeaderValue(os, "dragDir", coordSys.e1());
|
writeHeaderValue(os, "dragDir", coordSys.e1());
|
||||||
writeHeaderValue(os, "sideDir", coordSys.e2());
|
writeHeaderValue(os, "sideDir", coordSys.e2());
|
||||||
writeHeaderValue(os, "liftDir", coordSys.e3());
|
writeHeaderValue(os, "liftDir", coordSys.e3());
|
||||||
@ -103,128 +177,38 @@ void Foam::functionObjects::forceCoeffs::writeIntegratedHeader
|
|||||||
writeHeaderValue(os, "CofR", coordSys.origin());
|
writeHeaderValue(os, "CofR", coordSys.origin());
|
||||||
writeHeader(os, "");
|
writeHeader(os, "");
|
||||||
writeCommented(os, "Time");
|
writeCommented(os, "Time");
|
||||||
writeTabbed(os, "Cd");
|
|
||||||
writeTabbed(os, "Cs");
|
|
||||||
writeTabbed(os, "Cl");
|
|
||||||
writeTabbed(os, "CmRoll");
|
|
||||||
writeTabbed(os, "CmPitch");
|
|
||||||
writeTabbed(os, "CmYaw");
|
|
||||||
writeTabbed(os, "Cd(f)");
|
|
||||||
writeTabbed(os, "Cd(r)");
|
|
||||||
writeTabbed(os, "Cs(f)");
|
|
||||||
writeTabbed(os, "Cs(r)");
|
|
||||||
writeTabbed(os, "Cl(f)");
|
|
||||||
writeTabbed(os, "Cl(r)");
|
|
||||||
os << endl;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
for (const auto& iter : coeffs_.sorted())
|
||||||
void Foam::functionObjects::forceCoeffs::writeBinHeader
|
|
||||||
(
|
|
||||||
const word& header,
|
|
||||||
Ostream& os
|
|
||||||
) const
|
|
||||||
{
|
|
||||||
writeHeader(os, header);
|
|
||||||
writeHeaderValue(os, "bins", nBin_);
|
|
||||||
writeHeaderValue(os, "start", binMin_);
|
|
||||||
writeHeaderValue(os, "delta", binDx_);
|
|
||||||
writeHeaderValue(os, "direction", binDir_);
|
|
||||||
|
|
||||||
vectorField binPoints(nBin_);
|
|
||||||
writeCommented(os, "x co-ords :");
|
|
||||||
forAll(binPoints, pointi)
|
|
||||||
{
|
{
|
||||||
binPoints[pointi] = (binMin_ + (pointi + 1)*binDx_)*binDir_;
|
const auto& coeff = iter.val();
|
||||||
os << tab << binPoints[pointi].x();
|
|
||||||
}
|
|
||||||
os << nl;
|
|
||||||
|
|
||||||
writeCommented(os, "y co-ords :");
|
if (!coeff.active_) continue;
|
||||||
forAll(binPoints, pointi)
|
|
||||||
{
|
|
||||||
os << tab << binPoints[pointi].y();
|
|
||||||
}
|
|
||||||
os << nl;
|
|
||||||
|
|
||||||
writeCommented(os, "z co-ords :");
|
writeTabbed(os, coeff.name_);
|
||||||
forAll(binPoints, pointi)
|
|
||||||
{
|
|
||||||
os << tab << binPoints[pointi].z();
|
|
||||||
}
|
|
||||||
os << nl;
|
|
||||||
|
|
||||||
writeHeader(os, "");
|
|
||||||
writeCommented(os, "Time");
|
|
||||||
|
|
||||||
for (label j = 0; j < nBin_; ++j)
|
|
||||||
{
|
|
||||||
const word jn(Foam::name(j) + ':');
|
|
||||||
writeTabbed(os, jn + "total");
|
|
||||||
writeTabbed(os, jn + "pressure");
|
|
||||||
writeTabbed(os, jn + "viscous");
|
|
||||||
|
|
||||||
if (porosity_)
|
|
||||||
{
|
|
||||||
writeTabbed(os, jn + "porous");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
os << endl;
|
os << endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void Foam::functionObjects::forceCoeffs::writeIntegratedData
|
void Foam::functionObjects::forceCoeffs::writeIntegratedDataFile()
|
||||||
(
|
|
||||||
const word& title,
|
|
||||||
const List<Field<scalar>>& coeff
|
|
||||||
) const
|
|
||||||
{
|
{
|
||||||
if (!log)
|
OFstream& os = coeffFilePtr_();
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const scalar pressure = sum(coeff[0]);
|
|
||||||
const scalar viscous = sum(coeff[1]);
|
|
||||||
const scalar porous = sum(coeff[2]);
|
|
||||||
const scalar total = pressure + viscous + porous;
|
|
||||||
|
|
||||||
Info<< " " << title << " : " << total << token::TAB
|
|
||||||
<< '('
|
|
||||||
<< "pressure: " << pressure << token::TAB
|
|
||||||
<< "viscous: " << viscous;
|
|
||||||
|
|
||||||
if (porosity_)
|
|
||||||
{
|
|
||||||
Info<< token::TAB << "porous: " << porous;
|
|
||||||
}
|
|
||||||
|
|
||||||
Info<< ')' << endl;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void Foam::functionObjects::forceCoeffs::writeBinData
|
|
||||||
(
|
|
||||||
const List<Field<scalar>> coeffs,
|
|
||||||
Ostream& os
|
|
||||||
) const
|
|
||||||
{
|
|
||||||
writeCurrentTime(os);
|
writeCurrentTime(os);
|
||||||
|
|
||||||
for (label bini = 0; bini < nBin_; ++bini)
|
for (const auto& iter : coeffs_.sorted())
|
||||||
{
|
{
|
||||||
scalar total = coeffs[0][bini] + coeffs[1][bini] + coeffs[2][bini];
|
const auto& coeff = iter.val();
|
||||||
|
|
||||||
os << tab << total << tab << coeffs[0][bini] << tab << coeffs[1][bini];
|
if (!coeff.active_) continue;
|
||||||
|
|
||||||
if (porosity_)
|
const vector coeffValue = coeff.value(Cf_, Cm_);
|
||||||
{
|
|
||||||
os << tab << coeffs[2][bini];
|
os << tab << (coeffValue.x() + coeffValue.y() + coeffValue.z());
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
os << endl;
|
coeffFilePtr_() << endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -239,16 +223,39 @@ Foam::functionObjects::forceCoeffs::forceCoeffs
|
|||||||
)
|
)
|
||||||
:
|
:
|
||||||
forces(name, runTime, dict, false),
|
forces(name, runTime, dict, false),
|
||||||
|
Cf_(),
|
||||||
|
Cm_(),
|
||||||
|
forceCoeff_
|
||||||
|
(
|
||||||
|
IOobject
|
||||||
|
(
|
||||||
|
"forceCoeff", // scopedName() is not available at ctor level
|
||||||
|
mesh_.time().timeName(),
|
||||||
|
mesh_,
|
||||||
|
IOobject::NO_READ,
|
||||||
|
IOobject::NO_WRITE
|
||||||
|
),
|
||||||
|
mesh_,
|
||||||
|
dimensionedVector(dimless, Zero)
|
||||||
|
),
|
||||||
|
momentCoeff_
|
||||||
|
(
|
||||||
|
IOobject
|
||||||
|
(
|
||||||
|
"momentCoeff",
|
||||||
|
mesh_.time().timeName(),
|
||||||
|
mesh_,
|
||||||
|
IOobject::NO_READ,
|
||||||
|
IOobject::NO_WRITE
|
||||||
|
),
|
||||||
|
mesh_,
|
||||||
|
dimensionedVector(dimless, Zero)
|
||||||
|
),
|
||||||
|
coeffFilePtr_(),
|
||||||
magUInf_(Zero),
|
magUInf_(Zero),
|
||||||
lRef_(Zero),
|
lRef_(Zero),
|
||||||
Aref_(Zero),
|
Aref_(Zero),
|
||||||
coeffFilePtr_(),
|
initialised_(false)
|
||||||
CdBinFilePtr_(),
|
|
||||||
CsBinFilePtr_(),
|
|
||||||
ClBinFilePtr_(),
|
|
||||||
CmRollBinFilePtr_(),
|
|
||||||
CmPitchBinFilePtr_(),
|
|
||||||
CmYawBinFilePtr_()
|
|
||||||
{
|
{
|
||||||
if (readFields)
|
if (readFields)
|
||||||
{
|
{
|
||||||
@ -263,230 +270,139 @@ Foam::functionObjects::forceCoeffs::forceCoeffs
|
|||||||
|
|
||||||
bool Foam::functionObjects::forceCoeffs::read(const dictionary& dict)
|
bool Foam::functionObjects::forceCoeffs::read(const dictionary& dict)
|
||||||
{
|
{
|
||||||
forces::read(dict);
|
if (!forces::read(dict))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
// Free stream velocity magnitude
|
initialised_ = false;
|
||||||
|
|
||||||
|
// Reference scales
|
||||||
dict.readEntry("magUInf", magUInf_);
|
dict.readEntry("magUInf", magUInf_);
|
||||||
|
dict.readEntry("lRef", lRef_);
|
||||||
|
dict.readEntry("Aref", Aref_);
|
||||||
|
|
||||||
// If case is compressible we must read rhoInf (store in rhoRef_) to
|
// If case is compressible we must read rhoInf
|
||||||
// calculate the reference dynamic pressure
|
// (stored in rhoRef_) to calculate the reference dynamic pressure
|
||||||
// Note: for incompressible, rhoRef_ is already initialised
|
// Note: for incompressible, rhoRef_ is already initialised to 1
|
||||||
if (rhoName_ != "rhoInf")
|
if (rhoName_ != "rhoInf")
|
||||||
{
|
{
|
||||||
dict.readEntry("rhoInf", rhoRef_);
|
dict.readEntry("rhoInf", rhoRef_);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Reference length and area scales
|
Info<< " magUInf: " << magUInf_ << nl
|
||||||
dict.readEntry("lRef", lRef_);
|
<< " lRef : " << lRef_ << nl
|
||||||
dict.readEntry("Aref", Aref_);
|
<< " Aref : " << Aref_ << nl
|
||||||
|
<< " rhoInf : " << rhoRef_ << endl;
|
||||||
|
|
||||||
if (writeFields_)
|
if (min(magUInf_, rhoRef_) < SMALL || min(lRef_, Aref_) < SMALL)
|
||||||
{
|
{
|
||||||
volVectorField* forceCoeffPtr
|
FatalIOErrorInFunction(dict)
|
||||||
(
|
<< "Non-zero values are required for reference scales"
|
||||||
new volVectorField
|
<< exit(FatalIOError);
|
||||||
(
|
|
||||||
IOobject
|
|
||||||
(
|
|
||||||
scopedName("forceCoeff"),
|
|
||||||
mesh_.time().timeName(),
|
|
||||||
mesh_,
|
|
||||||
IOobject::NO_READ,
|
|
||||||
IOobject::NO_WRITE
|
|
||||||
),
|
|
||||||
mesh_,
|
|
||||||
dimensionedVector(dimless, Zero)
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
mesh_.objectRegistry::store(forceCoeffPtr);
|
return false;
|
||||||
|
|
||||||
volVectorField* momentCoeffPtr
|
|
||||||
(
|
|
||||||
new volVectorField
|
|
||||||
(
|
|
||||||
IOobject
|
|
||||||
(
|
|
||||||
scopedName("momentCoeff"),
|
|
||||||
mesh_.time().timeName(),
|
|
||||||
mesh_,
|
|
||||||
IOobject::NO_READ,
|
|
||||||
IOobject::NO_WRITE
|
|
||||||
),
|
|
||||||
mesh_,
|
|
||||||
dimensionedVector(dimless, Zero)
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
mesh_.objectRegistry::store(momentCoeffPtr);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!dict.found("coefficients"))
|
||||||
|
{
|
||||||
|
Info<< " Selecting all coefficients" << nl;
|
||||||
|
|
||||||
|
coeffs_ = selectCoeffs();
|
||||||
|
|
||||||
|
for (auto& iter : coeffs_.sorted())
|
||||||
|
{
|
||||||
|
auto& coeff = iter.val();
|
||||||
|
coeff.active_ = true;
|
||||||
|
Info<< " - " << coeff << nl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
const wordHashSet coeffs(dict.get<wordHashSet>("coefficients"));
|
||||||
|
|
||||||
|
coeffs_ = selectCoeffs();
|
||||||
|
|
||||||
|
Info<< " Selecting coefficients:" << nl;
|
||||||
|
|
||||||
|
for (const word& key : coeffs)
|
||||||
|
{
|
||||||
|
auto coeffIter = coeffs_.find(key);
|
||||||
|
|
||||||
|
if (!coeffIter.good())
|
||||||
|
{
|
||||||
|
FatalIOErrorInFunction(dict)
|
||||||
|
<< "Unknown coefficient type " << key
|
||||||
|
<< " . Valid entries are : " << coeffs_.sortedToc()
|
||||||
|
<< exit(FatalIOError);
|
||||||
|
}
|
||||||
|
auto& coeff = coeffIter.val();
|
||||||
|
coeff.active_ = true;
|
||||||
|
Info<< " - " << coeff << nl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
forceCoeff_.rename(scopedName("forceCoeff"));
|
||||||
|
momentCoeff_.rename(scopedName("momentCoeff"));
|
||||||
|
|
||||||
|
Info<< endl;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
bool Foam::functionObjects::forceCoeffs::execute()
|
bool Foam::functionObjects::forceCoeffs::execute()
|
||||||
{
|
{
|
||||||
forces::calcForcesMoment();
|
forces::calcForcesMoments();
|
||||||
|
|
||||||
createFiles();
|
initialise();
|
||||||
|
|
||||||
// Storage for pressure, viscous and porous contributions to coeffs
|
reset();
|
||||||
List<Field<scalar>> dragCoeffs(3);
|
|
||||||
List<Field<scalar>> sideCoeffs(3);
|
|
||||||
List<Field<scalar>> liftCoeffs(3);
|
|
||||||
List<Field<scalar>> rollMomentCoeffs(3);
|
|
||||||
List<Field<scalar>> pitchMomentCoeffs(3);
|
|
||||||
List<Field<scalar>> yawMomentCoeffs(3);
|
|
||||||
|
|
||||||
forAll(liftCoeffs, i)
|
Log << type() << " " << name() << " write:" << nl
|
||||||
|
<< " " << "Coefficient"
|
||||||
|
<< tab << "Total"
|
||||||
|
<< tab << "Pressure"
|
||||||
|
<< tab << "Viscous"
|
||||||
|
<< tab << "Internal"
|
||||||
|
<< nl;
|
||||||
|
|
||||||
|
calcForceCoeffs();
|
||||||
|
|
||||||
|
calcMomentCoeffs();
|
||||||
|
|
||||||
|
auto logValues = [](const word& name, const vector& coeff, Ostream& os)
|
||||||
{
|
{
|
||||||
dragCoeffs[i].setSize(nBin_);
|
os << " " << name << ":"
|
||||||
sideCoeffs[i].setSize(nBin_);
|
<< tab << coeff.x() + coeff.y() + coeff.z()
|
||||||
liftCoeffs[i].setSize(nBin_);
|
<< tab << coeff.x()
|
||||||
rollMomentCoeffs[i].setSize(nBin_);
|
<< tab << coeff.y()
|
||||||
pitchMomentCoeffs[i].setSize(nBin_);
|
<< tab << coeff.z()
|
||||||
yawMomentCoeffs[i].setSize(nBin_);
|
<< nl;
|
||||||
}
|
};
|
||||||
|
|
||||||
// Calculate coefficients
|
// Always setting all results
|
||||||
scalar CdTot = 0;
|
for (const auto& iter : coeffs_.sorted())
|
||||||
scalar CsTot = 0;
|
|
||||||
scalar ClTot = 0;
|
|
||||||
scalar CmRollTot = 0;
|
|
||||||
scalar CmPitchTot = 0;
|
|
||||||
scalar CmYawTot = 0;
|
|
||||||
|
|
||||||
const scalar pDyn = 0.5*rhoRef_*sqr(magUInf_);
|
|
||||||
|
|
||||||
// Avoid divide by zero in 2D cases
|
|
||||||
const scalar momentScaling = 1.0/(Aref_*pDyn*lRef_ + SMALL);
|
|
||||||
const scalar forceScaling = 1.0/(Aref_*pDyn + SMALL);
|
|
||||||
|
|
||||||
const auto& coordSys = coordSysPtr_();
|
|
||||||
|
|
||||||
forAll(liftCoeffs, i)
|
|
||||||
{
|
{
|
||||||
const Field<vector> localForce(coordSys.localVector(force_[i]));
|
const word& coeffName = iter.key();
|
||||||
const Field<vector> localMoment(coordSys.localVector(moment_[i]));
|
const auto& coeff = iter.val();
|
||||||
|
|
||||||
dragCoeffs[i] = forceScaling*(localForce.component(0));
|
// Vectors for x:pressure, y:viscous, z:internal
|
||||||
sideCoeffs[i] = forceScaling*(localForce.component(1));
|
const vector coeffValue = coeff.value(Cf_, Cm_);
|
||||||
liftCoeffs[i] = forceScaling*(localForce.component(2));
|
|
||||||
rollMomentCoeffs[i] = momentScaling*(localMoment.component(0));
|
|
||||||
pitchMomentCoeffs[i] = momentScaling*(localMoment.component(1));
|
|
||||||
yawMomentCoeffs[i] = momentScaling*(localMoment.component(2));
|
|
||||||
|
|
||||||
CdTot += sum(dragCoeffs[i]);
|
if (log && coeff.active_)
|
||||||
CsTot += sum(sideCoeffs[i]);
|
|
||||||
ClTot += sum(liftCoeffs[i]);
|
|
||||||
CmRollTot += sum(rollMomentCoeffs[i]);
|
|
||||||
CmPitchTot += sum(pitchMomentCoeffs[i]);
|
|
||||||
CmYawTot += sum(yawMomentCoeffs[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Single contributions to the front and rear
|
|
||||||
const scalar CdfTot = 0.5*CdTot + CmRollTot;
|
|
||||||
const scalar CdrTot = 0.5*CdTot - CmRollTot;
|
|
||||||
const scalar CsfTot = 0.5*CsTot + CmYawTot;
|
|
||||||
const scalar CsrTot = 0.5*CsTot - CmYawTot;
|
|
||||||
const scalar ClfTot = 0.5*ClTot + CmPitchTot;
|
|
||||||
const scalar ClrTot = 0.5*ClTot - CmPitchTot;
|
|
||||||
|
|
||||||
Log << type() << " " << name() << " execute:" << nl
|
|
||||||
<< " Coefficients" << nl;
|
|
||||||
|
|
||||||
writeIntegratedData("Cd", dragCoeffs);
|
|
||||||
writeIntegratedData("Cs", sideCoeffs);
|
|
||||||
writeIntegratedData("Cl", liftCoeffs);
|
|
||||||
writeIntegratedData("CmRoll", rollMomentCoeffs);
|
|
||||||
writeIntegratedData("CmPitch", pitchMomentCoeffs);
|
|
||||||
writeIntegratedData("CmYaw", yawMomentCoeffs);
|
|
||||||
|
|
||||||
Log << " Cd(f) : " << CdfTot << nl
|
|
||||||
<< " Cd(r) : " << CdrTot << nl;
|
|
||||||
|
|
||||||
Log << " Cs(f) : " << CsfTot << nl
|
|
||||||
<< " Cs(r) : " << CsrTot << nl;
|
|
||||||
|
|
||||||
Log << " Cl(f) : " << ClfTot << nl
|
|
||||||
<< " Cl(r) : " << ClrTot << nl;
|
|
||||||
|
|
||||||
if (writeToFile())
|
|
||||||
{
|
|
||||||
writeCurrentTime(coeffFilePtr_());
|
|
||||||
coeffFilePtr_()
|
|
||||||
<< tab << CdTot << tab << CsTot << tab << ClTot
|
|
||||||
<< tab << CmRollTot << tab << CmPitchTot << tab << CmYawTot
|
|
||||||
<< tab << CdfTot << tab << CdrTot
|
|
||||||
<< tab << CsfTot << tab << CsrTot
|
|
||||||
<< tab << ClfTot << tab << ClrTot << endl;
|
|
||||||
|
|
||||||
if (nBin_ > 1)
|
|
||||||
{
|
{
|
||||||
if (binCumulative_)
|
logValues(coeffName, coeffValue, Info);
|
||||||
{
|
|
||||||
forAll(liftCoeffs, i)
|
|
||||||
{
|
|
||||||
for (label bini = 1; bini < nBin_; ++bini)
|
|
||||||
{
|
|
||||||
dragCoeffs[i][bini] += dragCoeffs[i][bini-1];
|
|
||||||
sideCoeffs[i][bini] += sideCoeffs[i][bini-1];
|
|
||||||
liftCoeffs[i][bini] += liftCoeffs[i][bini-1];
|
|
||||||
rollMomentCoeffs[i][bini] +=
|
|
||||||
rollMomentCoeffs[i][bini-1];
|
|
||||||
pitchMomentCoeffs[i][bini] +=
|
|
||||||
pitchMomentCoeffs[i][bini-1];
|
|
||||||
yawMomentCoeffs[i][bini] += yawMomentCoeffs[i][bini-1];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
writeBinData(dragCoeffs, CdBinFilePtr_());
|
|
||||||
writeBinData(sideCoeffs, CsBinFilePtr_());
|
|
||||||
writeBinData(liftCoeffs, ClBinFilePtr_());
|
|
||||||
writeBinData(rollMomentCoeffs, CmRollBinFilePtr_());
|
|
||||||
writeBinData(pitchMomentCoeffs, CmPitchBinFilePtr_());
|
|
||||||
writeBinData(yawMomentCoeffs, CmYawBinFilePtr_());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
setResult(coeffName, coeffValue.x() + coeffValue.y() + coeffValue.z());
|
||||||
|
setResult(coeffName & "pressure", coeffValue.x());
|
||||||
|
setResult(coeffName & "viscous", coeffValue.y());
|
||||||
|
setResult(coeffName & "internal", coeffValue.z());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Write state/results information
|
Log << endl;
|
||||||
{
|
|
||||||
setResult("Cd", CdTot);
|
|
||||||
setResult("Cs", CsTot);
|
|
||||||
setResult("Cl", ClTot);
|
|
||||||
setResult("CmRoll", CmRollTot);
|
|
||||||
setResult("CmPitch", CmPitchTot);
|
|
||||||
setResult("CmYaw", CmYawTot);
|
|
||||||
setResult("Cd(f)", CdfTot);
|
|
||||||
setResult("Cd(r)", CdrTot);
|
|
||||||
setResult("Cs(f)", CsfTot);
|
|
||||||
setResult("Cs(r)", CsrTot);
|
|
||||||
setResult("Cl(f)", ClfTot);
|
|
||||||
setResult("Cl(r)", ClrTot);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (writeFields_)
|
|
||||||
{
|
|
||||||
const volVectorField& force =
|
|
||||||
lookupObject<volVectorField>(scopedName("force"));
|
|
||||||
|
|
||||||
const volVectorField& moment =
|
|
||||||
lookupObject<volVectorField>(scopedName("moment"));
|
|
||||||
|
|
||||||
volVectorField& forceCoeff =
|
|
||||||
lookupObjectRef<volVectorField>(scopedName("forceCoeff"));
|
|
||||||
|
|
||||||
volVectorField& momentCoeff =
|
|
||||||
lookupObjectRef<volVectorField>(scopedName("momentCoeff"));
|
|
||||||
|
|
||||||
dimensionedScalar f0("f0", dimForce, Aref_*pDyn);
|
|
||||||
dimensionedScalar m0("m0", dimForce*dimLength, Aref_*lRef_*pDyn);
|
|
||||||
|
|
||||||
forceCoeff == force/f0;
|
|
||||||
momentCoeff == moment/m0;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -494,18 +410,23 @@ bool Foam::functionObjects::forceCoeffs::execute()
|
|||||||
|
|
||||||
bool Foam::functionObjects::forceCoeffs::write()
|
bool Foam::functionObjects::forceCoeffs::write()
|
||||||
{
|
{
|
||||||
|
if (writeToFile())
|
||||||
|
{
|
||||||
|
Log << " writing force and moment coefficient files." << endl;
|
||||||
|
|
||||||
|
createIntegratedDataFile();
|
||||||
|
|
||||||
|
writeIntegratedDataFile();
|
||||||
|
}
|
||||||
|
|
||||||
if (writeFields_)
|
if (writeFields_)
|
||||||
{
|
{
|
||||||
const volVectorField& forceCoeff =
|
forceCoeff_.write();
|
||||||
lookupObject<volVectorField>(scopedName("forceCoeff"));
|
momentCoeff_.write();
|
||||||
|
|
||||||
const volVectorField& momentCoeff =
|
|
||||||
lookupObject<volVectorField>(scopedName("momentCoeff"));
|
|
||||||
|
|
||||||
forceCoeff.write();
|
|
||||||
momentCoeff.write();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Log << endl;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -6,7 +6,7 @@
|
|||||||
\\/ M anipulation |
|
\\/ M anipulation |
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
Copyright (C) 2011-2016 OpenFOAM Foundation
|
Copyright (C) 2011-2016 OpenFOAM Foundation
|
||||||
Copyright (C) 2019-2020 OpenCFD Ltd.
|
Copyright (C) 2019-2022 OpenCFD Ltd.
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
License
|
License
|
||||||
This file is part of OpenFOAM.
|
This file is part of OpenFOAM.
|
||||||
@ -31,142 +31,207 @@ Group
|
|||||||
grpForcesFunctionObjects
|
grpForcesFunctionObjects
|
||||||
|
|
||||||
Description
|
Description
|
||||||
Extends the \c forces functionObject by providing coefficients for:
|
Computes force and moment coefficients over a given
|
||||||
- drag, side and lift forces (Cd, Cs, and Cl)
|
list of patches, and optionally over given porous zones.
|
||||||
- roll, pitch and yaw moments (CmRoll, CmPitch, and CmYaw)
|
The following coefficients can be selected and output:
|
||||||
- front and rear axle force contributions (C(f) and C(r)) wherein
|
|
||||||
|
|
||||||
\verbatim
|
\verbatim
|
||||||
Cd(f/r) = 0.5*Cd \pm CmRoll
|
Cd | Drag coefficient
|
||||||
Cs(f/r) = 0.5*Cs \pm CmYaw
|
Cs | Side-force coefficient
|
||||||
Cl(f/r) = 0.5*Cl \pm CmPitch
|
Cl | Lift coefficient
|
||||||
|
CmRoll | Roll-moment coefficient
|
||||||
|
CmPitch | Pitch-moment coefficient
|
||||||
|
CmYaw | Yaw-moment coefficient
|
||||||
\endverbatim
|
\endverbatim
|
||||||
|
|
||||||
The data can optionally be output into bins, defined in a given direction.
|
The force coefficients can also be optionally output
|
||||||
|
in terms of their front and rear axle constituents:
|
||||||
|
\verbatim
|
||||||
|
Cd{f,r} = 0.5*Cd {+,-} CmRoll
|
||||||
|
Cs{f,r} = 0.5*Cs {+,-} CmYaw
|
||||||
|
Cl{f,r} = 0.5*Cl {+,-} CmPitch
|
||||||
|
\endverbatim
|
||||||
|
where \c f and \c r represent front and rear axles, respectively.
|
||||||
|
|
||||||
The binned data provides the total and consitituent components per bin:
|
Force and moment coefficients are output
|
||||||
- total coefficient
|
in their total and constituent components:
|
||||||
- pressure coefficient contribution
|
- total force and moment coefficients
|
||||||
- viscous coefficient contribution
|
- pressure contributions
|
||||||
- porous coefficient contribution
|
- viscous contributions
|
||||||
|
- porous resistance contributions (optional)
|
||||||
|
|
||||||
Data is written into multiple files in the
|
Force and moment coefficients can be computed and output in:
|
||||||
postProcessing/\<functionObjectName\> directory:
|
- the global Cartesian coordinate system (default)
|
||||||
- coefficient.dat : integrated coefficients over all geometries
|
- a user-defined Cartesian coordinate system
|
||||||
- CdBin.dat : drag coefficient bins
|
|
||||||
- CsBin.dat : side coefficient bins
|
Operands:
|
||||||
- ClBin.dat : lift coefficient bins
|
\table
|
||||||
- CmRollBin.dat : roll moment coefficient bins
|
Operand | Type | Location
|
||||||
- CmPitchBin.dat : pitch moment coefficient bins
|
input | - | -
|
||||||
- CmYawBin.dat : yaw moment coefficient bins
|
output file | dat | postProcessing/\<FO\>/\<time\>/\<file\>s
|
||||||
|
output field | volVectorField | \<time\>/\<outField\>s
|
||||||
|
\endtable
|
||||||
|
|
||||||
|
where \c \<file\>s:
|
||||||
|
\verbatim
|
||||||
|
coefficient.dat | Integrated coefficients over all patches
|
||||||
|
\endverbatim
|
||||||
|
|
||||||
|
where \c \<outField\>s:
|
||||||
|
\verbatim
|
||||||
|
<namePrefix>:forceCoeff | Force coefficient field
|
||||||
|
<namePrefix>:momentCoeff | Moment coefficient field
|
||||||
|
\endverbatim
|
||||||
|
|
||||||
Usage
|
Usage
|
||||||
Example of function object specification:
|
Minimal example by using \c system/controlDict.functions:
|
||||||
\verbatim
|
\verbatim
|
||||||
forceCoeffs1
|
forceCoeffs1
|
||||||
{
|
{
|
||||||
type forceCoeffs;
|
// Mandatory entries
|
||||||
libs (forces);
|
type forceCoeffs;
|
||||||
|
libs (forces);
|
||||||
|
patches (<wordRes>); // (wall1 "(wall2|wall3)");
|
||||||
|
magUInf <scalar>;
|
||||||
|
lRef <scalar>;
|
||||||
|
Aref <scalar>;
|
||||||
|
|
||||||
|
// Optional entries
|
||||||
|
coefficients (<wordHashSet>);
|
||||||
|
directForceDensity <bool>;
|
||||||
|
porosity <bool>;
|
||||||
|
writeFields <bool>;
|
||||||
|
useNamePrefix <bool>;
|
||||||
|
|
||||||
|
// Conditional mandatory entries
|
||||||
|
|
||||||
|
// Cartesian coordinate system specification when evaluating
|
||||||
|
// force and moment coefficients, either of the below
|
||||||
|
|
||||||
|
// Option-1, i.e. the centre of rotation
|
||||||
|
// by inherently using e3=(0 0 1) and e1=(1 0 0)
|
||||||
|
CofR (0 0 0); // Centre of rotation
|
||||||
|
dragDir (1 0 0);
|
||||||
|
liftDir (0 0 1);
|
||||||
|
|
||||||
|
// Option-2, i.e. local coordinate system specification
|
||||||
|
origin (0 0 0);
|
||||||
|
e1 (1 0 0);
|
||||||
|
e3 (0 0 1); // (e1, e2) or (e2, e3) or (e3, e1)
|
||||||
|
|
||||||
|
// Option-3, i.e. general coordinate system specification
|
||||||
|
coordinateSystem
|
||||||
|
{
|
||||||
|
type cartesian;
|
||||||
|
origin (0 0 0);
|
||||||
|
rotation
|
||||||
|
{
|
||||||
|
type axes;
|
||||||
|
e3 (0 0 1);
|
||||||
|
e1 (1 0 0); // (e1, e2) or (e2, e3) or (e3, e1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Conditional optional entries
|
||||||
|
|
||||||
|
// if directForceDensity == true
|
||||||
|
fD <word>;
|
||||||
|
|
||||||
|
// if directForceDensity == false
|
||||||
|
p <word>;
|
||||||
|
U <word>;
|
||||||
|
rho <word>;
|
||||||
|
rhoInf <scalar>; // redundant for incompressible-flow cases
|
||||||
|
pRef <scalar>;
|
||||||
|
|
||||||
|
// Inherited entries
|
||||||
...
|
...
|
||||||
log yes;
|
|
||||||
writeFields yes;
|
|
||||||
patches (walls);
|
|
||||||
|
|
||||||
// input keywords for directions of force/moment coefficients
|
|
||||||
// refer below for options, and relations
|
|
||||||
|
|
||||||
magUInf 100;
|
|
||||||
lRef 3.5;
|
|
||||||
Aref 2.2;
|
|
||||||
porosity no;
|
|
||||||
|
|
||||||
binData
|
|
||||||
{
|
|
||||||
nBin 20;
|
|
||||||
direction (1 0 0);
|
|
||||||
cumulative yes;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
\endverbatim
|
\endverbatim
|
||||||
|
|
||||||
Where the entries comprise:
|
where the entries mean:
|
||||||
\table
|
\table
|
||||||
Property | Description | Required | Default
|
Property | Description | Type | Reqd | Deflt
|
||||||
type | Type name: forceCoeffs | yes |
|
type | Type name: forceCoeffs | word | yes | -
|
||||||
log | Write force data to standard output | no | no
|
libs | Library name: forces | word | yes | -
|
||||||
writeFields | Write force,moment coefficient fields | no | no
|
patches | Names of operand patches | wordRes | yes | -
|
||||||
patches | Patches included in the forces calculation | yes |
|
coefficients | Names of operand coefficients | wordHashSet | no | -
|
||||||
magUInf | Free stream velocity magnitude | yes |
|
magUInf | Reference velocity magnitude | scalar | yes | -
|
||||||
rhoInf | Free stream density | for compressible cases |
|
lRef | Reference length scale for moment calculations <!--
|
||||||
lRef | Reference length scale for moment calculations | yes |
|
--> | scalar | yes | -
|
||||||
Aref | Reference area | yes |
|
Aref | Reference area | scalar | yes | -
|
||||||
porosity | Include porosity contributions | no | false
|
directForceDensity | Flag to directly supply force density <!--
|
||||||
|
--> | bool | no | false
|
||||||
|
porosity | Flag to include porosity contributions | bool | no | false
|
||||||
|
writeFields | Flag to write force and moment fields | bool | no | false
|
||||||
|
useNamePrefix | Flag to include prefix for field names | bool | no | false
|
||||||
|
CofR | Centre of rotation | vector | cndtnl | -
|
||||||
|
origin | Origin of coordinate system | vector | cndtnl | -
|
||||||
|
e3 | e3 coordinate axis | vector | cndtnl | -
|
||||||
|
e1 | e1 coordinate axis | vector | cndtnl | -
|
||||||
|
coordinateSystem | Coordinate system specifier | dictionary | cndtnl | -
|
||||||
|
fD | Name of force density field | word | cndtnl-no | fD
|
||||||
|
p | Name of pressure field | word | cndtnl-no | p
|
||||||
|
U | Name of velocity field | word | cndtnl-no | U
|
||||||
|
rho | Name of density field | word | cndtnl-no | rho
|
||||||
|
rhoInf | Value of reference density | scalar | cndtnl-yes | -
|
||||||
|
pRef | Value of reference pressure | scalar | cndtnl-no | 0
|
||||||
\endtable
|
\endtable
|
||||||
|
|
||||||
Bin data is optional, but if the dictionary is present, the entries must
|
Options for the \c coefficients entry:
|
||||||
be defined according to following:
|
|
||||||
\table
|
|
||||||
nBin | Number of data bins | yes |
|
|
||||||
direction | Direction along which bins are defined | yes |
|
|
||||||
cumulative | Bin data accumulated with incresing distance | yes |
|
|
||||||
\endtable
|
|
||||||
|
|
||||||
Input of force/moment coefficient directions:
|
|
||||||
- require an origin, and two orthogonal directions; the remaining orthogonal
|
|
||||||
direction is determined accordingly.
|
|
||||||
- can be added by the three options below.
|
|
||||||
|
|
||||||
\verbatim
|
\verbatim
|
||||||
CofR (0 0 0); // Centre of rotation
|
Cd | Drag coefficient
|
||||||
dragDir (1 0 0);
|
Cs | Side-force coefficient
|
||||||
liftDir (0 0 1);
|
Cl | Lift coefficient
|
||||||
|
CmRoll | Roll-moment coefficient
|
||||||
|
CmPitch | Pitch-moment coefficient
|
||||||
|
CmYaw | Yaw-moment coefficient
|
||||||
|
Cdf | Front-axle drag coefficient
|
||||||
|
Csf | Front-axle side-force coefficient
|
||||||
|
Clf | Front-axle lift coefficient
|
||||||
|
Cdr | Rear-axle drag coefficient
|
||||||
|
Csr | Rear-axle side-force coefficient
|
||||||
|
Clr | Rear-axle lift coefficient
|
||||||
\endverbatim
|
\endverbatim
|
||||||
|
|
||||||
\verbatim
|
The inherited entries are elaborated in:
|
||||||
origin (0 0 0);
|
- \link functionObject.H \endlink
|
||||||
e1 (1 0 0);
|
- \link writeFile.H \endlink
|
||||||
e3 (0 0 1); // combinations: (e1, e2) or (e2, e3) or (e3, e1)
|
- \link coordinateSystem.H \endlink
|
||||||
\endverbatim
|
- \link forces.H \endlink
|
||||||
|
|
||||||
\verbatim
|
Note
|
||||||
coordinateSystem
|
- \c rhoInf is always redundant for incompressible computations.
|
||||||
{
|
That is, \c rhoInf is always equal to 1 in incompressible
|
||||||
origin (0 0 0);
|
computations no matter which input value is assigned to \c rhoInf.
|
||||||
rotation
|
The value of \c rhoInf is only used for compressible computations.
|
||||||
{
|
- \c writeControl and \c writeInterval entries of function
|
||||||
type axes;
|
object do control when to output force and moment files and fields.
|
||||||
e1 (1 0 0);
|
- Input for force/moment coefficient directions
|
||||||
e3 (0 0 1); // combinations: (e1, e2) or (e2, e3) or (e3, e1)
|
require an origin and two orthogonal directions where
|
||||||
}
|
the remaining orthogonal direction is automatically computed.
|
||||||
}
|
- The default direction relations are shown below:
|
||||||
\endverbatim
|
|
||||||
|
|
||||||
The default direction relations are shown below:
|
|
||||||
|
|
||||||
\table
|
\table
|
||||||
Property | Description | Alias | Direction
|
Property | Description | Alias | Direction
|
||||||
dragDir | Drag direction | e1 | (1 0 0)
|
dragDir | Drag direction | e1 | (1 0 0)
|
||||||
sideDir | Side force direction | e2 | (0 1 0)
|
sideDir | Side force direction | e2 | (0 1 0)
|
||||||
liftDir | Lift direction | e3 | (0 0 1)
|
liftDir | Lift direction | e3 | (0 0 1)
|
||||||
rollAxis | Roll axis | e1 | (1 0 0)
|
rollAxis | Roll axis | e1 | (1 0 0)
|
||||||
pitchAxis | Pitch axis | e2 | (0 1 0)
|
pitchAxis | Pitch axis | e2 | (0 1 0)
|
||||||
yawAxis | Yaw axis | e3 | (0 0 1)
|
yawAxis | Yaw axis | e3 | (0 0 1)
|
||||||
\endtable
|
\endtable
|
||||||
|
|
||||||
See also
|
|
||||||
Foam::functionObject
|
|
||||||
Foam::functionObjects::timeControl
|
|
||||||
Foam::functionObjects::forces
|
|
||||||
|
|
||||||
SourceFiles
|
SourceFiles
|
||||||
forceCoeffs.C
|
forceCoeffs.C
|
||||||
|
|
||||||
\*---------------------------------------------------------------------------*/
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
#ifndef functionObjects_forceCoeffs_H
|
#ifndef Foam_functionObjects_forceCoeffs_H
|
||||||
#define functionObjects_forceCoeffs_H
|
#define Foam_functionObjects_forceCoeffs_H
|
||||||
|
|
||||||
#include "forces.H"
|
#include "forces.H"
|
||||||
|
#include "HashSet.H"
|
||||||
|
#include "Enum.H"
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
@ -183,78 +248,261 @@ class forceCoeffs
|
|||||||
:
|
:
|
||||||
public forces
|
public forces
|
||||||
{
|
{
|
||||||
// Private data
|
public:
|
||||||
|
|
||||||
// Free-stream conditions
|
// Container for force and moment components
|
||||||
|
class forceComponents
|
||||||
|
{
|
||||||
|
// Private Data
|
||||||
|
|
||||||
//- Free-stream velocity magnitude
|
//- Pressure force/moment component
|
||||||
scalar magUInf_;
|
vector pressure_;
|
||||||
|
|
||||||
|
//- Viscous force/moment component
|
||||||
|
vector viscous_;
|
||||||
|
|
||||||
|
//- Internal force/moment component
|
||||||
|
vector internal_;
|
||||||
|
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
// Constructors
|
||||||
|
|
||||||
|
//- Default construct
|
||||||
|
forceComponents()
|
||||||
|
:
|
||||||
|
pressure_(Zero),
|
||||||
|
viscous_(Zero),
|
||||||
|
internal_(Zero)
|
||||||
|
{}
|
||||||
|
|
||||||
|
|
||||||
|
// Member Functions
|
||||||
|
|
||||||
|
//- Return the sum of the components
|
||||||
|
const vector total() const noexcept
|
||||||
|
{
|
||||||
|
return pressure_ + viscous_ + internal_;
|
||||||
|
}
|
||||||
|
|
||||||
|
//- Reset the components to zero
|
||||||
|
void reset() noexcept
|
||||||
|
{
|
||||||
|
pressure_ = Zero;
|
||||||
|
viscous_ = Zero;
|
||||||
|
internal_ = Zero;
|
||||||
|
}
|
||||||
|
|
||||||
|
//- Reset the components to given values
|
||||||
|
void reset
|
||||||
|
(
|
||||||
|
const vector& pressure,
|
||||||
|
const vector& viscous,
|
||||||
|
const vector& internal
|
||||||
|
) noexcept
|
||||||
|
{
|
||||||
|
pressure_ = pressure;
|
||||||
|
viscous_ = viscous;
|
||||||
|
internal_ = internal;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Member Operators
|
||||||
|
|
||||||
|
//- Return components in a given direction
|
||||||
|
vector operator[](const label cmpt) const
|
||||||
|
{
|
||||||
|
return vector(pressure_[cmpt], viscous_[cmpt], internal_[cmpt]);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// Coefficients description
|
||||||
|
struct coeffDesc
|
||||||
|
{
|
||||||
|
enum splitType
|
||||||
|
{
|
||||||
|
stFront,
|
||||||
|
stRear,
|
||||||
|
stNone
|
||||||
|
};
|
||||||
|
|
||||||
|
string desc_;
|
||||||
|
word name_;
|
||||||
|
label c0_;
|
||||||
|
label c1_;
|
||||||
|
bool active_;
|
||||||
|
splitType splitType_;
|
||||||
|
|
||||||
|
// Constructors
|
||||||
|
|
||||||
|
//- Construct from components
|
||||||
|
coeffDesc
|
||||||
|
(
|
||||||
|
const string& description,
|
||||||
|
const word& name,
|
||||||
|
const label c0,
|
||||||
|
const label c1 = -1
|
||||||
|
)
|
||||||
|
:
|
||||||
|
desc_(description),
|
||||||
|
name_(name),
|
||||||
|
c0_(c0),
|
||||||
|
c1_(c1),
|
||||||
|
active_(false),
|
||||||
|
splitType_(stNone)
|
||||||
|
{}
|
||||||
|
|
||||||
|
//- Return name with front-name appendix
|
||||||
|
const word frontName() const noexcept
|
||||||
|
{
|
||||||
|
return name_ + "(f)";
|
||||||
|
}
|
||||||
|
|
||||||
|
//- Return name with rear-name appendix
|
||||||
|
const word rearName() const noexcept
|
||||||
|
{
|
||||||
|
return name_ + "(r)";
|
||||||
|
}
|
||||||
|
|
||||||
|
//- Return force/moment components based on the specified split type
|
||||||
|
vector value(const forceComponents& f, const forceComponents& m) const
|
||||||
|
{
|
||||||
|
if (c1_ == -1)
|
||||||
|
{
|
||||||
|
return m[c0_];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
switch (splitType_)
|
||||||
|
{
|
||||||
|
case stFront:
|
||||||
|
{
|
||||||
|
return 0.5*f[c0_] + m[c1_];
|
||||||
|
}
|
||||||
|
case stRear:
|
||||||
|
{
|
||||||
|
return 0.5*f[c0_] - m[c1_];
|
||||||
|
}
|
||||||
|
case stNone:
|
||||||
|
{
|
||||||
|
return f[c0_];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
FatalErrorInFunction
|
||||||
|
<< "Cannot determine value"
|
||||||
|
<< abort(FatalError);
|
||||||
|
|
||||||
|
return vector::zero;
|
||||||
|
}
|
||||||
|
|
||||||
|
//- Return front-axle coefficient description
|
||||||
|
coeffDesc front() const
|
||||||
|
{
|
||||||
|
coeffDesc coeff(*this);
|
||||||
|
coeff.name_ = coeff.frontName();
|
||||||
|
coeff.desc_ = coeff.desc_ + " front";
|
||||||
|
coeff.splitType_ = stFront;
|
||||||
|
return coeff;
|
||||||
|
}
|
||||||
|
|
||||||
|
//- Return rear-axle coefficient description
|
||||||
|
coeffDesc rear() const
|
||||||
|
{
|
||||||
|
coeffDesc coeff(*this);
|
||||||
|
coeff.name_ = coeff.rearName();
|
||||||
|
coeff.desc_ = coeff.desc_ + " rear";
|
||||||
|
coeff.splitType_ = stRear;
|
||||||
|
return coeff;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
// Private Data
|
||||||
|
|
||||||
|
//- Force components
|
||||||
|
forceComponents Cf_;
|
||||||
|
|
||||||
|
//- Moment components
|
||||||
|
forceComponents Cm_;
|
||||||
|
|
||||||
|
//- Force coefficient field
|
||||||
|
volVectorField forceCoeff_;
|
||||||
|
|
||||||
|
//- Moment coefficient field
|
||||||
|
volVectorField momentCoeff_;
|
||||||
|
|
||||||
|
//- Operand force and moment coefficients
|
||||||
|
HashTable<coeffDesc> coeffs_;
|
||||||
|
|
||||||
|
|
||||||
|
// File streams
|
||||||
|
|
||||||
|
//- File stream for integrated operand coefficients
|
||||||
|
autoPtr<OFstream> coeffFilePtr_;
|
||||||
|
|
||||||
|
|
||||||
// Reference scales
|
// Reference scales
|
||||||
|
|
||||||
//- Reference length [m]
|
//- Reference velocity magnitude [m/s]
|
||||||
|
scalar magUInf_;
|
||||||
|
|
||||||
|
//- Reference length scale [m]
|
||||||
scalar lRef_;
|
scalar lRef_;
|
||||||
|
|
||||||
//- Reference area [m^2]
|
//- Reference area [m^2]
|
||||||
scalar Aref_;
|
scalar Aref_;
|
||||||
|
|
||||||
|
|
||||||
// File streams
|
//- Flag of initialisation (internal)
|
||||||
|
bool initialised_;
|
||||||
//- Integrated coefficients
|
|
||||||
autoPtr<OFstream> coeffFilePtr_;
|
|
||||||
|
|
||||||
//- Drag coefficient
|
|
||||||
autoPtr<OFstream> CdBinFilePtr_;
|
|
||||||
|
|
||||||
//- Side coefficient
|
|
||||||
autoPtr<OFstream> CsBinFilePtr_;
|
|
||||||
|
|
||||||
//- Lift coefficient
|
|
||||||
autoPtr<OFstream> ClBinFilePtr_;
|
|
||||||
|
|
||||||
//- Roll moment coefficient
|
|
||||||
autoPtr<OFstream> CmRollBinFilePtr_;
|
|
||||||
|
|
||||||
//- Pitch moment coefficient
|
|
||||||
autoPtr<OFstream> CmPitchBinFilePtr_;
|
|
||||||
|
|
||||||
//- Yaw moment coefficient
|
|
||||||
autoPtr<OFstream> CmYawBinFilePtr_;
|
|
||||||
|
|
||||||
|
|
||||||
// Private Member Functions
|
|
||||||
|
|
||||||
//- No copy construct
|
|
||||||
forceCoeffs(const forceCoeffs&) = delete;
|
|
||||||
|
|
||||||
//- No copy assignment
|
|
||||||
void operator=(const forceCoeffs&) = delete;
|
|
||||||
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
// Protected Member Functions
|
// Protected Member Functions
|
||||||
|
|
||||||
//- Create the output files
|
//- Initialise containers and fields
|
||||||
void createFiles();
|
void initialise();
|
||||||
|
|
||||||
//- Write header for integrated data
|
//- Reset containers and fields
|
||||||
void writeIntegratedHeader(const word& header, Ostream& os) const;
|
void reset();
|
||||||
|
|
||||||
//- Write header for binned data
|
|
||||||
void writeBinHeader(const word& header, Ostream& os) const;
|
|
||||||
|
|
||||||
//- Write integrated data
|
// Evaluation
|
||||||
void writeIntegratedData
|
|
||||||
|
//- Return the operand coefficients
|
||||||
|
HashTable<coeffDesc> selectCoeffs() const;
|
||||||
|
|
||||||
|
//- Calculate force coefficients
|
||||||
|
void calcForceCoeffs();
|
||||||
|
|
||||||
|
//- Calculate moment coefficients
|
||||||
|
void calcMomentCoeffs();
|
||||||
|
|
||||||
|
//- Return integrated {total, pressure, viscous, porous} components
|
||||||
|
List<scalar> integrateData(const List<Field<scalar>>& coeff) const;
|
||||||
|
|
||||||
|
|
||||||
|
// I-O
|
||||||
|
|
||||||
|
//- Create the integrated-coefficient file
|
||||||
|
void createIntegratedDataFile();
|
||||||
|
|
||||||
|
//- Write header to the integrated-coefficient file
|
||||||
|
void writeIntegratedDataFileHeader
|
||||||
(
|
(
|
||||||
const word& title,
|
const word& header,
|
||||||
const List<Field<scalar>>& coeff
|
OFstream& os
|
||||||
) const;
|
) const;
|
||||||
|
|
||||||
//- Write binned data
|
//- Write integrated coefficients to the integrated-coefficient file
|
||||||
void writeBinData(const List<Field<scalar>> coeffs, Ostream& os) const;
|
void writeIntegratedDataFile();
|
||||||
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
@ -270,10 +518,16 @@ public:
|
|||||||
(
|
(
|
||||||
const word& name,
|
const word& name,
|
||||||
const Time& runTime,
|
const Time& runTime,
|
||||||
const dictionary&,
|
const dictionary& dict,
|
||||||
const bool readFields = true
|
const bool readFields = true
|
||||||
);
|
);
|
||||||
|
|
||||||
|
//- No copy construct
|
||||||
|
forceCoeffs(const forceCoeffs&) = delete;
|
||||||
|
|
||||||
|
//- No copy assignment
|
||||||
|
void operator=(const forceCoeffs&) = delete;
|
||||||
|
|
||||||
|
|
||||||
//- Destructor
|
//- Destructor
|
||||||
virtual ~forceCoeffs() = default;
|
virtual ~forceCoeffs() = default;
|
||||||
@ -281,19 +535,27 @@ public:
|
|||||||
|
|
||||||
// Member Functions
|
// Member Functions
|
||||||
|
|
||||||
//- Read the forces data
|
//- Read the dictionary
|
||||||
virtual bool read(const dictionary&);
|
virtual bool read(const dictionary& dict);
|
||||||
|
|
||||||
//- Execute
|
//- Execute the function object
|
||||||
virtual bool execute();
|
virtual bool execute();
|
||||||
|
|
||||||
//- Write the forces
|
//- Write to data files/fields and to streams
|
||||||
virtual bool write();
|
virtual bool write();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
Ostream& operator<<(Ostream& os, const forceCoeffs::coeffDesc& coeff)
|
||||||
|
{
|
||||||
|
os << coeff.desc_.c_str() << ": " << coeff.name_;
|
||||||
|
|
||||||
|
return os;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
} // End namespace functionObjects
|
} // End namespace functionObjects
|
||||||
} // End namespace Foam
|
} // End namespace Foam
|
||||||
|
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@ -6,7 +6,7 @@
|
|||||||
\\/ M anipulation |
|
\\/ M anipulation |
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
Copyright (C) 2011-2016 OpenFOAM Foundation
|
Copyright (C) 2011-2016 OpenFOAM Foundation
|
||||||
Copyright (C) 2015-2020 OpenCFD Ltd.
|
Copyright (C) 2015-2022 OpenCFD Ltd.
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
License
|
License
|
||||||
This file is part of OpenFOAM.
|
This file is part of OpenFOAM.
|
||||||
@ -31,127 +31,155 @@ Group
|
|||||||
grpForcesFunctionObjects
|
grpForcesFunctionObjects
|
||||||
|
|
||||||
Description
|
Description
|
||||||
Calculates the forces and moments by integrating the pressure and
|
Computes forces and moments over a given list of patches by integrating
|
||||||
skin-friction forces over a given list of patches, and the resistance
|
pressure and viscous forces and moments, and optionally resistance forces
|
||||||
from porous zones.
|
and moments from porous zones.
|
||||||
|
|
||||||
Forces and moments are calculated in a global Cartesian coordinate system
|
Forces and moments are output in their total and constituent components:
|
||||||
by default, or using a user-defined system. Contributions can be 'binned'
|
- total forces and moments
|
||||||
according to a user-defined number of uniform-width collection zones (bins)
|
- pressure contributions
|
||||||
that span the input geometries, oriented by a user-defined direction vector.
|
- viscous contributions
|
||||||
|
- porous resistance contributions (optional)
|
||||||
|
|
||||||
Results are written to multiple files as a function of time in the
|
Forces and moments can be computed and output in:
|
||||||
postProcessing/\<functionObjectName\> directory:
|
- the global Cartesian coordinate system (default)
|
||||||
- force.dat : forces
|
- a user-defined Cartesian coordinate system
|
||||||
- moment.dat : moments
|
|
||||||
- forceBin.dat : force bins
|
Operands:
|
||||||
- momentBin.dat : moment bins
|
\table
|
||||||
|
Operand | Type | Location
|
||||||
|
input | - | -
|
||||||
|
output file | dat | postProcessing/\<FO\>/\<time\>/\<file\>s
|
||||||
|
output field | volVectorField | \<time\>/\<outField\>s
|
||||||
|
\endtable
|
||||||
|
|
||||||
|
where \c \<file\>s:
|
||||||
|
\verbatim
|
||||||
|
force.dat | Forces
|
||||||
|
moment.dat | Moments
|
||||||
|
\endverbatim
|
||||||
|
|
||||||
|
where \c \<outField\>s:
|
||||||
|
\verbatim
|
||||||
|
<namePrefix>:force | Force field
|
||||||
|
<namePrefix>:moment | Moment field
|
||||||
|
\endverbatim
|
||||||
|
|
||||||
Usage
|
Usage
|
||||||
Example of function object specification:
|
Minimal example by using \c system/controlDict.functions:
|
||||||
\verbatim
|
\verbatim
|
||||||
forces1
|
<namePrefix>
|
||||||
{
|
{
|
||||||
type forces;
|
// Mandatory entries
|
||||||
libs (forces);
|
type forces;
|
||||||
...
|
libs (forces);
|
||||||
log yes;
|
patches (<wordRes>);
|
||||||
writeFields yes;
|
|
||||||
patches (walls);
|
|
||||||
|
|
||||||
binData
|
// Optional entries
|
||||||
{
|
directForceDensity <bool>;
|
||||||
nBin 20;
|
porosity <bool>;
|
||||||
direction (1 0 0);
|
writeFields <bool>;
|
||||||
cumulative yes;
|
useNamePrefix <bool>;
|
||||||
}
|
|
||||||
|
// Conditional mandatory entries
|
||||||
|
|
||||||
|
// if directForceDensity == true
|
||||||
|
fD <word>;
|
||||||
|
|
||||||
|
|
||||||
|
// Cartesian coordinate system specification when
|
||||||
|
// evaluating forces and moments, either of the below
|
||||||
|
|
||||||
|
// Option-1, i.e. the centre of rotation
|
||||||
|
// by inherently using e3=(0 0 1) and e1=(1 0 0)
|
||||||
|
CofR (0 0 0); // Centre of rotation
|
||||||
|
|
||||||
|
// Option-2, i.e. local coordinate system specification
|
||||||
|
origin (0 0 0);
|
||||||
|
e1 (1 0 0);
|
||||||
|
e3 (0 0 1); // (e1, e2) or (e2, e3) or (e3, e1)
|
||||||
|
|
||||||
|
// Option-3, i.e. general coordinate system specification
|
||||||
|
coordinateSystem
|
||||||
|
{
|
||||||
|
type cartesian;
|
||||||
|
origin (0 0 0);
|
||||||
|
rotation
|
||||||
|
{
|
||||||
|
type axes;
|
||||||
|
e3 (0 0 1);
|
||||||
|
e1 (1 0 0); // (e1, e2) or (e2, e3) or (e3, e1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Conditional optional entries
|
||||||
|
|
||||||
|
// if directForceDensity == false
|
||||||
|
p <word>;
|
||||||
|
U <word>;
|
||||||
|
rho <word>;
|
||||||
|
rhoInf <scalar>; // enabled if rho=rhoInf
|
||||||
|
pRef <scalar>;
|
||||||
|
|
||||||
|
// Inherited entries
|
||||||
|
...
|
||||||
}
|
}
|
||||||
\endverbatim
|
\endverbatim
|
||||||
|
|
||||||
Where the entries comprise:
|
where the entries mean:
|
||||||
\table
|
\table
|
||||||
Property | Description | Required | Default value
|
Property | Description | Type | Reqd | Deflt
|
||||||
type | Type name: forces | yes |
|
type | Type name: forces | word | yes | -
|
||||||
log | Write force data to standard output | no | no
|
libs | Library name: forces | word | yes | -
|
||||||
writeFields | Write the force and moment fields | no | no
|
patches | Names of operand patches | wordRes | yes | -
|
||||||
patches | Patches included in the forces calculation | yes |
|
directForceDensity | Flag to directly supply force density <!--
|
||||||
p | Pressure field name | no | p
|
--> | bool | no | false
|
||||||
U | Velocity field name | no | U
|
porosity | Flag to include porosity contributions | bool | no | false
|
||||||
rho | Density field name (see below) | no | rho
|
writeFields | Flag to write force and moment fields | bool | no | false
|
||||||
CofR | Centre of rotation (see below) | no |
|
useNamePrefix | Flag to include prefix for field names | bool | no | false
|
||||||
porosity | flag to include porosity contributions | no | no
|
CofR | Centre of rotation | vector | cndtnl | -
|
||||||
directForceDensity | Force density supplied directly (see below)|no|no
|
origin | Origin of coordinate system | vector | cndtnl | -
|
||||||
fD | Name of force density field (see below) | no | fD
|
e3 | e3 coordinate axis | vector | cndtnl | -
|
||||||
|
e1 | e1 coordinate axis | vector | cndtnl | -
|
||||||
|
coordinateSystem | Coordinate system specifier | dictionary | cndtnl | -
|
||||||
|
fD | Name of force density field | word | cndtnl | -
|
||||||
|
p | Name of pressure field | word | cndtnl | p
|
||||||
|
U | Name of velocity field | word | cndtnl | U
|
||||||
|
rho | Name of density field | word | cndtnl | rho
|
||||||
|
rhoInf | Value of reference density | scalar | cndtnl | -
|
||||||
|
pRef | Value of reference pressure | scalar | cndtnl | 0
|
||||||
\endtable
|
\endtable
|
||||||
|
|
||||||
Bin data is optional, but if the dictionary is present, the entries must
|
The inherited entries are elaborated in:
|
||||||
be defined according o
|
- \link functionObject.H \endlink
|
||||||
\table
|
- \link writeFile.H \endlink
|
||||||
nBin | number of data bins | yes |
|
- \link coordinateSystem.H \endlink
|
||||||
direction | direction along which bins are defined | yes |
|
|
||||||
cumulative | bin data accumulated with incresing distance | yes |
|
|
||||||
\endtable
|
|
||||||
|
|
||||||
Note
|
Note
|
||||||
- For incompressible cases, set \c rho to \c rhoInf. You will then be
|
- For incompressible cases, set \c rho to \c rhoInf.
|
||||||
required to provide a \c rhoInf value corresponding to the free-stream
|
You will then be required to provide a \c rhoInf
|
||||||
constant density.
|
value corresponding to the constant freestream density.
|
||||||
- If the force density is supplied directly, set the \c directForceDensity
|
- \c writeControl and \c writeInterval entries of function
|
||||||
flag to 'yes', and supply the force density field using the \c
|
object do control when to output force and moment files and fields.
|
||||||
fDName entry
|
|
||||||
- The centre of rotation (CofR) for moment calculations can either be
|
|
||||||
specified by an \c CofR entry, or be taken from origin of the local
|
|
||||||
coordinate system. For example,
|
|
||||||
\verbatim
|
|
||||||
CofR (0 0 0);
|
|
||||||
\endverbatim
|
|
||||||
or
|
|
||||||
\verbatim
|
|
||||||
origin (0 0 0);
|
|
||||||
e1 (0 1 0);
|
|
||||||
e3 (0 0 1);
|
|
||||||
\endverbatim
|
|
||||||
or
|
|
||||||
\verbatim
|
|
||||||
coordinateSystem
|
|
||||||
{
|
|
||||||
origin (0 0 0);
|
|
||||||
rotation
|
|
||||||
{
|
|
||||||
type axes;
|
|
||||||
e3 (0 0 1);
|
|
||||||
e1 (1 0 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
\endverbatim
|
|
||||||
|
|
||||||
See also
|
|
||||||
Foam::functionObject
|
|
||||||
Foam::functionObjects::fvMeshFunctionObject
|
|
||||||
Foam::functionObjects::writeFile
|
|
||||||
Foam::functionObjects::timeControl
|
|
||||||
|
|
||||||
SourceFiles
|
SourceFiles
|
||||||
forces.C
|
forces.C
|
||||||
|
|
||||||
\*---------------------------------------------------------------------------*/
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
#ifndef functionObjects_forces_H
|
#ifndef Foam_functionObjects_forces_H
|
||||||
#define functionObjects_forces_H
|
#define Foam_functionObjects_forces_H
|
||||||
|
|
||||||
#include "fvMeshFunctionObject.H"
|
#include "fvMeshFunctionObject.H"
|
||||||
#include "writeFile.H"
|
#include "writeFile.H"
|
||||||
#include "coordinateSystem.H"
|
#include "coordinateSystem.H"
|
||||||
#include "volFieldsFwd.H"
|
#include "volFields.H"
|
||||||
#include "HashSet.H"
|
|
||||||
#include "Tuple2.H"
|
|
||||||
#include "OFstream.H"
|
|
||||||
#include "Switch.H"
|
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
namespace Foam
|
namespace Foam
|
||||||
{
|
{
|
||||||
|
|
||||||
namespace functionObjects
|
namespace functionObjects
|
||||||
{
|
{
|
||||||
|
|
||||||
@ -164,107 +192,87 @@ class forces
|
|||||||
public fvMeshFunctionObject,
|
public fvMeshFunctionObject,
|
||||||
public writeFile
|
public writeFile
|
||||||
{
|
{
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
// Protected data
|
// Protected Data
|
||||||
|
|
||||||
//- Pressure, viscous and porous force per bin
|
// Fields
|
||||||
List<Field<vector>> force_;
|
|
||||||
|
//- Forces
|
||||||
|
volVectorField force_;
|
||||||
|
|
||||||
|
//- Moments
|
||||||
|
volVectorField moment_;
|
||||||
|
|
||||||
|
//- Sum of patch pressure forces
|
||||||
|
vector sumPatchForcesP_;
|
||||||
|
|
||||||
|
//- Sum of patch viscous forces
|
||||||
|
vector sumPatchForcesV_;
|
||||||
|
|
||||||
|
//- Sum of patch pressure moments
|
||||||
|
vector sumPatchMomentsP_;
|
||||||
|
|
||||||
|
//- Sum of patch viscous moments
|
||||||
|
vector sumPatchMomentsV_;
|
||||||
|
|
||||||
|
//- Sum of internal forces
|
||||||
|
vector sumInternalForces_;
|
||||||
|
|
||||||
|
//- Sum of internal moments
|
||||||
|
vector sumInternalMoments_;
|
||||||
|
|
||||||
//- Pressure, viscous and porous moment per bin
|
|
||||||
List<Field<vector>> moment_;
|
|
||||||
|
|
||||||
// File streams
|
// File streams
|
||||||
|
|
||||||
//- Forces
|
//- File stream for forces
|
||||||
autoPtr<OFstream> forceFilePtr_;
|
autoPtr<OFstream> forceFilePtr_;
|
||||||
|
|
||||||
//- Moments
|
//- File stream for moments
|
||||||
autoPtr<OFstream> momentFilePtr_;
|
autoPtr<OFstream> momentFilePtr_;
|
||||||
|
|
||||||
//- Force bins
|
|
||||||
autoPtr<OFstream> forceBinFilePtr_;
|
|
||||||
|
|
||||||
//- Moment bins
|
|
||||||
autoPtr<OFstream> momentBinFilePtr_;
|
|
||||||
|
|
||||||
|
|
||||||
// Read from dictionary
|
// Read from dictionary
|
||||||
|
|
||||||
//- Patches to integrate forces over
|
//- Coordinate system used when evaluating forces and moments
|
||||||
|
autoPtr<coordinateSystem> coordSysPtr_;
|
||||||
|
|
||||||
|
//- Names of operand patches
|
||||||
labelHashSet patchSet_;
|
labelHashSet patchSet_;
|
||||||
|
|
||||||
//- Name of pressure field
|
|
||||||
word pName_;
|
|
||||||
|
|
||||||
//- Name of velocity field
|
|
||||||
word UName_;
|
|
||||||
|
|
||||||
//- Name of density field (optional)
|
|
||||||
word rhoName_;
|
|
||||||
|
|
||||||
//- Is the force density being supplied directly?
|
|
||||||
Switch directForceDensity_;
|
|
||||||
|
|
||||||
//- The name of the force density (fD) field
|
|
||||||
word fDName_;
|
|
||||||
|
|
||||||
//- Reference density needed for incompressible calculations
|
//- Reference density needed for incompressible calculations
|
||||||
scalar rhoRef_;
|
scalar rhoRef_;
|
||||||
|
|
||||||
//- Reference pressure
|
//- Reference pressure
|
||||||
scalar pRef_;
|
scalar pRef_;
|
||||||
|
|
||||||
//- Coordinate system used when evaluating forces/moments
|
//- Name of pressure field
|
||||||
autoPtr<coordinateSystem> coordSysPtr_;
|
word pName_;
|
||||||
|
|
||||||
|
//- Name of velocity field
|
||||||
|
word UName_;
|
||||||
|
|
||||||
|
//- Name of density field
|
||||||
|
word rhoName_;
|
||||||
|
|
||||||
|
//- Name of force density field
|
||||||
|
word fDName_;
|
||||||
|
|
||||||
|
//- Flag to directly supply force density
|
||||||
|
bool directForceDensity_;
|
||||||
|
|
||||||
//- Flag to include porosity effects
|
//- Flag to include porosity effects
|
||||||
bool porosity_;
|
bool porosity_;
|
||||||
|
|
||||||
|
//- Flag to write force and moment fields
|
||||||
// Bin information
|
|
||||||
|
|
||||||
//- Number of bins
|
|
||||||
label nBin_;
|
|
||||||
|
|
||||||
//- Direction used to determine bin orientation
|
|
||||||
vector binDir_;
|
|
||||||
|
|
||||||
//- Distance between bin divisions
|
|
||||||
scalar binDx_;
|
|
||||||
|
|
||||||
//- Minimum bin bounds
|
|
||||||
scalar binMin_;
|
|
||||||
|
|
||||||
//- Maximum bin bounds
|
|
||||||
scalar binMax_;
|
|
||||||
|
|
||||||
//- Bin positions along binDir
|
|
||||||
List<point> binPoints_;
|
|
||||||
|
|
||||||
//- Should bin data be cumulative?
|
|
||||||
bool binCumulative_;
|
|
||||||
|
|
||||||
|
|
||||||
//- Write fields flag
|
|
||||||
bool writeFields_;
|
bool writeFields_;
|
||||||
|
|
||||||
//- Initialised flag
|
//- Flag of initialisation (internal)
|
||||||
bool initialised_;
|
bool initialised_;
|
||||||
|
|
||||||
|
|
||||||
// Protected Member Functions
|
// Protected Member Functions
|
||||||
|
|
||||||
//- Create the output files
|
|
||||||
void createFiles();
|
|
||||||
|
|
||||||
//- Write header for integrated data
|
|
||||||
void writeIntegratedHeader(const word& header, Ostream& os) const;
|
|
||||||
|
|
||||||
//- Write header for binned data
|
|
||||||
void writeBinHeader(const word& header, Ostream& os) const;
|
|
||||||
|
|
||||||
//- Set the co-ordinate system from dictionary and axes names
|
//- Set the co-ordinate system from dictionary and axes names
|
||||||
void setCoordinateSystem
|
void setCoordinateSystem
|
||||||
(
|
(
|
||||||
@ -273,87 +281,80 @@ protected:
|
|||||||
const word& e1Name = word::null
|
const word& e1Name = word::null
|
||||||
);
|
);
|
||||||
|
|
||||||
//- Initialise the fields
|
//- Initialise containers and fields
|
||||||
void initialise();
|
void initialise();
|
||||||
|
|
||||||
//- Initialise the collection bins
|
//- Reset containers and fields
|
||||||
void initialiseBins();
|
void reset();
|
||||||
|
|
||||||
//- Reset the fields prior to accumulation of force/moments
|
|
||||||
void resetFields();
|
|
||||||
|
|
||||||
//- Return the effective viscous stress (laminar + turbulent).
|
// Evaluation
|
||||||
|
|
||||||
|
//- Return the effective stress (viscous + turbulent)
|
||||||
tmp<volSymmTensorField> devRhoReff() const;
|
tmp<volSymmTensorField> devRhoReff() const;
|
||||||
|
|
||||||
//- Dynamic viscosity field
|
//- Return dynamic viscosity field
|
||||||
tmp<volScalarField> mu() const;
|
tmp<volScalarField> mu() const;
|
||||||
|
|
||||||
//- Return rho if specified otherwise rhoRef
|
//- Return rho if specified otherwise rhoRef
|
||||||
tmp<volScalarField> rho() const;
|
tmp<volScalarField> rho() const;
|
||||||
|
|
||||||
//- Return rhoRef if the pressure field is dynamic, i.e. p/rho
|
//- Return rhoRef if the pressure field is
|
||||||
// otherwise return 1
|
//- dynamic (i.e. p/rho), otherwise return 1
|
||||||
scalar rho(const volScalarField& p) const;
|
scalar rho(const volScalarField& p) const;
|
||||||
|
|
||||||
//- Accumulate bin data
|
|
||||||
void applyBins
|
|
||||||
(
|
|
||||||
const vectorField& Md,
|
|
||||||
const vectorField& fN,
|
|
||||||
const vectorField& fT,
|
|
||||||
const vectorField& fP,
|
|
||||||
const vectorField& d
|
|
||||||
);
|
|
||||||
|
|
||||||
//- Add patch contributions to force and moment fields
|
//- Add patch contributions to force and moment fields
|
||||||
void addToFields
|
void addToPatchFields
|
||||||
(
|
(
|
||||||
const label patchi,
|
const label patchi,
|
||||||
const vectorField& Md,
|
const vectorField& Md,
|
||||||
const vectorField& fN,
|
const vectorField& fP,
|
||||||
const vectorField& fT,
|
const vectorField& fV
|
||||||
const vectorField& fP
|
|
||||||
);
|
);
|
||||||
|
|
||||||
//- Add cell contributions to force and moment fields
|
//- Add cell contributions to force and
|
||||||
void addToFields
|
//- moment fields, and include porosity effects
|
||||||
|
void addToInternalField
|
||||||
(
|
(
|
||||||
const labelList& cellIDs,
|
const labelList& cellIDs,
|
||||||
const vectorField& Md,
|
const vectorField& Md,
|
||||||
const vectorField& fN,
|
const vectorField& f
|
||||||
const vectorField& fT,
|
|
||||||
const vectorField& fP
|
|
||||||
);
|
);
|
||||||
|
|
||||||
//- Helper function to write integrated forces and moments
|
|
||||||
void writeIntegratedForceMoment
|
// I-O
|
||||||
|
|
||||||
|
//- Create the integrated-data files
|
||||||
|
void createIntegratedDataFiles();
|
||||||
|
|
||||||
|
//- Write header for an integrated-data file
|
||||||
|
void writeIntegratedDataFileHeader
|
||||||
|
(
|
||||||
|
const word& header,
|
||||||
|
OFstream& os
|
||||||
|
) const;
|
||||||
|
|
||||||
|
//- Write integrated data to files
|
||||||
|
void writeIntegratedDataFiles();
|
||||||
|
|
||||||
|
//- Write integrated data to a file
|
||||||
|
void writeIntegratedDataFile
|
||||||
|
(
|
||||||
|
const vector& pres,
|
||||||
|
const vector& vis,
|
||||||
|
const vector& internal,
|
||||||
|
OFstream& os
|
||||||
|
) const;
|
||||||
|
|
||||||
|
//- Write integrated data to stream
|
||||||
|
void logIntegratedData
|
||||||
(
|
(
|
||||||
const string& descriptor,
|
const string& descriptor,
|
||||||
const vectorField& fm0,
|
const vector& pres,
|
||||||
const vectorField& fm1,
|
const vector& vis,
|
||||||
const vectorField& fm2,
|
const vector& internal
|
||||||
autoPtr<OFstream>& osPtr
|
|
||||||
) const;
|
) const;
|
||||||
|
|
||||||
//- Write force data
|
|
||||||
void writeForces();
|
|
||||||
|
|
||||||
//- Helper function to write binned forces and moments
|
|
||||||
void writeBinnedForceMoment
|
|
||||||
(
|
|
||||||
const List<Field<vector>>& fm,
|
|
||||||
autoPtr<OFstream>& osPtr
|
|
||||||
) const;
|
|
||||||
|
|
||||||
//- Write binned data
|
|
||||||
void writeBins();
|
|
||||||
|
|
||||||
//- No copy construct
|
|
||||||
forces(const forces&) = delete;
|
|
||||||
|
|
||||||
//- No copy assignment
|
|
||||||
void operator=(const forces&) = delete;
|
|
||||||
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
@ -381,6 +382,12 @@ public:
|
|||||||
const bool readFields = true
|
const bool readFields = true
|
||||||
);
|
);
|
||||||
|
|
||||||
|
//- No copy construct
|
||||||
|
forces(const forces&) = delete;
|
||||||
|
|
||||||
|
//- No copy assignment
|
||||||
|
void operator=(const forces&) = delete;
|
||||||
|
|
||||||
|
|
||||||
//- Destructor
|
//- Destructor
|
||||||
virtual ~forces() = default;
|
virtual ~forces() = default;
|
||||||
@ -388,11 +395,11 @@ public:
|
|||||||
|
|
||||||
// Member Functions
|
// Member Functions
|
||||||
|
|
||||||
//- Read the forces data
|
//- Read the dictionary
|
||||||
virtual bool read(const dictionary&);
|
virtual bool read(const dictionary& dict);
|
||||||
|
|
||||||
//- Calculate the forces and moments
|
//- Calculate forces and moments
|
||||||
virtual void calcForcesMoment();
|
virtual void calcForcesMoments();
|
||||||
|
|
||||||
//- Return the total force
|
//- Return the total force
|
||||||
virtual vector forceEff() const;
|
virtual vector forceEff() const;
|
||||||
@ -400,10 +407,10 @@ public:
|
|||||||
//- Return the total moment
|
//- Return the total moment
|
||||||
virtual vector momentEff() const;
|
virtual vector momentEff() const;
|
||||||
|
|
||||||
//- Execute, currently does nothing
|
//- Execute the function object
|
||||||
virtual bool execute();
|
virtual bool execute();
|
||||||
|
|
||||||
//- Write the forces
|
//- Write to data files/fields and to streams
|
||||||
virtual bool write();
|
virtual bool write();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -5,7 +5,7 @@
|
|||||||
\\ / A nd | www.openfoam.com
|
\\ / A nd | www.openfoam.com
|
||||||
\\/ M anipulation |
|
\\/ M anipulation |
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
Copyright (C) 2021 OpenCFD Ltd.
|
Copyright (C) 2021-2022 OpenCFD Ltd.
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
License
|
License
|
||||||
This file is part of OpenFOAM.
|
This file is part of OpenFOAM.
|
||||||
@ -560,8 +560,8 @@ void Foam::functionObjects::propellerInfo::writePropellerPerformance()
|
|||||||
// Update n_
|
// Update n_
|
||||||
setRotationalSpeed();
|
setRotationalSpeed();
|
||||||
|
|
||||||
const vector sumForce(sum(force_[0]) + sum(force_[1]) + sum(force_[2]));
|
const vector sumForce = forceEff();
|
||||||
const vector sumMoment(sum(moment_[0]) + sum(moment_[1]) + sum(moment_[2]));
|
const vector sumMoment = momentEff();
|
||||||
|
|
||||||
const scalar diameter = 2*radius_;
|
const scalar diameter = 2*radius_;
|
||||||
const scalar URef = URefPtr_->value(time_.timeOutputValue());
|
const scalar URef = URefPtr_->value(time_.timeOutputValue());
|
||||||
@ -866,7 +866,7 @@ bool Foam::functionObjects::propellerInfo::read(const dictionary& dict)
|
|||||||
|
|
||||||
bool Foam::functionObjects::propellerInfo::execute()
|
bool Foam::functionObjects::propellerInfo::execute()
|
||||||
{
|
{
|
||||||
calcForcesMoment();
|
calcForcesMoments();
|
||||||
|
|
||||||
createFiles();
|
createFiles();
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user