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:
@ -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