rotorDiskSource: Corrected coordinate transformations
Now the rotor axis may be specified in other than the z-direction Resolves bug-report http://www.openfoam.org/mantisbt/view.php?id=1290
This commit is contained in:
@ -69,14 +69,14 @@ namespace Foam
|
|||||||
|
|
||||||
void Foam::fv::rotorDiskSource::checkData()
|
void Foam::fv::rotorDiskSource::checkData()
|
||||||
{
|
{
|
||||||
// set inflow type
|
// Set inflow type
|
||||||
switch (selectionMode())
|
switch (selectionMode())
|
||||||
{
|
{
|
||||||
case smCellSet:
|
case smCellSet:
|
||||||
case smCellZone:
|
case smCellZone:
|
||||||
case smAll:
|
case smAll:
|
||||||
{
|
{
|
||||||
// set the profile ID for each blade section
|
// Set the profile ID for each blade section
|
||||||
profiles_.connectBlades(blade_.profileName(), blade_.profileID());
|
profiles_.connectBlades(blade_.profileName(), blade_.profileID());
|
||||||
switch (inletFlow_)
|
switch (inletFlow_)
|
||||||
{
|
{
|
||||||
@ -96,7 +96,7 @@ void Foam::fv::rotorDiskSource::checkData()
|
|||||||
}
|
}
|
||||||
case ifLocal:
|
case ifLocal:
|
||||||
{
|
{
|
||||||
// do nothing
|
// Do nothing
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
@ -137,7 +137,7 @@ void Foam::fv::rotorDiskSource::setFaceArea(vector& axis, const bool correct)
|
|||||||
|
|
||||||
vector n = vector::zero;
|
vector n = vector::zero;
|
||||||
|
|
||||||
// calculate cell addressing for selected cells
|
// Calculate cell addressing for selected cells
|
||||||
labelList cellAddr(mesh_.nCells(), -1);
|
labelList cellAddr(mesh_.nCells(), -1);
|
||||||
UIndirectList<label>(cellAddr, cells_) = identity(cells_.size());
|
UIndirectList<label>(cellAddr, cells_) = identity(cells_.size());
|
||||||
labelList nbrFaceCellAddr(mesh_.nFaces() - nInternalFaces, -1);
|
labelList nbrFaceCellAddr(mesh_.nFaces() - nInternalFaces, -1);
|
||||||
@ -157,10 +157,10 @@ void Foam::fv::rotorDiskSource::setFaceArea(vector& axis, const bool correct)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// correct for parallel running
|
// Correct for parallel running
|
||||||
syncTools::swapBoundaryFaceList(mesh_, nbrFaceCellAddr);
|
syncTools::swapBoundaryFaceList(mesh_, nbrFaceCellAddr);
|
||||||
|
|
||||||
// add internal field contributions
|
// Add internal field contributions
|
||||||
for (label faceI = 0; faceI < nInternalFaces; faceI++)
|
for (label faceI = 0; faceI < nInternalFaces; faceI++)
|
||||||
{
|
{
|
||||||
const label own = cellAddr[mesh_.faceOwner()[faceI]];
|
const label own = cellAddr[mesh_.faceOwner()[faceI]];
|
||||||
@ -189,7 +189,7 @@ void Foam::fv::rotorDiskSource::setFaceArea(vector& axis, const bool correct)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// add boundary contributions
|
// Add boundary contributions
|
||||||
forAll(pbm, patchI)
|
forAll(pbm, patchI)
|
||||||
{
|
{
|
||||||
const polyPatch& pp = pbm[patchI];
|
const polyPatch& pp = pbm[patchI];
|
||||||
@ -262,7 +262,7 @@ void Foam::fv::rotorDiskSource::setFaceArea(vector& axis, const bool correct)
|
|||||||
|
|
||||||
void Foam::fv::rotorDiskSource::createCoordinateSystem()
|
void Foam::fv::rotorDiskSource::createCoordinateSystem()
|
||||||
{
|
{
|
||||||
// construct the local rotor co-prdinate system
|
// Construct the local rotor co-prdinate system
|
||||||
vector origin(vector::zero);
|
vector origin(vector::zero);
|
||||||
vector axis(vector::zero);
|
vector axis(vector::zero);
|
||||||
vector refDir(vector::zero);
|
vector refDir(vector::zero);
|
||||||
@ -274,7 +274,7 @@ void Foam::fv::rotorDiskSource::createCoordinateSystem()
|
|||||||
{
|
{
|
||||||
case gmAuto:
|
case gmAuto:
|
||||||
{
|
{
|
||||||
// determine rotation origin (cell volume weighted)
|
// Determine rotation origin (cell volume weighted)
|
||||||
scalar sumV = 0.0;
|
scalar sumV = 0.0;
|
||||||
const scalarField& V = mesh_.V();
|
const scalarField& V = mesh_.V();
|
||||||
const vectorField& C = mesh_.C();
|
const vectorField& C = mesh_.C();
|
||||||
@ -288,7 +288,7 @@ void Foam::fv::rotorDiskSource::createCoordinateSystem()
|
|||||||
reduce(sumV, sumOp<scalar>());
|
reduce(sumV, sumOp<scalar>());
|
||||||
origin /= sumV;
|
origin /= sumV;
|
||||||
|
|
||||||
// determine first radial vector
|
// Determine first radial vector
|
||||||
vector dx1(vector::zero);
|
vector dx1(vector::zero);
|
||||||
scalar magR = -GREAT;
|
scalar magR = -GREAT;
|
||||||
forAll(cells_, i)
|
forAll(cells_, i)
|
||||||
@ -304,7 +304,7 @@ void Foam::fv::rotorDiskSource::createCoordinateSystem()
|
|||||||
reduce(dx1, maxMagSqrOp<vector>());
|
reduce(dx1, maxMagSqrOp<vector>());
|
||||||
magR = mag(dx1);
|
magR = mag(dx1);
|
||||||
|
|
||||||
// determine second radial vector and cross to determine axis
|
// Determine second radial vector and cross to determine axis
|
||||||
forAll(cells_, i)
|
forAll(cells_, i)
|
||||||
{
|
{
|
||||||
const label cellI = cells_[i];
|
const label cellI = cells_[i];
|
||||||
@ -321,7 +321,7 @@ void Foam::fv::rotorDiskSource::createCoordinateSystem()
|
|||||||
reduce(axis, maxMagSqrOp<vector>());
|
reduce(axis, maxMagSqrOp<vector>());
|
||||||
axis /= mag(axis);
|
axis /= mag(axis);
|
||||||
|
|
||||||
// correct the axis direction using a point above the rotor
|
// Correct the axis direction using a point above the rotor
|
||||||
{
|
{
|
||||||
vector pointAbove(coeffs_.lookup("pointAbove"));
|
vector pointAbove(coeffs_.lookup("pointAbove"));
|
||||||
vector dir = pointAbove - origin;
|
vector dir = pointAbove - origin;
|
||||||
@ -345,7 +345,7 @@ void Foam::fv::rotorDiskSource::createCoordinateSystem()
|
|||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
// set the face areas and apply correction to calculated axis
|
// Set the face areas and apply correction to calculated axis
|
||||||
// e.g. if cellZone is more than a single layer in thickness
|
// e.g. if cellZone is more than a single layer in thickness
|
||||||
setFaceArea(axis, true);
|
setFaceArea(axis, true);
|
||||||
|
|
||||||
@ -405,20 +405,20 @@ void Foam::fv::rotorDiskSource::constructGeometry()
|
|||||||
{
|
{
|
||||||
const label cellI = cells_[i];
|
const label cellI = cells_[i];
|
||||||
|
|
||||||
// position in (planar) rotor co-ordinate system
|
// Position in (planar) rotor co-ordinate system
|
||||||
x_[i] = coordSys_.localPosition(C[cellI]);
|
x_[i] = coordSys_.localPosition(C[cellI]);
|
||||||
|
|
||||||
// cache max radius
|
// Cache max radius
|
||||||
rMax_ = max(rMax_, x_[i].x());
|
rMax_ = max(rMax_, x_[i].x());
|
||||||
|
|
||||||
// swept angle relative to rDir axis [radians] in range 0 -> 2*pi
|
// Swept angle relative to rDir axis [radians] in range 0 -> 2*pi
|
||||||
scalar psi = x_[i].y();
|
scalar psi = x_[i].y();
|
||||||
|
|
||||||
// blade flap angle [radians]
|
// Blade flap angle [radians]
|
||||||
scalar beta =
|
scalar beta =
|
||||||
flap_.beta0 - flap_.beta1c*cos(psi) - flap_.beta2s*sin(psi);
|
flap_.beta0 - flap_.beta1c*cos(psi) - flap_.beta2s*sin(psi);
|
||||||
|
|
||||||
// determine rotation tensor to convert from planar system into the
|
// Determine rotation tensor to convert from planar system into the
|
||||||
// rotor cone system
|
// rotor cone system
|
||||||
scalar c = cos(beta);
|
scalar c = cos(beta);
|
||||||
scalar s = sin(beta);
|
scalar s = sin(beta);
|
||||||
@ -601,7 +601,7 @@ bool Foam::fv::rotorDiskSource::read(const dictionary& dict)
|
|||||||
coeffs_.lookup("fieldNames") >> fieldNames_;
|
coeffs_.lookup("fieldNames") >> fieldNames_;
|
||||||
applied_.setSize(fieldNames_.size(), false);
|
applied_.setSize(fieldNames_.size(), false);
|
||||||
|
|
||||||
// read co-ordinate system/geometry invariant properties
|
// Read co-ordinate system/geometry invariant properties
|
||||||
scalar rpm(readScalar(coeffs_.lookup("rpm")));
|
scalar rpm(readScalar(coeffs_.lookup("rpm")));
|
||||||
omega_ = rpm/60.0*mathematical::twoPi;
|
omega_ = rpm/60.0*mathematical::twoPi;
|
||||||
|
|
||||||
@ -620,10 +620,10 @@ bool Foam::fv::rotorDiskSource::read(const dictionary& dict)
|
|||||||
flap_.beta2s = degToRad(flap_.beta2s);
|
flap_.beta2s = degToRad(flap_.beta2s);
|
||||||
|
|
||||||
|
|
||||||
// create co-ordinate system
|
// Create co-ordinate system
|
||||||
createCoordinateSystem();
|
createCoordinateSystem();
|
||||||
|
|
||||||
// read co-odinate system dependent properties
|
// Read co-odinate system dependent properties
|
||||||
checkData();
|
checkData();
|
||||||
|
|
||||||
constructGeometry();
|
constructGeometry();
|
||||||
|
|||||||
@ -43,7 +43,7 @@ void Foam::fv::rotorDiskSource::calculate
|
|||||||
{
|
{
|
||||||
const scalarField& V = mesh_.V();
|
const scalarField& V = mesh_.V();
|
||||||
|
|
||||||
// logging info
|
// Logging info
|
||||||
scalar dragEff = 0.0;
|
scalar dragEff = 0.0;
|
||||||
scalar liftEff = 0.0;
|
scalar liftEff = 0.0;
|
||||||
scalar AOAmin = GREAT;
|
scalar AOAmin = GREAT;
|
||||||
@ -57,19 +57,19 @@ void Foam::fv::rotorDiskSource::calculate
|
|||||||
|
|
||||||
const scalar radius = x_[i].x();
|
const scalar radius = x_[i].x();
|
||||||
|
|
||||||
// velocity in local cylindrical reference frame
|
// Transform velocity into local cylindrical reference frame
|
||||||
vector Uc = localAxesRotation_->transform(U[cellI], i);
|
vector Uc = localAxesRotation_->invTransform(U[cellI], i);
|
||||||
|
|
||||||
// transform from rotor cylindrical into local coning system
|
// Transform velocity into local coning system
|
||||||
Uc = R_[i] & Uc;
|
Uc = R_[i] & Uc;
|
||||||
|
|
||||||
// set radial component of velocity to zero
|
// Set radial component of velocity to zero
|
||||||
Uc.x() = 0.0;
|
Uc.x() = 0.0;
|
||||||
|
|
||||||
// set blade normal component of velocity
|
// Set blade normal component of velocity
|
||||||
Uc.y() = radius*omega_ - Uc.y();
|
Uc.y() = radius*omega_ - Uc.y();
|
||||||
|
|
||||||
// determine blade data for this radius
|
// Determine blade data for this radius
|
||||||
// i2 = index of upper radius bound data point in blade list
|
// i2 = index of upper radius bound data point in blade list
|
||||||
scalar twist = 0.0;
|
scalar twist = 0.0;
|
||||||
scalar chord = 0.0;
|
scalar chord = 0.0;
|
||||||
@ -78,14 +78,14 @@ void Foam::fv::rotorDiskSource::calculate
|
|||||||
scalar invDr = 0.0;
|
scalar invDr = 0.0;
|
||||||
blade_.interpolate(radius, twist, chord, i1, i2, invDr);
|
blade_.interpolate(radius, twist, chord, i1, i2, invDr);
|
||||||
|
|
||||||
// flip geometric angle if blade is spinning in reverse (clockwise)
|
// Flip geometric angle if blade is spinning in reverse (clockwise)
|
||||||
scalar alphaGeom = thetag[i] + twist;
|
scalar alphaGeom = thetag[i] + twist;
|
||||||
if (omega_ < 0)
|
if (omega_ < 0)
|
||||||
{
|
{
|
||||||
alphaGeom = mathematical::pi - alphaGeom;
|
alphaGeom = mathematical::pi - alphaGeom;
|
||||||
}
|
}
|
||||||
|
|
||||||
// effective angle of attack
|
// Effective angle of attack
|
||||||
scalar alphaEff = alphaGeom - atan2(-Uc.z(), Uc.y());
|
scalar alphaEff = alphaGeom - atan2(-Uc.z(), Uc.y());
|
||||||
if (alphaEff > mathematical::pi)
|
if (alphaEff > mathematical::pi)
|
||||||
{
|
{
|
||||||
@ -99,7 +99,7 @@ void Foam::fv::rotorDiskSource::calculate
|
|||||||
AOAmin = min(AOAmin, alphaEff);
|
AOAmin = min(AOAmin, alphaEff);
|
||||||
AOAmax = max(AOAmax, alphaEff);
|
AOAmax = max(AOAmax, alphaEff);
|
||||||
|
|
||||||
// determine profile data for this radius and angle of attack
|
// Determine profile data for this radius and angle of attack
|
||||||
const label profile1 = blade_.profileID()[i1];
|
const label profile1 = blade_.profileID()[i1];
|
||||||
const label profile2 = blade_.profileID()[i2];
|
const label profile2 = blade_.profileID()[i2];
|
||||||
|
|
||||||
@ -114,24 +114,24 @@ void Foam::fv::rotorDiskSource::calculate
|
|||||||
scalar Cd = invDr*(Cd2 - Cd1) + Cd1;
|
scalar Cd = invDr*(Cd2 - Cd1) + Cd1;
|
||||||
scalar Cl = invDr*(Cl2 - Cl1) + Cl1;
|
scalar Cl = invDr*(Cl2 - Cl1) + Cl1;
|
||||||
|
|
||||||
// apply tip effect for blade lift
|
// Apply tip effect for blade lift
|
||||||
scalar tipFactor = neg(radius/rMax_ - tipEffect_);
|
scalar tipFactor = neg(radius/rMax_ - tipEffect_);
|
||||||
|
|
||||||
// calculate forces perpendicular to blade
|
// Calculate forces perpendicular to blade
|
||||||
scalar pDyn = 0.5*rho[cellI]*magSqr(Uc);
|
scalar pDyn = 0.5*rho[cellI]*magSqr(Uc);
|
||||||
|
|
||||||
scalar f = pDyn*chord*nBlades_*area_[i]/radius/mathematical::twoPi;
|
scalar f = pDyn*chord*nBlades_*area_[i]/radius/mathematical::twoPi;
|
||||||
vector localForce = vector(0.0, -f*Cd, tipFactor*f*Cl);
|
vector localForce = vector(0.0, -f*Cd, tipFactor*f*Cl);
|
||||||
|
|
||||||
// accumulate forces
|
// Accumulate forces
|
||||||
dragEff += rhoRef_*localForce.y();
|
dragEff += rhoRef_*localForce.y();
|
||||||
liftEff += rhoRef_*localForce.z();
|
liftEff += rhoRef_*localForce.z();
|
||||||
|
|
||||||
// convert force from local coning system into rotor cylindrical
|
// Transform force from local coning system into rotor cylindrical
|
||||||
localForce = invR_[i] & localForce;
|
localForce = invR_[i] & localForce;
|
||||||
|
|
||||||
// convert force to global cartesian co-ordinate system
|
// Transform force into global Cartesian co-ordinate system
|
||||||
force[cellI] = localAxesRotation_->invTransform(localForce, i);
|
force[cellI] = localAxesRotation_->transform(localForce, i);
|
||||||
|
|
||||||
if (divideVolume)
|
if (divideVolume)
|
||||||
{
|
{
|
||||||
|
|||||||
@ -103,9 +103,10 @@ void Foam::axesRotation::calcTransform
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// the global->local transformation
|
// Global->local transformation
|
||||||
Rtr_ = Rtr;
|
Rtr_ = Rtr;
|
||||||
// the local->global transformation
|
|
||||||
|
// Local->global transformation
|
||||||
R_ = Rtr.T();
|
R_ = Rtr.T();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -298,7 +299,8 @@ void Foam::axesRotation::operator=(const dictionary& dict)
|
|||||||
}
|
}
|
||||||
else if (dict.found("axis") || dict.found("direction"))
|
else if (dict.found("axis") || dict.found("direction"))
|
||||||
{
|
{
|
||||||
// let it bomb if only one of axis/direction is defined
|
// Both "axis" and "direction" are required
|
||||||
|
// If one is missing the appropriate error message will be generated
|
||||||
order = e3e1;
|
order = e3e1;
|
||||||
dict.lookup("axis") >> axis1;
|
dict.lookup("axis") >> axis1;
|
||||||
dict.lookup("direction") >> axis2;
|
dict.lookup("direction") >> axis2;
|
||||||
|
|||||||
@ -88,6 +88,7 @@ class axesRotation
|
|||||||
const axisOrder& order = e3e1
|
const axisOrder& order = e3e1
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
//- Runtime type information
|
//- Runtime type information
|
||||||
@ -134,7 +135,7 @@ public:
|
|||||||
//- Update the rotation for a list of cells
|
//- Update the rotation for a list of cells
|
||||||
virtual void updateCells(const polyMesh&, const labelList&)
|
virtual void updateCells(const polyMesh&, const labelList&)
|
||||||
{
|
{
|
||||||
// do nothing
|
// Do nothing
|
||||||
}
|
}
|
||||||
|
|
||||||
//- Return local-to-global transformation tensor
|
//- Return local-to-global transformation tensor
|
||||||
@ -196,14 +197,14 @@ public:
|
|||||||
) const;
|
) const;
|
||||||
|
|
||||||
//- Transform vectorField using transformation tensorField and return
|
//- Transform vectorField using transformation tensorField and return
|
||||||
// symmetrical tensorField
|
// symmetric tensorField
|
||||||
virtual tmp<symmTensorField> transformVector
|
virtual tmp<symmTensorField> transformVector
|
||||||
(
|
(
|
||||||
const vectorField& st
|
const vectorField& st
|
||||||
) const;
|
) const;
|
||||||
|
|
||||||
//- Transform vector using transformation tensor and return
|
//- Transform vector using transformation tensor and return
|
||||||
// symmetrical tensor
|
// symmetric tensor
|
||||||
virtual symmTensor transformVector(const vector& st) const;
|
virtual symmTensor transformVector(const vector& st) const;
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user