mirror of
https://develop.openfoam.com/Development/openfoam.git
synced 2025-11-28 03:28:01 +00:00
ENH: support 'rpm' input for propeller functionObject (as per rotorDisk)
- update code style for forces/propeller. - simplify coordinate handling in propeller functionObject
This commit is contained in:
@ -6,7 +6,7 @@
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2011-2016 OpenFOAM Foundation
|
||||
Copyright (C) 2015-2024 OpenCFD Ltd.
|
||||
Copyright (C) 2015-2025 OpenCFD Ltd.
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
@ -205,11 +205,10 @@ void Foam::functionObjects::forces::reset()
|
||||
}
|
||||
else
|
||||
{
|
||||
constexpr bool updateAccessTime = false;
|
||||
for (const label patchi : patchIDs_)
|
||||
{
|
||||
force.boundaryFieldRef(updateAccessTime)[patchi] = Zero;
|
||||
moment.boundaryFieldRef(updateAccessTime)[patchi] = Zero;
|
||||
force.boundaryField().constCast()[patchi] = Zero;
|
||||
moment.boundaryField().constCast()[patchi] = Zero;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -222,88 +221,82 @@ Foam::functionObjects::forces::devRhoReff
|
||||
const label patchi
|
||||
) const
|
||||
{
|
||||
typedef incompressible::turbulenceModel icoTurbModel;
|
||||
typedef compressible::turbulenceModel cmpTurbModel;
|
||||
typedef incompressible::turbulenceModel icoModel;
|
||||
typedef compressible::turbulenceModel cmpModel;
|
||||
|
||||
if (foundObject<icoTurbModel>(icoTurbModel::propertiesName))
|
||||
if (const auto* turbp = cfindObject<icoModel>(icoModel::propertiesName))
|
||||
{
|
||||
const auto& turb =
|
||||
lookupObject<icoTurbModel>(icoTurbModel::propertiesName);
|
||||
const auto& turb = *turbp;
|
||||
|
||||
return -rho(patchi)*turb.nuEff(patchi)*devTwoSymm(gradUp);
|
||||
}
|
||||
else if (foundObject<cmpTurbModel>(cmpTurbModel::propertiesName))
|
||||
|
||||
if (const auto* turbp = cfindObject<cmpModel>(cmpModel::propertiesName))
|
||||
{
|
||||
const auto& turb =
|
||||
lookupObject<cmpTurbModel>(cmpTurbModel::propertiesName);
|
||||
const auto& turb = *turbp;
|
||||
|
||||
return -turb.muEff(patchi)*devTwoSymm(gradUp);
|
||||
}
|
||||
else if (foundObject<fluidThermo>(fluidThermo::dictName))
|
||||
|
||||
if (const auto* thermop = cfindObject<fluidThermo>(fluidThermo::dictName))
|
||||
{
|
||||
const auto& thermo = lookupObject<fluidThermo>(fluidThermo::dictName);
|
||||
const auto& thermo = *thermop;
|
||||
|
||||
return -thermo.mu(patchi)*devTwoSymm(gradUp);
|
||||
}
|
||||
else if (foundObject<transportModel>("transportProperties"))
|
||||
|
||||
if (const auto* props = cfindObject<transportModel>("transportProperties"))
|
||||
{
|
||||
const auto& laminarT =
|
||||
lookupObject<transportModel>("transportProperties");
|
||||
const auto& laminarT = *props;
|
||||
|
||||
return -rho(patchi)*laminarT.nu(patchi)*devTwoSymm(gradUp);
|
||||
}
|
||||
else if (foundObject<dictionary>("transportProperties"))
|
||||
{
|
||||
const auto& transportProperties =
|
||||
lookupObject<dictionary>("transportProperties");
|
||||
|
||||
const dimensionedScalar nu("nu", dimViscosity, transportProperties);
|
||||
if (const auto* props = cfindObject<dictionary>("transportProperties"))
|
||||
{
|
||||
const dimensionedScalar nu("nu", dimViscosity, *props);
|
||||
|
||||
return -rho(patchi)*nu.value()*devTwoSymm(gradUp);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
// Failed to resolve any model
|
||||
FatalErrorInFunction
|
||||
<< "No valid model for viscous stress calculation"
|
||||
<< exit(FatalError);
|
||||
|
||||
return volSymmTensorField::null();
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
||||
Foam::tmp<Foam::volScalarField> Foam::functionObjects::forces::mu() const
|
||||
{
|
||||
if (foundObject<fluidThermo>(basicThermo::dictName))
|
||||
if (const auto* thermop = cfindObject<fluidThermo>(basicThermo::dictName))
|
||||
{
|
||||
const auto& thermo = lookupObject<fluidThermo>(basicThermo::dictName);
|
||||
const auto& thermo = *thermop;
|
||||
|
||||
return thermo.mu();
|
||||
}
|
||||
else if (foundObject<transportModel>("transportProperties"))
|
||||
|
||||
if (const auto* props = cfindObject<transportModel>("transportProperties"))
|
||||
{
|
||||
const auto& laminarT =
|
||||
lookupObject<transportModel>("transportProperties");
|
||||
const auto& laminarT = *props;
|
||||
|
||||
return rho()*laminarT.nu();
|
||||
}
|
||||
else if (foundObject<dictionary>("transportProperties"))
|
||||
{
|
||||
const auto& transportProperties =
|
||||
lookupObject<dictionary>("transportProperties");
|
||||
|
||||
const dimensionedScalar nu("nu", dimViscosity, transportProperties);
|
||||
if (const auto* props = cfindObject<dictionary>("transportProperties"))
|
||||
{
|
||||
const dimensionedScalar nu("nu", dimViscosity, *props);
|
||||
|
||||
return rho()*nu;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
// Failed to resolve any model
|
||||
FatalErrorInFunction
|
||||
<< "No valid model for dynamic viscosity calculation"
|
||||
<< exit(FatalError);
|
||||
|
||||
return volScalarField::null();
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
||||
@ -320,7 +313,7 @@ Foam::tmp<Foam::volScalarField> Foam::functionObjects::forces::rho() const
|
||||
);
|
||||
}
|
||||
|
||||
return (lookupObject<volScalarField>(rhoName_));
|
||||
return lookupObject<volScalarField>(rhoName_);
|
||||
}
|
||||
|
||||
|
||||
@ -367,18 +360,16 @@ void Foam::functionObjects::forces::addToPatchFields
|
||||
const vectorField& fV
|
||||
)
|
||||
{
|
||||
constexpr bool updateAccessTime = false;
|
||||
|
||||
sumPatchForcesP_ += sum(fP);
|
||||
sumPatchForcesV_ += sum(fV);
|
||||
force().boundaryFieldRef(updateAccessTime)[patchi] += fP + fV;
|
||||
force().boundaryField().constCast()[patchi] += fP + fV;
|
||||
|
||||
const vectorField mP(Md^fP);
|
||||
const vectorField mV(Md^fV);
|
||||
|
||||
sumPatchMomentsP_ += sum(mP);
|
||||
sumPatchMomentsV_ += sum(mV);
|
||||
moment().boundaryFieldRef(updateAccessTime)[patchi] += mP + mV;
|
||||
moment().boundaryField().constCast()[patchi] += mP + mV;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -5,7 +5,7 @@
|
||||
\\ / A nd | www.openfoam.com
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2021-2024 OpenCFD Ltd.
|
||||
Copyright (C) 2021-2025 OpenCFD Ltd.
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
@ -73,7 +73,16 @@ void Foam::functionObjects::propellerInfo::setCoordinateSystem
|
||||
axis = dict.get<vector>("axis");
|
||||
axis.normalise();
|
||||
|
||||
// Can specify 'rpm' or 'n' (rev/s)
|
||||
if (dict.readIfPresent("rpm", n_))
|
||||
{
|
||||
n_ /= 60; // -> rev/s
|
||||
dict.readIfPresent("n", n_); // Optional if rpm was specified
|
||||
}
|
||||
else
|
||||
{
|
||||
n_ = dict.get<scalar>("n");
|
||||
}
|
||||
break;
|
||||
}
|
||||
case rotationMode::MRF:
|
||||
@ -90,11 +99,12 @@ void Foam::functionObjects::propellerInfo::setCoordinateSystem
|
||||
<< exit(FatalIOError);
|
||||
}
|
||||
const auto& mrf = MRFZones->MRFZoneList::getFromName(MRFName_);
|
||||
vector offset = dict.getOrDefault("originOffset", vector::zero);
|
||||
origin = offset + mrf.origin();
|
||||
|
||||
dict.readIfPresent("originOffset", origin);
|
||||
origin += mrf.origin();
|
||||
axis = mrf.axis();
|
||||
|
||||
// Convert rad/s to revolutions per second
|
||||
// Convert rad/s to rev/s
|
||||
n_ = (mrf.Omega() & axis)/constant::mathematical::twoPi;
|
||||
break;
|
||||
}
|
||||
@ -106,31 +116,22 @@ void Foam::functionObjects::propellerInfo::setCoordinateSystem
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Optional orientation axis for cylindrical coordinate system
|
||||
vector alphaAxis;
|
||||
if (!dict.readIfPresent("alphaAxis", alphaAxis))
|
||||
if (dict.readIfPresent("alphaAxis", alphaAxis))
|
||||
{
|
||||
// Value has not been set - find vector orthogonal to axis
|
||||
|
||||
vector cand(Zero);
|
||||
scalar minDot = GREAT;
|
||||
for (direction d = 0; d < 3; ++d)
|
||||
{
|
||||
vector test(Zero);
|
||||
test[d] = 1;
|
||||
scalar dotp = mag(test & axis);
|
||||
if (dotp < minDot)
|
||||
{
|
||||
minDot = dotp;
|
||||
cand = test;
|
||||
}
|
||||
}
|
||||
|
||||
alphaAxis = axis ^ cand;
|
||||
}
|
||||
|
||||
alphaAxis.normalise();
|
||||
|
||||
coordSysPtr_.reset(new coordSystem::cylindrical(origin, axis, alphaAxis));
|
||||
coordSysPtr_.reset
|
||||
(
|
||||
new coordSystem::cylindrical(origin, axis, alphaAxis)
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Use best-guess for an orthogonal second axis
|
||||
coordSysPtr_.reset(new coordSystem::cylindrical(origin, axis));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -222,6 +223,8 @@ const Foam::volVectorField& Foam::functionObjects::propellerInfo::U() const
|
||||
<< " . Available vector fields are: "
|
||||
<< flatOutput(mesh_.sortedNames<volVectorField>())
|
||||
<< exit(FatalError);
|
||||
|
||||
return volVectorField::null();
|
||||
}
|
||||
|
||||
return *UPtr;
|
||||
@ -250,8 +253,8 @@ void Foam::functionObjects::propellerInfo::setSampleDiskGeometry
|
||||
}
|
||||
const label nFace = nRadius*nTheta;
|
||||
|
||||
points.setSize(nPoint);
|
||||
faces.setSize(nFace);
|
||||
points.resize_nocopy(nPoint);
|
||||
faces.resize_nocopy(nFace);
|
||||
|
||||
const point& origin = coordSys.origin();
|
||||
const scalar zCoord = 0;
|
||||
@ -495,10 +498,9 @@ Foam::scalar Foam::functionObjects::propellerInfo::meanSampleDiskField
|
||||
|
||||
scalar sumArea = 0;
|
||||
scalar sumFieldArea = 0;
|
||||
forAll(faces_, facei)
|
||||
{
|
||||
const face& f = faces_[facei];
|
||||
|
||||
for (const face& f : faces_)
|
||||
{
|
||||
bool valid = true;
|
||||
scalar faceValue = 0;
|
||||
for (const label pti : f)
|
||||
|
||||
@ -5,7 +5,7 @@
|
||||
\\ / A nd | www.openfoam.com
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2021-2024 OpenCFD Ltd.
|
||||
Copyright (C) 2021-2025 OpenCFD Ltd.
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
@ -121,9 +121,10 @@ Usage
|
||||
URef | Reference velocity | yes |
|
||||
rotationMode | Rotation mode (see below) | yes |
|
||||
origin | Sample disk centre | no* |
|
||||
n | Revolutions per second | no* |
|
||||
axis | Propeller axis | no* |
|
||||
alphaAxis | Axis that defines alpha=0 dir | no |
|
||||
n | Rotation speed [rev/sec] | no* |
|
||||
rpm | Rotation speed [rev/min] | no* |
|
||||
MRF | Name of MRF zone | no* |
|
||||
originOffset | Origin offset for MRF mode | no | (0 0 0)
|
||||
writePropellerPerformance| Write propeller performance text file | yes |
|
||||
@ -140,6 +141,7 @@ Usage
|
||||
Note
|
||||
- URef is a scalar Function1 type, i.e. supports constant, table, lookup values
|
||||
- rotationMode is used to set the origin, axis and revolutions per second
|
||||
(alternatively rpm)
|
||||
- if set to 'specified' all 3 entries are required
|
||||
- note: origin is the sample disk origin
|
||||
- if set to 'MRF' only the MRF entry is required
|
||||
@ -173,9 +175,8 @@ SourceFiles
|
||||
namespace Foam
|
||||
{
|
||||
|
||||
template<class Type>
|
||||
class Function1;
|
||||
|
||||
// Forward Declarations
|
||||
template<class Type> class Function1;
|
||||
class surfaceWriter;
|
||||
|
||||
namespace functionObjects
|
||||
|
||||
@ -114,7 +114,7 @@ Usage
|
||||
type | Type name: rotorDiskSource | word | yes | -
|
||||
fields | Names of operand fields | wordList | yes | -
|
||||
rhoRef | Reference density for incompressible case | scalar | yes | -
|
||||
rpm | Rotational speed [rad/s] | scalar | yes | -
|
||||
rpm | Rotational speed [rev/min] | scalar | yes | -
|
||||
nBlades | Number of rotor blades | label | yes | -
|
||||
tipEffect | Ratio of blade radius beyond which lift=0 | scalar | yes | -
|
||||
refDirection | Reference direction used as reference <!--
|
||||
|
||||
@ -8,10 +8,10 @@ then
|
||||
|
||||
./Allrun.pre
|
||||
|
||||
restore0Dir
|
||||
|
||||
runApplication decomposePar
|
||||
|
||||
restore0Dir -processor
|
||||
|
||||
runParallel $(getApplication)
|
||||
|
||||
runApplication reconstructPar
|
||||
|
||||
@ -27,8 +27,8 @@ propellerInfo1
|
||||
|
||||
// rotationMode = specified:
|
||||
origin (0 -0.1 0);
|
||||
n 25.15;
|
||||
axis (0 1 0);
|
||||
n 25.15; // Or as rpm 1509;
|
||||
|
||||
// Optionally write wake text files
|
||||
// Note: controlled by writeControl
|
||||
|
||||
Reference in New Issue
Block a user