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