mirror of
https://develop.openfoam.com/Development/openfoam.git
synced 2025-11-28 03:28:01 +00:00
ENH: Added new rotorDiskSource momentum source model for rotor blades/airfoils
This commit is contained in:
@ -390,6 +390,12 @@ $(basicSource)/actuationDiskSource/actuationDiskSource.C
|
|||||||
$(basicSource)/radialActuationDiskSource/radialActuationDiskSource.C
|
$(basicSource)/radialActuationDiskSource/radialActuationDiskSource.C
|
||||||
$(basicSource)/explicitSource/explicitSource.C
|
$(basicSource)/explicitSource/explicitSource.C
|
||||||
$(basicSource)/explicitSetValue/explicitSetValue.C
|
$(basicSource)/explicitSetValue/explicitSetValue.C
|
||||||
|
$(basicSource)/rotorDiskSource/rotorDiskSource.C
|
||||||
|
$(basicSource)/rotorDiskSource/bladeModel/bladeModel.C
|
||||||
|
$(basicSource)/rotorDiskSource/profileModel/profileModel.C
|
||||||
|
$(basicSource)/rotorDiskSource/profileModel/profileModelList.C
|
||||||
|
$(basicSource)/rotorDiskSource/profileModel/lookup/lookupProfile.C
|
||||||
|
$(basicSource)/rotorDiskSource/profileModel/series/seriesProfile.C
|
||||||
|
|
||||||
|
|
||||||
LIB = $(FOAM_LIBBIN)/libfiniteVolume
|
LIB = $(FOAM_LIBBIN)/libfiniteVolume
|
||||||
|
|||||||
@ -0,0 +1,195 @@
|
|||||||
|
/*---------------------------------------------------------------------------*\
|
||||||
|
========= |
|
||||||
|
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||||
|
\\ / O peration |
|
||||||
|
\\ / A nd | Copyright (C) 2011 OpenFOAM Foundation
|
||||||
|
\\/ M anipulation |
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
License
|
||||||
|
This file is part of OpenFOAM.
|
||||||
|
|
||||||
|
OpenFOAM is free software: you can redistribute it and/or modify it
|
||||||
|
under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
#include "bladeModel.H"
|
||||||
|
#include "unitConversion.H"
|
||||||
|
#include "Tuple2.H"
|
||||||
|
#include "vector.H"
|
||||||
|
#include "IFstream.H"
|
||||||
|
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * //
|
||||||
|
|
||||||
|
bool Foam::bladeModel::readFromFile() const
|
||||||
|
{
|
||||||
|
return fName_ != fileName::null;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Foam::bladeModel::interpolateWeights
|
||||||
|
(
|
||||||
|
const scalar& xIn,
|
||||||
|
const List<scalar>& values,
|
||||||
|
label& i1,
|
||||||
|
label& i2,
|
||||||
|
scalar& ddx
|
||||||
|
) const
|
||||||
|
{
|
||||||
|
scalar x = -GREAT;
|
||||||
|
label nElem = values.size();
|
||||||
|
|
||||||
|
i2 = 0;
|
||||||
|
while ((x < xIn) && (i2 < nElem))
|
||||||
|
{
|
||||||
|
x = values[i2];
|
||||||
|
i2++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (i2 == 0)
|
||||||
|
{
|
||||||
|
i1 = i2;
|
||||||
|
ddx = 0.0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else if (i2 == values.size())
|
||||||
|
{
|
||||||
|
i2 = values.size() - 1;
|
||||||
|
i1 = i2;
|
||||||
|
ddx = 0.0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
i1 = i2 - 1;
|
||||||
|
ddx = (xIn - values[i1])/(values[i2] - values[i1]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
Foam::bladeModel::bladeModel(const dictionary& dict)
|
||||||
|
:
|
||||||
|
profileName_(),
|
||||||
|
profileID_(),
|
||||||
|
radius_(),
|
||||||
|
twist_(),
|
||||||
|
chord_(),
|
||||||
|
fName_(fileName::null)
|
||||||
|
{
|
||||||
|
List<Tuple2<word, vector> > data;
|
||||||
|
if (readFromFile())
|
||||||
|
{
|
||||||
|
IFstream is(fName_);
|
||||||
|
is >> data;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
dict.lookup("data") >> data;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (data.size() > 0)
|
||||||
|
{
|
||||||
|
profileName_.setSize(data.size());
|
||||||
|
profileID_.setSize(data.size());
|
||||||
|
radius_.setSize(data.size());
|
||||||
|
twist_.setSize(data.size());
|
||||||
|
chord_.setSize(data.size());
|
||||||
|
|
||||||
|
forAll(data, i)
|
||||||
|
{
|
||||||
|
profileName_[i] = data[i].first();
|
||||||
|
profileID_[i] = -1;
|
||||||
|
radius_[i] = data[i].second()[0];
|
||||||
|
twist_[i] = degToRad(data[i].second()[1]);
|
||||||
|
chord_[i] = data[i].second()[2];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
FatalErrorIn
|
||||||
|
(
|
||||||
|
"Foam::bladeModel::bladeModel"
|
||||||
|
"("
|
||||||
|
"const dictionary&, "
|
||||||
|
"const word&"
|
||||||
|
")"
|
||||||
|
) << "No blade data specified" << exit(FatalError);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
Foam::bladeModel::~bladeModel()
|
||||||
|
{}
|
||||||
|
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
const Foam::List<Foam::word>& Foam::bladeModel::profileName() const
|
||||||
|
{
|
||||||
|
return profileName_;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const Foam::List<Foam::label>& Foam::bladeModel::profileID() const
|
||||||
|
{
|
||||||
|
return profileID_;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const Foam::List<Foam::scalar>& Foam::bladeModel::radius() const
|
||||||
|
{
|
||||||
|
return radius_;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const Foam::List<Foam::scalar>& Foam::bladeModel::twist() const
|
||||||
|
{
|
||||||
|
return twist_;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const Foam::List<Foam::scalar>& Foam::bladeModel::chord() const
|
||||||
|
{
|
||||||
|
return chord_;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Foam::List<Foam::label>& Foam::bladeModel::profileID()
|
||||||
|
{
|
||||||
|
return profileID_;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Foam::bladeModel::interpolate
|
||||||
|
(
|
||||||
|
const scalar radius,
|
||||||
|
scalar& twist,
|
||||||
|
scalar& chord,
|
||||||
|
label& i1,
|
||||||
|
label& i2,
|
||||||
|
scalar& invDr
|
||||||
|
) const
|
||||||
|
{
|
||||||
|
interpolateWeights(radius, radius_, i1, i2, invDr);
|
||||||
|
|
||||||
|
twist = invDr*(twist_[i2] - twist_[i1]) + twist_[i1];
|
||||||
|
chord = invDr*(chord_[i2] - chord_[i1]) + chord_[i1];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ************************************************************************* //
|
||||||
@ -0,0 +1,151 @@
|
|||||||
|
/*---------------------------------------------------------------------------*\
|
||||||
|
========= |
|
||||||
|
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||||
|
\\ / O peration |
|
||||||
|
\\ / A nd | Copyright (C) 2011 OpenFOAM Foundation
|
||||||
|
\\/ M anipulation |
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
License
|
||||||
|
This file is part of OpenFOAM.
|
||||||
|
|
||||||
|
OpenFOAM is free software: you can redistribute it and/or modify it
|
||||||
|
under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
Class
|
||||||
|
Foam::bladeModel
|
||||||
|
|
||||||
|
Description
|
||||||
|
Blade model class
|
||||||
|
|
||||||
|
SourceFiles
|
||||||
|
bladeModel.C
|
||||||
|
|
||||||
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
#ifndef bladeModel_H
|
||||||
|
#define bladeModel_H
|
||||||
|
|
||||||
|
#include "List.H"
|
||||||
|
#include "dictionary.H"
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
namespace Foam
|
||||||
|
{
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------*\
|
||||||
|
Class bladeModel Declaration
|
||||||
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
class bladeModel
|
||||||
|
{
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
// Protected data
|
||||||
|
|
||||||
|
//- Corresponding profile name per section
|
||||||
|
List<word> profileName_;
|
||||||
|
|
||||||
|
//- Corresponding profile ID per section
|
||||||
|
List<label> profileID_;
|
||||||
|
|
||||||
|
//- Radius [m]
|
||||||
|
List<scalar> radius_;
|
||||||
|
|
||||||
|
//- Twist [deg] on input, converted to [rad]
|
||||||
|
List<scalar> twist_;
|
||||||
|
|
||||||
|
//- Chord [m]
|
||||||
|
List<scalar> chord_;
|
||||||
|
|
||||||
|
//- File name (optional)
|
||||||
|
fileName fName_;
|
||||||
|
|
||||||
|
|
||||||
|
// Protected Member Functions
|
||||||
|
|
||||||
|
//- Return ture if file name is set
|
||||||
|
bool readFromFile() const;
|
||||||
|
|
||||||
|
//- Return the interpolation indices and gradient
|
||||||
|
void interpolateWeights
|
||||||
|
(
|
||||||
|
const scalar& xIn,
|
||||||
|
const List<scalar>& values,
|
||||||
|
label& i1,
|
||||||
|
label& i2,
|
||||||
|
scalar& ddx
|
||||||
|
) const;
|
||||||
|
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
//- Constructor
|
||||||
|
bladeModel(const dictionary& dict);
|
||||||
|
|
||||||
|
|
||||||
|
//- Destructor
|
||||||
|
virtual ~bladeModel();
|
||||||
|
|
||||||
|
|
||||||
|
// Member functions
|
||||||
|
|
||||||
|
// Access
|
||||||
|
|
||||||
|
//- Return const access to the profile name list
|
||||||
|
const List<word>& profileName() const;
|
||||||
|
|
||||||
|
//- Return const access to the profile ID list
|
||||||
|
const List<label>& profileID() const;
|
||||||
|
|
||||||
|
//- Return const access to the radius list
|
||||||
|
const List<scalar>& radius() const;
|
||||||
|
|
||||||
|
//- Return const access to the twist list
|
||||||
|
const List<scalar>& twist() const;
|
||||||
|
|
||||||
|
//- Return const access to the chord list
|
||||||
|
const List<scalar>& chord() const;
|
||||||
|
|
||||||
|
|
||||||
|
// Edit
|
||||||
|
|
||||||
|
//- Return non-const access to the profile ID list
|
||||||
|
List<label>& profileID();
|
||||||
|
|
||||||
|
|
||||||
|
// Evaluation
|
||||||
|
|
||||||
|
//- Return the twist and chord for a given radius
|
||||||
|
virtual void interpolate
|
||||||
|
(
|
||||||
|
const scalar radius,
|
||||||
|
scalar& twist,
|
||||||
|
scalar& chord,
|
||||||
|
label& i1,
|
||||||
|
label& i2,
|
||||||
|
scalar& invDr
|
||||||
|
) const;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
} // End namespace Foam
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// ************************************************************************* //
|
||||||
@ -0,0 +1,148 @@
|
|||||||
|
/*---------------------------------------------------------------------------*\
|
||||||
|
========= |
|
||||||
|
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||||
|
\\ / O peration |
|
||||||
|
\\ / A nd | Copyright (C) 2011 OpenFOAM Foundation
|
||||||
|
\\/ M anipulation |
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
License
|
||||||
|
This file is part of OpenFOAM.
|
||||||
|
|
||||||
|
OpenFOAM is free software: you can redistribute it and/or modify it
|
||||||
|
under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
#include "lookupProfile.H"
|
||||||
|
#include "addToRunTimeSelectionTable.H"
|
||||||
|
#include "vector.H"
|
||||||
|
#include "unitConversion.H"
|
||||||
|
#include "IFstream.H"
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
namespace Foam
|
||||||
|
{
|
||||||
|
defineTypeNameAndDebug(lookupProfile, 0);
|
||||||
|
addToRunTimeSelectionTable(profileModel, lookupProfile, dictionary);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * //
|
||||||
|
|
||||||
|
void Foam::lookupProfile::interpolateWeights
|
||||||
|
(
|
||||||
|
const scalar& xIn,
|
||||||
|
const List<scalar>& values,
|
||||||
|
label& i1,
|
||||||
|
label& i2,
|
||||||
|
scalar& ddx
|
||||||
|
) const
|
||||||
|
{
|
||||||
|
scalar x = -GREAT;
|
||||||
|
label nElem = values.size();
|
||||||
|
|
||||||
|
i2 = 0;
|
||||||
|
while ((x < xIn) && (i2 < nElem))
|
||||||
|
{
|
||||||
|
x = values[i2];
|
||||||
|
i2++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (i2 == 0)
|
||||||
|
{
|
||||||
|
i1 = i2;
|
||||||
|
ddx = 0.0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else if (i2 == values.size())
|
||||||
|
{
|
||||||
|
i2 = values.size() - 1;
|
||||||
|
i1 = i2;
|
||||||
|
ddx = 0.0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
i1 = i2 - 1;
|
||||||
|
ddx = (xIn - values[i1])/(values[i2] - values[i1]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
Foam::lookupProfile::lookupProfile
|
||||||
|
(
|
||||||
|
const dictionary& dict,
|
||||||
|
const word& modelName
|
||||||
|
)
|
||||||
|
:
|
||||||
|
profileModel(dict, modelName),
|
||||||
|
AOA_(),
|
||||||
|
Cd_(),
|
||||||
|
Cl_()
|
||||||
|
{
|
||||||
|
List<vector> data;
|
||||||
|
if (readFromFile())
|
||||||
|
{
|
||||||
|
IFstream is(fName_);
|
||||||
|
is >> data;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
dict.lookup("data") >> data;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (data.size() > 0)
|
||||||
|
{
|
||||||
|
AOA_.setSize(data.size());
|
||||||
|
Cd_.setSize(data.size());
|
||||||
|
Cl_.setSize(data.size());
|
||||||
|
|
||||||
|
forAll(data, i)
|
||||||
|
{
|
||||||
|
AOA_[i] = degToRad(data[i][0]);
|
||||||
|
Cd_[i] = data[i][1];
|
||||||
|
Cl_[i] = data[i][2];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
FatalErrorIn
|
||||||
|
(
|
||||||
|
"Foam::lookupProfile::lookupProfile"
|
||||||
|
"("
|
||||||
|
"const dictionary&, "
|
||||||
|
"const word&"
|
||||||
|
")"
|
||||||
|
) << "No profile data specified" << exit(FatalError);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
void Foam::lookupProfile::Cdl(const scalar alpha, scalar& Cd, scalar& Cl) const
|
||||||
|
{
|
||||||
|
label i1 = -1;
|
||||||
|
label i2 = -1;
|
||||||
|
scalar invAlpha = -1.0;
|
||||||
|
interpolateWeights(alpha, AOA_, i1, i2, invAlpha);
|
||||||
|
|
||||||
|
Cd = invAlpha*(Cd_[i2] - Cd_[i1]) + Cd_[i1];
|
||||||
|
Cl = invAlpha*(Cl_[i2] - Cl_[i1]) + Cl_[i1];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ************************************************************************* //
|
||||||
@ -0,0 +1,124 @@
|
|||||||
|
/*---------------------------------------------------------------------------*\
|
||||||
|
========= |
|
||||||
|
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||||
|
\\ / O peration |
|
||||||
|
\\ / A nd | Copyright (C) 2011 OpenFOAM Foundation
|
||||||
|
\\/ M anipulation |
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
License
|
||||||
|
This file is part of OpenFOAM.
|
||||||
|
|
||||||
|
OpenFOAM is free software: you can redistribute it and/or modify it
|
||||||
|
under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
Class
|
||||||
|
Foam::lookupProfile
|
||||||
|
|
||||||
|
Description
|
||||||
|
Look-up based profile data - drag and lift coefficients are lineraly
|
||||||
|
interpolated based on the supplied angle of attack
|
||||||
|
|
||||||
|
Input in list format:
|
||||||
|
|
||||||
|
data
|
||||||
|
(
|
||||||
|
(AOA1 Cd1 Cl2)
|
||||||
|
(AOA2 Cd2 Cl2)
|
||||||
|
...
|
||||||
|
(AOAN CdN CdN)
|
||||||
|
);
|
||||||
|
|
||||||
|
where:
|
||||||
|
AOA = angle of attack [deg] converted to [rad] internally
|
||||||
|
Cd = drag coefficient
|
||||||
|
Cl = lift coefficient
|
||||||
|
|
||||||
|
SourceFiles
|
||||||
|
lookupProfile.C
|
||||||
|
|
||||||
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
#ifndef lookupProfile_H
|
||||||
|
#define lookupProfile_H
|
||||||
|
|
||||||
|
#include "profileModel.H"
|
||||||
|
#include "List.H"
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
namespace Foam
|
||||||
|
{
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------*\
|
||||||
|
Class lookupProfile Declaration
|
||||||
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
class lookupProfile
|
||||||
|
:
|
||||||
|
public profileModel
|
||||||
|
{
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
// Protected data
|
||||||
|
|
||||||
|
//- List of angle-of-attack values [deg] on input, converted to [rad]
|
||||||
|
List<scalar> AOA_;
|
||||||
|
|
||||||
|
//- List of drag coefficient values
|
||||||
|
List<scalar> Cd_;
|
||||||
|
|
||||||
|
//- List of lift coefficient values
|
||||||
|
List<scalar> Cl_;
|
||||||
|
|
||||||
|
|
||||||
|
// Protected Member Functions
|
||||||
|
|
||||||
|
//- Return the interpolation indices and gradient
|
||||||
|
void interpolateWeights
|
||||||
|
(
|
||||||
|
const scalar& xIn,
|
||||||
|
const List<scalar>& values,
|
||||||
|
label& i1,
|
||||||
|
label& i2,
|
||||||
|
scalar& ddx
|
||||||
|
) const;
|
||||||
|
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
//- Runtime type information
|
||||||
|
TypeName("lookup");
|
||||||
|
|
||||||
|
//- Constructor
|
||||||
|
lookupProfile(const dictionary& dict, const word& modelName);
|
||||||
|
|
||||||
|
|
||||||
|
// Member functions
|
||||||
|
|
||||||
|
// Evaluation
|
||||||
|
|
||||||
|
//- Return the Cd and Cl for a given angle-of-attack
|
||||||
|
virtual void Cdl(const scalar alpha, scalar& Cd, scalar& Cl) const;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
} // End namespace Foam
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// ************************************************************************* //
|
||||||
@ -0,0 +1,99 @@
|
|||||||
|
/*---------------------------------------------------------------------------*\
|
||||||
|
========= |
|
||||||
|
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||||
|
\\ / O peration |
|
||||||
|
\\ / A nd | Copyright (C) 2011 OpenFOAM Foundation
|
||||||
|
\\/ M anipulation |
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
License
|
||||||
|
This file is part of OpenFOAM.
|
||||||
|
|
||||||
|
OpenFOAM is free software: you can redistribute it and/or modify it
|
||||||
|
under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
#include "profileModel.H"
|
||||||
|
#include "addToRunTimeSelectionTable.H"
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
namespace Foam
|
||||||
|
{
|
||||||
|
defineTypeNameAndDebug(profileModel, 0);
|
||||||
|
defineRunTimeSelectionTable(profileModel, dictionary);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * //
|
||||||
|
|
||||||
|
bool Foam::profileModel::readFromFile() const
|
||||||
|
{
|
||||||
|
return fName_ != fileName::null;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
Foam::profileModel::profileModel(const dictionary& dict, const word& name)
|
||||||
|
:
|
||||||
|
dict_(dict),
|
||||||
|
name_(name),
|
||||||
|
fName_(fileName::null)
|
||||||
|
{
|
||||||
|
dict.readIfPresent("fileName", fName_);
|
||||||
|
}
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
Foam::profileModel::~profileModel()
|
||||||
|
{}
|
||||||
|
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
const Foam::word& Foam::profileModel::name() const
|
||||||
|
{
|
||||||
|
return name_;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Foam::autoPtr<Foam::profileModel> Foam::profileModel::New
|
||||||
|
(
|
||||||
|
const dictionary& dict
|
||||||
|
)
|
||||||
|
{
|
||||||
|
const word& modelName(dict.dictName());
|
||||||
|
|
||||||
|
const word modelType(dict.lookup("type"));
|
||||||
|
|
||||||
|
Info<< " - creating " << modelType << " profile " << modelName << endl;
|
||||||
|
|
||||||
|
dictionaryConstructorTable::iterator cstrIter =
|
||||||
|
dictionaryConstructorTablePtr_->find(modelType);
|
||||||
|
|
||||||
|
if (cstrIter == dictionaryConstructorTablePtr_->end())
|
||||||
|
{
|
||||||
|
FatalErrorIn("profileModel::New(const dictionary&)")
|
||||||
|
<< "Unknown profile model type " << modelType
|
||||||
|
<< nl << nl
|
||||||
|
<< "Valid model types are :" << nl
|
||||||
|
<< dictionaryConstructorTablePtr_->sortedToc()
|
||||||
|
<< exit(FatalError);
|
||||||
|
}
|
||||||
|
|
||||||
|
return autoPtr<profileModel>(cstrIter()(dict, modelName));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ************************************************************************* //
|
||||||
@ -0,0 +1,136 @@
|
|||||||
|
/*---------------------------------------------------------------------------*\
|
||||||
|
========= |
|
||||||
|
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||||
|
\\ / O peration |
|
||||||
|
\\ / A nd | Copyright (C) 2011 OpenFOAM Foundation
|
||||||
|
\\/ M anipulation |
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
License
|
||||||
|
This file is part of OpenFOAM.
|
||||||
|
|
||||||
|
OpenFOAM is free software: you can redistribute it and/or modify it
|
||||||
|
under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
Class
|
||||||
|
Foam::profileModel
|
||||||
|
|
||||||
|
Description
|
||||||
|
Base class for profile models
|
||||||
|
|
||||||
|
SourceFiles
|
||||||
|
profileModel.C
|
||||||
|
|
||||||
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
#ifndef profileModel_H
|
||||||
|
#define profileModel_H
|
||||||
|
|
||||||
|
#include "autoPtr.H"
|
||||||
|
#include "runTimeSelectionTables.H"
|
||||||
|
#include "dictionary.H"
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
namespace Foam
|
||||||
|
{
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------*\
|
||||||
|
Class profileModel Declaration
|
||||||
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
class profileModel
|
||||||
|
{
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
// Protected data
|
||||||
|
|
||||||
|
//- Coefficients dictionary
|
||||||
|
const dictionary dict_;
|
||||||
|
|
||||||
|
//- Name of profile model
|
||||||
|
const word name_;
|
||||||
|
|
||||||
|
//- File name (optional)
|
||||||
|
fileName fName_;
|
||||||
|
|
||||||
|
|
||||||
|
// Protected Member Functions
|
||||||
|
|
||||||
|
//- Return ture if file name is set
|
||||||
|
bool readFromFile() const;
|
||||||
|
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
//- Runtime type information
|
||||||
|
TypeName("profileModel");
|
||||||
|
|
||||||
|
|
||||||
|
// Declare run-time constructor selection table
|
||||||
|
declareRunTimeSelectionTable
|
||||||
|
(
|
||||||
|
autoPtr,
|
||||||
|
profileModel,
|
||||||
|
dictionary,
|
||||||
|
(
|
||||||
|
const dictionary& dict,
|
||||||
|
const word& modelName
|
||||||
|
),
|
||||||
|
(dict, modelName)
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
// Selectors
|
||||||
|
|
||||||
|
//- Return a reference to the selected basicSource model
|
||||||
|
static autoPtr<profileModel> New(const dictionary& dict);
|
||||||
|
|
||||||
|
|
||||||
|
//- Constructor
|
||||||
|
profileModel(const dictionary& dict, const word& modelName);
|
||||||
|
|
||||||
|
|
||||||
|
//- Destructor
|
||||||
|
virtual ~profileModel();
|
||||||
|
|
||||||
|
|
||||||
|
// Member functions
|
||||||
|
|
||||||
|
// Access
|
||||||
|
|
||||||
|
//- Return const access to the source name
|
||||||
|
const word& name() const;
|
||||||
|
|
||||||
|
|
||||||
|
// Evaluation
|
||||||
|
|
||||||
|
//- Return the Cd and Cl for a given angle-of-attack
|
||||||
|
virtual void Cdl
|
||||||
|
(
|
||||||
|
const scalar alpha,
|
||||||
|
scalar& Cd,
|
||||||
|
scalar& Cl
|
||||||
|
) const = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
} // End namespace Foam
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// ************************************************************************* //
|
||||||
@ -0,0 +1,121 @@
|
|||||||
|
/*---------------------------------------------------------------------------*\
|
||||||
|
========= |
|
||||||
|
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||||
|
\\ / O peration |
|
||||||
|
\\ / A nd | Copyright (C) 2011 OpenFOAM Foundation
|
||||||
|
\\/ M anipulation |
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
License
|
||||||
|
This file is part of OpenFOAM.
|
||||||
|
|
||||||
|
OpenFOAM is free software: you can redistribute it and/or modify it
|
||||||
|
under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
#include "profileModelList.H"
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
Foam::profileModelList::profileModelList
|
||||||
|
(
|
||||||
|
const dictionary& dict,
|
||||||
|
const bool readFields
|
||||||
|
)
|
||||||
|
:
|
||||||
|
PtrList<profileModel>(),
|
||||||
|
dict_(dict)
|
||||||
|
{
|
||||||
|
if (readFields)
|
||||||
|
{
|
||||||
|
wordList modelNames(dict.toc());
|
||||||
|
|
||||||
|
Info<< " Constructing blade profiles:" << endl;
|
||||||
|
|
||||||
|
if (modelNames.size() > 0)
|
||||||
|
{
|
||||||
|
this->setSize(modelNames.size());
|
||||||
|
|
||||||
|
forAll(modelNames, i)
|
||||||
|
{
|
||||||
|
const word& modelName = modelNames[i];
|
||||||
|
|
||||||
|
this->set
|
||||||
|
(
|
||||||
|
i,
|
||||||
|
profileModel::New(dict.subDict(modelName))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Info<< " none" << endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
Foam::profileModelList::~profileModelList()
|
||||||
|
{}
|
||||||
|
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
void Foam::profileModelList::connectBlades
|
||||||
|
(
|
||||||
|
const List<word>& names,
|
||||||
|
List<label>& addr
|
||||||
|
) const
|
||||||
|
{
|
||||||
|
// construct the addressing between blade sections and profiles
|
||||||
|
forAll(names, bI)
|
||||||
|
{
|
||||||
|
label index = -1;
|
||||||
|
const word& profileName = names[bI];
|
||||||
|
|
||||||
|
forAll(*this, pI)
|
||||||
|
{
|
||||||
|
const profileModel& pm = this->operator[](pI);
|
||||||
|
|
||||||
|
if (pm.name() == profileName)
|
||||||
|
{
|
||||||
|
index = pI;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (index == -1)
|
||||||
|
{
|
||||||
|
List<word> profileNames(size());
|
||||||
|
forAll(*this, i)
|
||||||
|
{
|
||||||
|
const profileModel& pm = this->operator[](i);
|
||||||
|
profileNames[i] = pm.name();
|
||||||
|
}
|
||||||
|
|
||||||
|
FatalErrorIn("void Foam::connectBlades(List<word>& names) const")
|
||||||
|
<< "Profile " << profileName << " could not be found "
|
||||||
|
<< "in profile list. Available profiles are"
|
||||||
|
<< profileNames << exit(FatalError);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
addr[bI] = index;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ************************************************************************* //
|
||||||
@ -0,0 +1,91 @@
|
|||||||
|
/*---------------------------------------------------------------------------*\
|
||||||
|
========= |
|
||||||
|
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||||
|
\\ / O peration |
|
||||||
|
\\ / A nd | Copyright (C) 2011 OpenFOAM Foundation
|
||||||
|
\\/ M anipulation |
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
License
|
||||||
|
This file is part of OpenFOAM.
|
||||||
|
|
||||||
|
OpenFOAM is free software: you can redistribute it and/or modify it
|
||||||
|
under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
Class
|
||||||
|
Foam::profileModelList
|
||||||
|
|
||||||
|
Description
|
||||||
|
Base class for profile models
|
||||||
|
|
||||||
|
SourceFiles
|
||||||
|
profileModel.C
|
||||||
|
|
||||||
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
#ifndef profileModelList_H
|
||||||
|
#define profileModelList_H
|
||||||
|
|
||||||
|
#include "PtrList.H"
|
||||||
|
#include "profileModel.H"
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
namespace Foam
|
||||||
|
{
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------*\
|
||||||
|
Class profileModelList Declaration
|
||||||
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
class profileModelList
|
||||||
|
:
|
||||||
|
public PtrList<profileModel>
|
||||||
|
{
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
// Protected data
|
||||||
|
|
||||||
|
//- Dictionary
|
||||||
|
const dictionary dict_;
|
||||||
|
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
//- Constructor
|
||||||
|
profileModelList(const dictionary& dict, const bool readFields = true);
|
||||||
|
|
||||||
|
//- Destructor
|
||||||
|
~profileModelList();
|
||||||
|
|
||||||
|
|
||||||
|
// Member Functions
|
||||||
|
|
||||||
|
//- Set blade->profile addressing
|
||||||
|
void connectBlades
|
||||||
|
(
|
||||||
|
const List<word>& names,
|
||||||
|
List<label>& addr
|
||||||
|
) const;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
} // End namespace Foam
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// ************************************************************************* //
|
||||||
@ -0,0 +1,116 @@
|
|||||||
|
/*---------------------------------------------------------------------------*\
|
||||||
|
========= |
|
||||||
|
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||||
|
\\ / O peration |
|
||||||
|
\\ / A nd | Copyright (C) 2011 OpenFOAM Foundation
|
||||||
|
\\/ M anipulation |
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
License
|
||||||
|
This file is part of OpenFOAM.
|
||||||
|
|
||||||
|
OpenFOAM is free software: you can redistribute it and/or modify it
|
||||||
|
under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
#include "seriesProfile.H"
|
||||||
|
#include "addToRunTimeSelectionTable.H"
|
||||||
|
#include "IFstream.H"
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
namespace Foam
|
||||||
|
{
|
||||||
|
defineTypeNameAndDebug(seriesProfile, 0);
|
||||||
|
addToRunTimeSelectionTable(profileModel, seriesProfile, dictionary);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * //
|
||||||
|
|
||||||
|
Foam::scalar Foam::seriesProfile::evaluate
|
||||||
|
(
|
||||||
|
const scalar& xIn,
|
||||||
|
const List<scalar>& values
|
||||||
|
) const
|
||||||
|
{
|
||||||
|
scalar result = 0.0;
|
||||||
|
|
||||||
|
forAll(values, i)
|
||||||
|
{
|
||||||
|
result += values[i]*cos((i+1)*xIn);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
Foam::seriesProfile::seriesProfile
|
||||||
|
(
|
||||||
|
const dictionary& dict,
|
||||||
|
const word& modelName
|
||||||
|
)
|
||||||
|
:
|
||||||
|
profileModel(dict, modelName),
|
||||||
|
CdCoeffs_(),
|
||||||
|
ClCoeffs_()
|
||||||
|
{
|
||||||
|
if (readFromFile())
|
||||||
|
{
|
||||||
|
IFstream is(fName_);
|
||||||
|
is >> CdCoeffs_ >> ClCoeffs_;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
dict.lookup("CdCoeffs") >> CdCoeffs_;
|
||||||
|
dict.lookup("ClCoeffs") >> ClCoeffs_;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (CdCoeffs_.empty())
|
||||||
|
{
|
||||||
|
FatalErrorIn
|
||||||
|
(
|
||||||
|
"Foam::seriesProfile::seriesProfile"
|
||||||
|
"("
|
||||||
|
"const dictionary&, "
|
||||||
|
"const word&"
|
||||||
|
")"
|
||||||
|
) << "CdCoeffs must be specified" << exit(FatalError);
|
||||||
|
}
|
||||||
|
if (ClCoeffs_.empty())
|
||||||
|
{
|
||||||
|
FatalErrorIn
|
||||||
|
(
|
||||||
|
"Foam::seriesProfile::seriesProfile"
|
||||||
|
"("
|
||||||
|
"const dictionary&, "
|
||||||
|
"const word&"
|
||||||
|
")"
|
||||||
|
) << "ClCoeffs must be specified" << exit(FatalError);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
void Foam::seriesProfile::Cdl(const scalar alpha, scalar& Cd, scalar& Cl) const
|
||||||
|
{
|
||||||
|
Cd = evaluate(alpha, CdCoeffs_);
|
||||||
|
Cl = evaluate(alpha, ClCoeffs_);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ************************************************************************* //
|
||||||
@ -0,0 +1,116 @@
|
|||||||
|
/*---------------------------------------------------------------------------*\
|
||||||
|
========= |
|
||||||
|
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||||
|
\\ / O peration |
|
||||||
|
\\ / A nd | Copyright (C) 2011 OpenFOAM Foundation
|
||||||
|
\\/ M anipulation |
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
License
|
||||||
|
This file is part of OpenFOAM.
|
||||||
|
|
||||||
|
OpenFOAM is free software: you can redistribute it and/or modify it
|
||||||
|
under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
Class
|
||||||
|
Foam::seriesProfile
|
||||||
|
|
||||||
|
Description
|
||||||
|
Series-up based profile data - drag and lift coefficients computed as
|
||||||
|
sum of cosine series
|
||||||
|
|
||||||
|
Cd = sum_i(CdCoeff)*cos(i*AOA)
|
||||||
|
Cl = sum_i(ClCoeff)*cos(i*AOA)
|
||||||
|
|
||||||
|
where:
|
||||||
|
AOA = angle of attack [deg] converted to [rad] internally
|
||||||
|
Cd = drag coefficent
|
||||||
|
Cl = lift coefficent
|
||||||
|
|
||||||
|
Input in two (arbitrary length) lists:
|
||||||
|
|
||||||
|
CdCoeffs (coeff1 coeff2 ... coeffN);
|
||||||
|
ClCoeffs (coeff1 coeff2 ... coeffN);
|
||||||
|
|
||||||
|
SourceFiles
|
||||||
|
seriesProfile.C
|
||||||
|
|
||||||
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
#ifndef seriesProfile_H
|
||||||
|
#define seriesProfile_H
|
||||||
|
|
||||||
|
#include "profileModel.H"
|
||||||
|
#include "List.H"
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
namespace Foam
|
||||||
|
{
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------*\
|
||||||
|
Class seriesProfile Declaration
|
||||||
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
class seriesProfile
|
||||||
|
:
|
||||||
|
public profileModel
|
||||||
|
{
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
// Protected data
|
||||||
|
|
||||||
|
//- List of drag coefficient values
|
||||||
|
List<scalar> CdCoeffs_;
|
||||||
|
|
||||||
|
//- List of lift coefficient values
|
||||||
|
List<scalar> ClCoeffs_;
|
||||||
|
|
||||||
|
|
||||||
|
// Protected Member Functions
|
||||||
|
|
||||||
|
//- Evaluate
|
||||||
|
scalar evaluate
|
||||||
|
(
|
||||||
|
const scalar& xIn,
|
||||||
|
const List<scalar>& values
|
||||||
|
) const;
|
||||||
|
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
//- Runtime type information
|
||||||
|
TypeName("series");
|
||||||
|
|
||||||
|
//- Constructor
|
||||||
|
seriesProfile(const dictionary& dict, const word& modelName);
|
||||||
|
|
||||||
|
|
||||||
|
// Member functions
|
||||||
|
|
||||||
|
// Evaluation
|
||||||
|
|
||||||
|
//- Return the Cd and Cl for a given angle-of-attack
|
||||||
|
virtual void Cdl(const scalar alpha, scalar& Cd, scalar& Cl) const;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
} // End namespace Foam
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// ************************************************************************* //
|
||||||
@ -0,0 +1,492 @@
|
|||||||
|
/*---------------------------------------------------------------------------*\
|
||||||
|
========= |
|
||||||
|
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||||
|
\\ / O peration |
|
||||||
|
\\ / A nd | Copyright (C) 2011 OpenFOAM Foundation
|
||||||
|
\\/ M anipulation |
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
License
|
||||||
|
This file is part of OpenFOAM.
|
||||||
|
|
||||||
|
OpenFOAM is free software: you can redistribute it and/or modify it
|
||||||
|
under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
#include "rotorDiskSource.H"
|
||||||
|
#include "addToRunTimeSelectionTable.H"
|
||||||
|
#include "mathematicalConstants.H"
|
||||||
|
#include "unitConversion.H"
|
||||||
|
#include "geometricOneField.H"
|
||||||
|
|
||||||
|
using namespace Foam::constant;
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
namespace Foam
|
||||||
|
{
|
||||||
|
defineTypeNameAndDebug(rotorDiskSource, 0);
|
||||||
|
addToRunTimeSelectionTable(basicSource, rotorDiskSource, dictionary);
|
||||||
|
|
||||||
|
template<> const char* NamedEnum<rotorDiskSource::geometryModeType, 2>::
|
||||||
|
names[] =
|
||||||
|
{
|
||||||
|
"auto",
|
||||||
|
"specified"
|
||||||
|
};
|
||||||
|
|
||||||
|
const NamedEnum<rotorDiskSource::geometryModeType, 2>
|
||||||
|
rotorDiskSource::geometryModeTypeNames_;
|
||||||
|
|
||||||
|
template<> const char* NamedEnum<rotorDiskSource::inletFlowType, 3>::
|
||||||
|
names[] =
|
||||||
|
{
|
||||||
|
"fixed",
|
||||||
|
"surfaceNormal",
|
||||||
|
"local"
|
||||||
|
};
|
||||||
|
|
||||||
|
const NamedEnum<rotorDiskSource::inletFlowType, 3>
|
||||||
|
rotorDiskSource::inletFlowTypeNames_;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * //
|
||||||
|
|
||||||
|
void Foam::rotorDiskSource::checkData()
|
||||||
|
{
|
||||||
|
switch (selectionMode())
|
||||||
|
{
|
||||||
|
case smCellSet:
|
||||||
|
case smCellZone:
|
||||||
|
case smAll:
|
||||||
|
{
|
||||||
|
// set the profile ID for each blade section
|
||||||
|
profiles_.connectBlades(blade_.profileName(), blade_.profileID());
|
||||||
|
switch (inletFlow_)
|
||||||
|
{
|
||||||
|
case ifFixed:
|
||||||
|
{
|
||||||
|
coeffs_.lookup("inletVelocity") >> inletVelocity_;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case ifSurfaceNormal:
|
||||||
|
{
|
||||||
|
scalar UIn(readScalar(coeffs_.lookup("inletNormalVelocity")));
|
||||||
|
inletVelocity_ = -coordSys_.e3()*UIn;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case ifLocal:
|
||||||
|
{
|
||||||
|
// do nothing
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
FatalErrorIn("void rotorDiskSource::checkData()")
|
||||||
|
<< "Unknown inlet velocity type" << abort(FatalError);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
FatalErrorIn("void rotorDiskSource::checkData()")
|
||||||
|
<< "Source cannot be used with '"
|
||||||
|
<< selectionModeTypeNames_[selectionMode()]
|
||||||
|
<< "' mode. Please use one of: " << nl
|
||||||
|
<< selectionModeTypeNames_[smCellSet] << nl
|
||||||
|
<< selectionModeTypeNames_[smCellZone] << nl
|
||||||
|
<< selectionModeTypeNames_[smAll]
|
||||||
|
<< exit(FatalError);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Foam::rotorDiskSource::setFaceArea(vector& axis, const bool correct)
|
||||||
|
{
|
||||||
|
// calculate rotor face areas
|
||||||
|
const vectorField& Sf = mesh_.Sf();
|
||||||
|
const scalarField& magSf = mesh_.magSf();
|
||||||
|
|
||||||
|
boolList selectedCells(mesh_.nCells(), false);
|
||||||
|
boolList processedFaces(mesh_.nFaces(), false);
|
||||||
|
UIndirectList<bool>(selectedCells, cells_) = boolList(cells_.size(), true);
|
||||||
|
|
||||||
|
vector n = vector::zero;
|
||||||
|
|
||||||
|
label nFace = 0;
|
||||||
|
area_ = 0.0;
|
||||||
|
forAll(cells_, i)
|
||||||
|
{
|
||||||
|
const label cellI = cells_[i];
|
||||||
|
const cell& cFaces = mesh_.cells()[cellI];
|
||||||
|
forAll(cFaces, j)
|
||||||
|
{
|
||||||
|
const label faceI = cFaces[j];
|
||||||
|
label own = mesh_.owner()[faceI];
|
||||||
|
label nbr = mesh_.neighbour()[faceI];
|
||||||
|
if
|
||||||
|
(
|
||||||
|
!processedFaces[faceI]
|
||||||
|
&& (selectedCells[own] != selectedCells[nbr])
|
||||||
|
)
|
||||||
|
{
|
||||||
|
if (selectedCells[own])
|
||||||
|
{
|
||||||
|
if (((Sf[faceI]/magSf[faceI]) & axis) > 0.8)
|
||||||
|
{
|
||||||
|
area_[i] += magSf[faceI];
|
||||||
|
n += Sf[faceI];
|
||||||
|
nFace++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (selectedCells[nbr])
|
||||||
|
{
|
||||||
|
if (((-Sf[faceI]/magSf[faceI]) & axis) > 0.8)
|
||||||
|
{
|
||||||
|
area_[i] += magSf[faceI];
|
||||||
|
n -= Sf[faceI];
|
||||||
|
nFace++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
processedFaces[faceI] = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (correct && (nFace > 0))
|
||||||
|
{
|
||||||
|
axis = n/mag(n);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Foam::rotorDiskSource::createCoordinateSystem()
|
||||||
|
{
|
||||||
|
// construct the local rotor co-prdinate system
|
||||||
|
vector origin(vector::zero);
|
||||||
|
vector axis(vector::zero);
|
||||||
|
vector refDir(vector::zero);
|
||||||
|
|
||||||
|
geometryModeType gm =
|
||||||
|
geometryModeTypeNames_.read(coeffs_.lookup("geometryMode"));
|
||||||
|
|
||||||
|
switch (gm)
|
||||||
|
{
|
||||||
|
case gmAuto:
|
||||||
|
{
|
||||||
|
// determine rotation origin
|
||||||
|
scalar sumV = 0.0;
|
||||||
|
const scalarField& V = mesh_.V();
|
||||||
|
const vectorField& C = mesh_.C();
|
||||||
|
forAll(cells_, i)
|
||||||
|
{
|
||||||
|
const label cellI = cells_[i];
|
||||||
|
sumV += V[cellI];
|
||||||
|
origin += V[cellI]*C[cellI];
|
||||||
|
}
|
||||||
|
origin /= sumV;
|
||||||
|
|
||||||
|
// determine first radial vector
|
||||||
|
vector dx1(vector::zero);
|
||||||
|
scalar magR = -GREAT;
|
||||||
|
forAll(cells_, i)
|
||||||
|
{
|
||||||
|
const label cellI = cells_[i];
|
||||||
|
vector test = C[cellI] - origin;
|
||||||
|
if (mag(test) > magR)
|
||||||
|
{
|
||||||
|
dx1 = test;
|
||||||
|
magR = mag(test);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// determine second radial vector and cross to determine axis
|
||||||
|
forAll(cells_, i)
|
||||||
|
{
|
||||||
|
const label cellI = cells_[i];
|
||||||
|
vector dx2 = C[cellI] - origin;
|
||||||
|
if (mag(dx2) > 0.5*magR)
|
||||||
|
{
|
||||||
|
axis = dx1 ^ dx2;
|
||||||
|
if (mag(axis) > SMALL)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
axis /= mag(axis);
|
||||||
|
|
||||||
|
// axis direction is somewhat arbitrary - check if user needs
|
||||||
|
// needs to reverse
|
||||||
|
bool reverse(readBool(coeffs_.lookup("reverseAxis")));
|
||||||
|
if (reverse)
|
||||||
|
{
|
||||||
|
axis *= -1.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
coeffs_.lookup("refDirection") >> refDir;
|
||||||
|
|
||||||
|
// set the face areas and apply correction to calculated axis
|
||||||
|
// e.g. if cellZone is more than a single layer in thickness
|
||||||
|
setFaceArea(axis, true);
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case gmSpecified:
|
||||||
|
{
|
||||||
|
coeffs_.lookup("origin") >> origin;
|
||||||
|
coeffs_.lookup("axis") >> axis;
|
||||||
|
coeffs_.lookup("refDirection") >> refDir;
|
||||||
|
|
||||||
|
setFaceArea(axis, false);
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
FatalErrorIn
|
||||||
|
(
|
||||||
|
"rotorDiskSource::createCoordinateSystem(const geometryMode&);"
|
||||||
|
) << "Unknown geometryMode " << geometryModeTypeNames_[gm]
|
||||||
|
<< ". Available geometry modes include " << geometryModeTypeNames_
|
||||||
|
<< exit(FatalError);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
coordSys_ = cylindricalCS("rotorCoordSys", origin, axis, refDir, false);
|
||||||
|
|
||||||
|
const scalar sumArea = gSum(area_);
|
||||||
|
const scalar diameter = Foam::sqrt(4.0*sumArea/mathematical::pi);
|
||||||
|
Info<< " Rotor gometry:" << nl
|
||||||
|
<< " - disk diameter = " << diameter << nl
|
||||||
|
<< " - disk area = " << sumArea << nl
|
||||||
|
<< " - origin = " << coordSys_.origin() << nl
|
||||||
|
<< " - r-axis = " << coordSys_.e1() << nl
|
||||||
|
<< " - psi-axis = " << coordSys_.e2() << nl
|
||||||
|
<< " - z-axis = " << coordSys_.e3() << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Foam::rotorDiskSource::constructGeometry()
|
||||||
|
{
|
||||||
|
const vectorField& C = mesh_.C();
|
||||||
|
|
||||||
|
const vector rDir = coordSys_.e1();
|
||||||
|
const vector zDir = coordSys_.e3();
|
||||||
|
|
||||||
|
forAll(cells_, i)
|
||||||
|
{
|
||||||
|
const label cellI = cells_[i];
|
||||||
|
|
||||||
|
// position in rotor co-ordinate system
|
||||||
|
x_[i] = coordSys_.localPosition(C[cellI]);
|
||||||
|
|
||||||
|
// cache max radius
|
||||||
|
rMax_ = max(rMax_, x_[i].x());
|
||||||
|
|
||||||
|
// determine swept angle relative to rDir axis
|
||||||
|
scalar psi = x_[i].y() - rDir.y();
|
||||||
|
|
||||||
|
// blade flap angle
|
||||||
|
scalar beta = flap_.beta0 - flap_.beta1*cos(psi) - flap_.beta2*sin(psi);
|
||||||
|
|
||||||
|
// determine rotation tensor to convert into the rotor cone plane
|
||||||
|
scalar c = cos(-beta);
|
||||||
|
scalar s = sin(-beta);
|
||||||
|
R_[i] = tensor(1, 0, 0, 0, c, s, 0, -s, c);
|
||||||
|
|
||||||
|
// geometric angle of attack - not including twist
|
||||||
|
alphag_[i] = trim_.alphaC - trim_.A*cos(psi) - trim_.B*sin(psi);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Foam::tmp<Foam::vectorField> Foam::rotorDiskSource::inflowVelocity
|
||||||
|
(
|
||||||
|
const volVectorField& U
|
||||||
|
) const
|
||||||
|
{
|
||||||
|
switch (inletFlow_)
|
||||||
|
{
|
||||||
|
case ifFixed:
|
||||||
|
case ifSurfaceNormal:
|
||||||
|
{
|
||||||
|
return tmp<vectorField>
|
||||||
|
(
|
||||||
|
new vectorField(mesh_.nCells(), inletVelocity_)
|
||||||
|
);
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case ifLocal:
|
||||||
|
{
|
||||||
|
return U.internalField();
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
FatalErrorIn
|
||||||
|
(
|
||||||
|
"Foam::tmp<Foam::vectorField> "
|
||||||
|
"Foam::rotorDiskSource::inflowVelocity"
|
||||||
|
"(const volVectorField&) const"
|
||||||
|
) << "Unknown inlet flow specification" << abort(FatalError);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return tmp<vectorField>(new vectorField(mesh_.nCells(), vector::zero));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
Foam::rotorDiskSource::rotorDiskSource
|
||||||
|
(
|
||||||
|
const word& name,
|
||||||
|
const word& modelType,
|
||||||
|
const dictionary& dict,
|
||||||
|
const fvMesh& mesh
|
||||||
|
|
||||||
|
)
|
||||||
|
:
|
||||||
|
basicSource(name, modelType, dict, mesh),
|
||||||
|
coeffs_(dict_.subDict(type() + "Coeffs")),
|
||||||
|
rhoName_("none"),
|
||||||
|
omega_(0.0),
|
||||||
|
nBlades_(0),
|
||||||
|
inletFlow_(ifLocal),
|
||||||
|
inletVelocity_(vector::zero),
|
||||||
|
tipEffect_(1.0),
|
||||||
|
flap_(),
|
||||||
|
trim_(),
|
||||||
|
blade_(coeffs_.subDict("blade")),
|
||||||
|
profiles_(coeffs_.subDict("profiles")),
|
||||||
|
x_(cells_.size(), vector::zero),
|
||||||
|
R_(cells_.size(), I),
|
||||||
|
alphag_(cells_.size(), 0.0),
|
||||||
|
area_(cells_.size(), 0.0),
|
||||||
|
coordSys_(false),
|
||||||
|
rMax_(0.0)
|
||||||
|
{
|
||||||
|
read(dict);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
Foam::rotorDiskSource::~rotorDiskSource()
|
||||||
|
{}
|
||||||
|
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
void Foam::rotorDiskSource::addSu(fvMatrix<vector>& UEqn)
|
||||||
|
{
|
||||||
|
// add source to lhs of eqn
|
||||||
|
|
||||||
|
const volVectorField& U = UEqn.psi();
|
||||||
|
|
||||||
|
if (UEqn.dimensions() == dimForce)
|
||||||
|
{
|
||||||
|
coeffs_.lookup("rhoName") >> rhoName_;
|
||||||
|
|
||||||
|
const volScalarField& rho =
|
||||||
|
mesh_.lookupObject<volScalarField>(rhoName_);
|
||||||
|
|
||||||
|
UEqn += calculateForces
|
||||||
|
(
|
||||||
|
rho.internalField(),
|
||||||
|
inflowVelocity(U),
|
||||||
|
dimForce/dimVolume
|
||||||
|
);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
UEqn += calculateForces
|
||||||
|
(
|
||||||
|
oneField(),
|
||||||
|
inflowVelocity(U),
|
||||||
|
dimForce/dimVolume/dimDensity
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Foam::rotorDiskSource::addSu(fvMatrix<scalar>& UEqn)
|
||||||
|
{
|
||||||
|
// do nothing
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Foam::rotorDiskSource::writeData(Ostream& os) const
|
||||||
|
{
|
||||||
|
os << indent << name_ << endl;
|
||||||
|
dict_.write(os);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool Foam::rotorDiskSource::read(const dictionary& dict)
|
||||||
|
{
|
||||||
|
if (basicSource::read(dict))
|
||||||
|
{
|
||||||
|
coeffs_ = dict.subDict(type() + "Coeffs");
|
||||||
|
|
||||||
|
scalar rpm(readScalar(coeffs_.lookup("rpm")));
|
||||||
|
omega_ = rpm/60.0*mathematical::twoPi;
|
||||||
|
|
||||||
|
coeffs_.lookup("nBlades") >> nBlades_;
|
||||||
|
|
||||||
|
inletFlow_ = inletFlowTypeNames_.read(coeffs_.lookup("inletFlowType"));
|
||||||
|
|
||||||
|
coeffs_.lookup("tipEffect") >> tipEffect_;
|
||||||
|
|
||||||
|
const dictionary& flapCoeffs(coeffs_.subDict("flapCoeffs"));
|
||||||
|
flapCoeffs.lookup("beta0") >> flap_.beta0;
|
||||||
|
flapCoeffs.lookup("beta1") >> flap_.beta1;
|
||||||
|
flapCoeffs.lookup("beta2") >> flap_.beta2;
|
||||||
|
flap_.beta0 = degToRad(flap_.beta0);
|
||||||
|
|
||||||
|
const dictionary& trimCoeffs(coeffs_.subDict("trimCoeffs"));
|
||||||
|
trimCoeffs.lookup("alphaC") >> trim_.alphaC;
|
||||||
|
trimCoeffs.lookup("A") >> trim_.A;
|
||||||
|
trimCoeffs.lookup("B") >> trim_.B;
|
||||||
|
trim_.alphaC = degToRad(trim_.alphaC);
|
||||||
|
|
||||||
|
checkData();
|
||||||
|
|
||||||
|
createCoordinateSystem();
|
||||||
|
|
||||||
|
constructGeometry();
|
||||||
|
|
||||||
|
if (debug)
|
||||||
|
{
|
||||||
|
writeField("alphag", alphag_, true);
|
||||||
|
writeField("faceArea", area_, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ************************************************************************* //
|
||||||
@ -0,0 +1,249 @@
|
|||||||
|
/*---------------------------------------------------------------------------*\
|
||||||
|
========= |
|
||||||
|
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||||
|
\\ / O peration |
|
||||||
|
\\ / A nd | Copyright (C) 2011 OpenFOAM Foundation
|
||||||
|
\\/ M anipulation |
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
License
|
||||||
|
This file is part of OpenFOAM.
|
||||||
|
|
||||||
|
OpenFOAM is free software: you can redistribute it and/or modify it
|
||||||
|
under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
Class
|
||||||
|
Foam::rotorDiskSource
|
||||||
|
|
||||||
|
Description
|
||||||
|
Cell-zone based momemtum source
|
||||||
|
|
||||||
|
Source approximates the mean effects of rotor forces on a cylindrical
|
||||||
|
region within the domain
|
||||||
|
|
||||||
|
SourceFiles
|
||||||
|
rotorDiskSource.C
|
||||||
|
rotorDiskSourceTemplates.C
|
||||||
|
|
||||||
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
#ifndef rotorDiskSource_H
|
||||||
|
#define rotorDiskSource_H
|
||||||
|
|
||||||
|
#include "basicSource.H"
|
||||||
|
#include "cylindricalCS.H"
|
||||||
|
#include "NamedEnum.H"
|
||||||
|
#include "bladeModel.H"
|
||||||
|
#include "profileModelList.H"
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
namespace Foam
|
||||||
|
{
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------*\
|
||||||
|
Class rotorDiskSource Declaration
|
||||||
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
class rotorDiskSource
|
||||||
|
:
|
||||||
|
public basicSource
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
enum geometryModeType
|
||||||
|
{
|
||||||
|
gmAuto,
|
||||||
|
gmSpecified
|
||||||
|
};
|
||||||
|
static const NamedEnum<geometryModeType, 2> geometryModeTypeNames_;
|
||||||
|
|
||||||
|
enum inletFlowType
|
||||||
|
{
|
||||||
|
ifFixed,
|
||||||
|
ifSurfaceNormal,
|
||||||
|
ifLocal
|
||||||
|
};
|
||||||
|
static const NamedEnum<inletFlowType, 3> inletFlowTypeNames_;
|
||||||
|
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
// Helper structures to encapsulate flap and trim data
|
||||||
|
|
||||||
|
struct flapData
|
||||||
|
{
|
||||||
|
scalar beta0; // coning angle [deg]
|
||||||
|
scalar beta1; // lateral flapping coeff
|
||||||
|
scalar beta2; // longitudinal flapping coeff
|
||||||
|
};
|
||||||
|
|
||||||
|
struct trimData
|
||||||
|
{
|
||||||
|
scalar alphaC; // collective pitch angle [deg]
|
||||||
|
scalar A; // lateral cyclic coeff
|
||||||
|
scalar B; // longitudinal cyclic coeff
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// Protected data
|
||||||
|
|
||||||
|
//- Coefficients dictionary
|
||||||
|
dictionary coeffs_;
|
||||||
|
|
||||||
|
//- Name of density field
|
||||||
|
word rhoName_;
|
||||||
|
|
||||||
|
//- Rotational speed [rad/s]
|
||||||
|
scalar omega_;
|
||||||
|
|
||||||
|
//- Number of blades
|
||||||
|
label nBlades_;
|
||||||
|
|
||||||
|
//- Inlet flow type
|
||||||
|
inletFlowType inletFlow_;
|
||||||
|
|
||||||
|
//- Inlet velocity for specified iinflow
|
||||||
|
vector inletVelocity_;
|
||||||
|
|
||||||
|
//- Tip effect [0-1]
|
||||||
|
// Ratio of blade radius beyond which lift=0
|
||||||
|
scalar tipEffect_;
|
||||||
|
|
||||||
|
//- Blade flap coefficients [rad/s]
|
||||||
|
flapData flap_;
|
||||||
|
|
||||||
|
//- Blad trim coefficients
|
||||||
|
trimData trim_;
|
||||||
|
|
||||||
|
//- Blade data
|
||||||
|
bladeModel blade_;
|
||||||
|
|
||||||
|
//- Profile data
|
||||||
|
profileModelList profiles_;
|
||||||
|
|
||||||
|
//- Cell centre positions in local rotor frame (Cartesian x, y, z)
|
||||||
|
List<point> x_;
|
||||||
|
|
||||||
|
//- Rotation tensor for flap angle
|
||||||
|
List<tensor> R_;
|
||||||
|
|
||||||
|
//- Geometric angle of attack [deg]
|
||||||
|
List<scalar> alphag_;
|
||||||
|
|
||||||
|
//- Area [m2]
|
||||||
|
List<scalar> area_;
|
||||||
|
|
||||||
|
//- Rotor co-ordinate system (r, theta, z)
|
||||||
|
cylindricalCS coordSys_;
|
||||||
|
|
||||||
|
//- Maximum radius
|
||||||
|
scalar rMax_;
|
||||||
|
|
||||||
|
|
||||||
|
// Protected Member Functions
|
||||||
|
|
||||||
|
//- Check data
|
||||||
|
void checkData();
|
||||||
|
|
||||||
|
//- Set the face areas per cell, and optionally correct the rotor axis
|
||||||
|
void setFaceArea(vector& axis, const bool correct);
|
||||||
|
|
||||||
|
//- Create the co-ordinate system
|
||||||
|
void createCoordinateSystem();
|
||||||
|
|
||||||
|
//- Construct geometry
|
||||||
|
void constructGeometry();
|
||||||
|
|
||||||
|
//- Return the inlet flow field
|
||||||
|
tmp<vectorField> inflowVelocity(const volVectorField& U) const;
|
||||||
|
|
||||||
|
//- Calculate forces
|
||||||
|
template<class RhoType>
|
||||||
|
tmp<volVectorField> calculateForces
|
||||||
|
(
|
||||||
|
const RhoType& rho,
|
||||||
|
const vectorField& U,
|
||||||
|
const dimensionSet& dims
|
||||||
|
);
|
||||||
|
|
||||||
|
//- Helper function to write rotor values
|
||||||
|
template<class Type>
|
||||||
|
void writeField
|
||||||
|
(
|
||||||
|
const word& name,
|
||||||
|
const List<Type>& values,
|
||||||
|
const bool writeNow = false
|
||||||
|
) const;
|
||||||
|
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
//- Runtime type information
|
||||||
|
TypeName("rotorDisk");
|
||||||
|
|
||||||
|
|
||||||
|
// Constructors
|
||||||
|
|
||||||
|
|
||||||
|
//- Construct from components
|
||||||
|
rotorDiskSource
|
||||||
|
(
|
||||||
|
const word& name,
|
||||||
|
const word& modelType,
|
||||||
|
const dictionary& dict,
|
||||||
|
const fvMesh& mesh
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
//- Destructor
|
||||||
|
virtual ~rotorDiskSource();
|
||||||
|
|
||||||
|
|
||||||
|
// Member Functions
|
||||||
|
|
||||||
|
|
||||||
|
// Source term addition
|
||||||
|
|
||||||
|
//- Source term to fvMatrix<vector>
|
||||||
|
virtual void addSu(fvMatrix<vector>& UEqn);
|
||||||
|
|
||||||
|
//- Source term to fvMatrix<scalar>
|
||||||
|
virtual void addSu(fvMatrix<scalar>& UEqn);
|
||||||
|
|
||||||
|
|
||||||
|
// I-O
|
||||||
|
|
||||||
|
//- Write the source properties
|
||||||
|
virtual void writeData(Ostream&) const;
|
||||||
|
|
||||||
|
//- Read source dictionary
|
||||||
|
virtual bool read(const dictionary& dict);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
} // End namespace Foam
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
#ifdef NoRepository
|
||||||
|
#include "rotorDiskSourceTemplates.C"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// ************************************************************************* //
|
||||||
|
|
||||||
@ -0,0 +1,205 @@
|
|||||||
|
/*---------------------------------------------------------------------------*\
|
||||||
|
========= |
|
||||||
|
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||||
|
\\ / O peration |
|
||||||
|
\\ / A nd | Copyright (C) 2011 OpenFOAM Foundation
|
||||||
|
\\/ M anipulation |
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
License
|
||||||
|
This file is part of OpenFOAM.
|
||||||
|
|
||||||
|
OpenFOAM is free software: you can redistribute it and/or modify it
|
||||||
|
under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
#include "rotorDiskSource.H"
|
||||||
|
#include "addToRunTimeSelectionTable.H"
|
||||||
|
#include "mathematicalConstants.H"
|
||||||
|
#include "unitConversion.H"
|
||||||
|
|
||||||
|
using namespace Foam::constant;
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * //
|
||||||
|
|
||||||
|
template<class Type>
|
||||||
|
void Foam::rotorDiskSource::writeField
|
||||||
|
(
|
||||||
|
const word& name,
|
||||||
|
const List<Type>& values,
|
||||||
|
const bool writeNow
|
||||||
|
) const
|
||||||
|
{
|
||||||
|
typedef GeometricField<Type, fvPatchField, volMesh> fieldType;
|
||||||
|
|
||||||
|
if (mesh_.time().outputTime() || writeNow)
|
||||||
|
{
|
||||||
|
tmp<fieldType> tfld
|
||||||
|
(
|
||||||
|
new fieldType
|
||||||
|
(
|
||||||
|
IOobject
|
||||||
|
(
|
||||||
|
name,
|
||||||
|
mesh_.time().timeName(),
|
||||||
|
mesh_,
|
||||||
|
IOobject::NO_READ,
|
||||||
|
IOobject::NO_WRITE
|
||||||
|
),
|
||||||
|
mesh_,
|
||||||
|
dimensioned<Type>("zero", dimless, pTraits<Type>::zero)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
Field<Type>& fld = tfld().internalField();
|
||||||
|
|
||||||
|
if (cells_.size() != values.size())
|
||||||
|
{
|
||||||
|
FatalErrorIn("") << "cells_.size() != values_.size()"
|
||||||
|
<< abort(FatalError);
|
||||||
|
}
|
||||||
|
|
||||||
|
forAll(cells_, i)
|
||||||
|
{
|
||||||
|
const label cellI = cells_[i];
|
||||||
|
fld[cellI] = values[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
tfld().write();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template<class RhoType>
|
||||||
|
Foam::tmp<Foam::volVectorField> Foam::rotorDiskSource::calculateForces
|
||||||
|
(
|
||||||
|
const RhoType& rho,
|
||||||
|
const vectorField& U,
|
||||||
|
const dimensionSet& dims
|
||||||
|
)
|
||||||
|
{
|
||||||
|
tmp<volVectorField> tForce
|
||||||
|
(
|
||||||
|
new volVectorField
|
||||||
|
(
|
||||||
|
IOobject
|
||||||
|
(
|
||||||
|
"rotorForce",
|
||||||
|
mesh_.time().timeName(),
|
||||||
|
mesh_,
|
||||||
|
IOobject::NO_READ,
|
||||||
|
IOobject::NO_WRITE
|
||||||
|
),
|
||||||
|
mesh_,
|
||||||
|
dimensionedVector("zero", dims, vector::zero)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
vectorField& force = tForce().internalField();
|
||||||
|
const scalarField& V = mesh_.V();
|
||||||
|
|
||||||
|
|
||||||
|
// logging info
|
||||||
|
scalar dragEff = 0.0;
|
||||||
|
scalar liftEff = 0.0;
|
||||||
|
scalar AOAmin = GREAT;
|
||||||
|
scalar AOAmax = -GREAT;
|
||||||
|
|
||||||
|
forAll(cells_, i)
|
||||||
|
{
|
||||||
|
if (area_[i] > ROOTVSMALL)
|
||||||
|
{
|
||||||
|
const label cellI = cells_[i];
|
||||||
|
|
||||||
|
const scalar radius = x_[i].x();
|
||||||
|
|
||||||
|
// apply correction due to flap in cartesian frame
|
||||||
|
vector Uc = R_[i] & U[cellI];
|
||||||
|
|
||||||
|
// velocity in local reference frame
|
||||||
|
Uc = coordSys_.localVector(Uc);
|
||||||
|
|
||||||
|
// set radial component of velocity to zero
|
||||||
|
Uc.x() = 0.0;
|
||||||
|
|
||||||
|
// remove blade linear velocity from blade normal component
|
||||||
|
Uc.y() -= radius*omega_;
|
||||||
|
|
||||||
|
// velocity magnitude
|
||||||
|
scalar magUc = mag(Uc);
|
||||||
|
|
||||||
|
// determine blade data for this radius
|
||||||
|
// i1 = index of upper bound data point in blade list
|
||||||
|
scalar twist = 0.0;
|
||||||
|
scalar chord = 0.0;
|
||||||
|
label i1 = -1;
|
||||||
|
label i2 = -1;
|
||||||
|
scalar invDr = 0.0;
|
||||||
|
blade_.interpolate(radius, twist, chord, i1, i2, invDr);
|
||||||
|
|
||||||
|
// effective angle of attack
|
||||||
|
scalar alphaEff = alphag_[i] + twist - atan(Uc.z()/Uc.y());
|
||||||
|
AOAmin = min(AOAmin, alphaEff);
|
||||||
|
AOAmax = max(AOAmax, alphaEff);
|
||||||
|
|
||||||
|
// determine profile data for this radius and angle of attack
|
||||||
|
const label profile1 = blade_.profileID()[i1];
|
||||||
|
const label profile2 = blade_.profileID()[i2];
|
||||||
|
|
||||||
|
scalar Cd1 = 0.0;
|
||||||
|
scalar Cl1 = 0.0;
|
||||||
|
profiles_[profile1].Cdl(alphaEff, Cd1, Cl1);
|
||||||
|
|
||||||
|
scalar Cd2 = 0.0;
|
||||||
|
scalar Cl2 = 0.0;
|
||||||
|
profiles_[profile2].Cdl(alphaEff, Cd2, Cl2);
|
||||||
|
|
||||||
|
scalar Cd = invDr*(Cd2 - Cd1) + Cd1;
|
||||||
|
scalar Cl = invDr*(Cl2 - Cl1) + Cl1;
|
||||||
|
|
||||||
|
// apply tip effect for blade lift
|
||||||
|
scalar tipFactor = 1.0;
|
||||||
|
if (radius/rMax_ > tipEffect_)
|
||||||
|
{
|
||||||
|
tipFactor = 0.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// calculate forces
|
||||||
|
scalar pDyn = 0.5*rho[cellI]*sqr(magUc);
|
||||||
|
scalar f = pDyn*chord*nBlades_*area_[i]/(mathematical::twoPi);
|
||||||
|
vector localForce = vector(0.0, f*Cd, tipFactor*f*Cl);
|
||||||
|
|
||||||
|
// accumulate forces
|
||||||
|
dragEff += localForce.y();
|
||||||
|
liftEff += localForce.z();
|
||||||
|
|
||||||
|
// convert force to global cartesian co-ordinate system
|
||||||
|
force[cellI] = coordSys_.globalVector(localForce);
|
||||||
|
|
||||||
|
force[cellI] /= V[cellI];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Info<< type() << " output:" << nl
|
||||||
|
<< " min/max(AOA) = " << radToDeg(AOAmin) << ", "
|
||||||
|
<< radToDeg(AOAmax) << nl
|
||||||
|
<< " Effective drag = " << dragEff << nl
|
||||||
|
<< " Effective lift = " << liftEff << endl;
|
||||||
|
|
||||||
|
|
||||||
|
return tForce;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ************************************************************************* //
|
||||||
Reference in New Issue
Block a user