From dd506c3f14a130bcb4ce28bfb9318487889e46d7 Mon Sep 17 00:00:00 2001 From: andy <andy> Date: Thu, 20 Oct 2011 16:40:04 +0100 Subject: [PATCH] ENH: Added new rotorDiskSource momentum source model for rotor blades/airfoils --- src/finiteVolume/Make/files | 6 + .../rotorDiskSource/bladeModel/bladeModel.C | 195 +++++++ .../rotorDiskSource/bladeModel/bladeModel.H | 151 ++++++ .../profileModel/lookup/lookupProfile.C | 148 ++++++ .../profileModel/lookup/lookupProfile.H | 124 +++++ .../profileModel/profileModel.C | 99 ++++ .../profileModel/profileModel.H | 136 +++++ .../profileModel/profileModelList.C | 121 +++++ .../profileModel/profileModelList.H | 91 ++++ .../profileModel/series/seriesProfile.C | 116 +++++ .../profileModel/series/seriesProfile.H | 116 +++++ .../rotorDiskSource/rotorDiskSource.C | 492 ++++++++++++++++++ .../rotorDiskSource/rotorDiskSource.H | 249 +++++++++ .../rotorDiskSourceTemplates.C | 205 ++++++++ 14 files changed, 2249 insertions(+) create mode 100644 src/finiteVolume/cfdTools/general/fieldSources/basicSource/rotorDiskSource/bladeModel/bladeModel.C create mode 100644 src/finiteVolume/cfdTools/general/fieldSources/basicSource/rotorDiskSource/bladeModel/bladeModel.H create mode 100644 src/finiteVolume/cfdTools/general/fieldSources/basicSource/rotorDiskSource/profileModel/lookup/lookupProfile.C create mode 100644 src/finiteVolume/cfdTools/general/fieldSources/basicSource/rotorDiskSource/profileModel/lookup/lookupProfile.H create mode 100644 src/finiteVolume/cfdTools/general/fieldSources/basicSource/rotorDiskSource/profileModel/profileModel.C create mode 100644 src/finiteVolume/cfdTools/general/fieldSources/basicSource/rotorDiskSource/profileModel/profileModel.H create mode 100644 src/finiteVolume/cfdTools/general/fieldSources/basicSource/rotorDiskSource/profileModel/profileModelList.C create mode 100644 src/finiteVolume/cfdTools/general/fieldSources/basicSource/rotorDiskSource/profileModel/profileModelList.H create mode 100644 src/finiteVolume/cfdTools/general/fieldSources/basicSource/rotorDiskSource/profileModel/series/seriesProfile.C create mode 100644 src/finiteVolume/cfdTools/general/fieldSources/basicSource/rotorDiskSource/profileModel/series/seriesProfile.H create mode 100644 src/finiteVolume/cfdTools/general/fieldSources/basicSource/rotorDiskSource/rotorDiskSource.C create mode 100644 src/finiteVolume/cfdTools/general/fieldSources/basicSource/rotorDiskSource/rotorDiskSource.H create mode 100644 src/finiteVolume/cfdTools/general/fieldSources/basicSource/rotorDiskSource/rotorDiskSourceTemplates.C diff --git a/src/finiteVolume/Make/files b/src/finiteVolume/Make/files index 3bcd7b80d55..cc2f3e4225a 100644 --- a/src/finiteVolume/Make/files +++ b/src/finiteVolume/Make/files @@ -390,6 +390,12 @@ $(basicSource)/actuationDiskSource/actuationDiskSource.C $(basicSource)/radialActuationDiskSource/radialActuationDiskSource.C $(basicSource)/explicitSource/explicitSource.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 diff --git a/src/finiteVolume/cfdTools/general/fieldSources/basicSource/rotorDiskSource/bladeModel/bladeModel.C b/src/finiteVolume/cfdTools/general/fieldSources/basicSource/rotorDiskSource/bladeModel/bladeModel.C new file mode 100644 index 00000000000..a1f76d3e993 --- /dev/null +++ b/src/finiteVolume/cfdTools/general/fieldSources/basicSource/rotorDiskSource/bladeModel/bladeModel.C @@ -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]; +} + + +// ************************************************************************* // diff --git a/src/finiteVolume/cfdTools/general/fieldSources/basicSource/rotorDiskSource/bladeModel/bladeModel.H b/src/finiteVolume/cfdTools/general/fieldSources/basicSource/rotorDiskSource/bladeModel/bladeModel.H new file mode 100644 index 00000000000..df26e7bd401 --- /dev/null +++ b/src/finiteVolume/cfdTools/general/fieldSources/basicSource/rotorDiskSource/bladeModel/bladeModel.H @@ -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 + +// ************************************************************************* // diff --git a/src/finiteVolume/cfdTools/general/fieldSources/basicSource/rotorDiskSource/profileModel/lookup/lookupProfile.C b/src/finiteVolume/cfdTools/general/fieldSources/basicSource/rotorDiskSource/profileModel/lookup/lookupProfile.C new file mode 100644 index 00000000000..ae80d03995d --- /dev/null +++ b/src/finiteVolume/cfdTools/general/fieldSources/basicSource/rotorDiskSource/profileModel/lookup/lookupProfile.C @@ -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]; +} + + +// ************************************************************************* // diff --git a/src/finiteVolume/cfdTools/general/fieldSources/basicSource/rotorDiskSource/profileModel/lookup/lookupProfile.H b/src/finiteVolume/cfdTools/general/fieldSources/basicSource/rotorDiskSource/profileModel/lookup/lookupProfile.H new file mode 100644 index 00000000000..deb5c1f725a --- /dev/null +++ b/src/finiteVolume/cfdTools/general/fieldSources/basicSource/rotorDiskSource/profileModel/lookup/lookupProfile.H @@ -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 + +// ************************************************************************* // diff --git a/src/finiteVolume/cfdTools/general/fieldSources/basicSource/rotorDiskSource/profileModel/profileModel.C b/src/finiteVolume/cfdTools/general/fieldSources/basicSource/rotorDiskSource/profileModel/profileModel.C new file mode 100644 index 00000000000..c9008d276c6 --- /dev/null +++ b/src/finiteVolume/cfdTools/general/fieldSources/basicSource/rotorDiskSource/profileModel/profileModel.C @@ -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)); +} + + +// ************************************************************************* // diff --git a/src/finiteVolume/cfdTools/general/fieldSources/basicSource/rotorDiskSource/profileModel/profileModel.H b/src/finiteVolume/cfdTools/general/fieldSources/basicSource/rotorDiskSource/profileModel/profileModel.H new file mode 100644 index 00000000000..5c850ec1bb3 --- /dev/null +++ b/src/finiteVolume/cfdTools/general/fieldSources/basicSource/rotorDiskSource/profileModel/profileModel.H @@ -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 + +// ************************************************************************* // diff --git a/src/finiteVolume/cfdTools/general/fieldSources/basicSource/rotorDiskSource/profileModel/profileModelList.C b/src/finiteVolume/cfdTools/general/fieldSources/basicSource/rotorDiskSource/profileModel/profileModelList.C new file mode 100644 index 00000000000..904b01372b5 --- /dev/null +++ b/src/finiteVolume/cfdTools/general/fieldSources/basicSource/rotorDiskSource/profileModel/profileModelList.C @@ -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; + } + } +} + + +// ************************************************************************* // diff --git a/src/finiteVolume/cfdTools/general/fieldSources/basicSource/rotorDiskSource/profileModel/profileModelList.H b/src/finiteVolume/cfdTools/general/fieldSources/basicSource/rotorDiskSource/profileModel/profileModelList.H new file mode 100644 index 00000000000..74326dced4b --- /dev/null +++ b/src/finiteVolume/cfdTools/general/fieldSources/basicSource/rotorDiskSource/profileModel/profileModelList.H @@ -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 + +// ************************************************************************* // diff --git a/src/finiteVolume/cfdTools/general/fieldSources/basicSource/rotorDiskSource/profileModel/series/seriesProfile.C b/src/finiteVolume/cfdTools/general/fieldSources/basicSource/rotorDiskSource/profileModel/series/seriesProfile.C new file mode 100644 index 00000000000..865ed3ab62e --- /dev/null +++ b/src/finiteVolume/cfdTools/general/fieldSources/basicSource/rotorDiskSource/profileModel/series/seriesProfile.C @@ -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_); +} + + +// ************************************************************************* // diff --git a/src/finiteVolume/cfdTools/general/fieldSources/basicSource/rotorDiskSource/profileModel/series/seriesProfile.H b/src/finiteVolume/cfdTools/general/fieldSources/basicSource/rotorDiskSource/profileModel/series/seriesProfile.H new file mode 100644 index 00000000000..73b474aae1f --- /dev/null +++ b/src/finiteVolume/cfdTools/general/fieldSources/basicSource/rotorDiskSource/profileModel/series/seriesProfile.H @@ -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 + +// ************************************************************************* // diff --git a/src/finiteVolume/cfdTools/general/fieldSources/basicSource/rotorDiskSource/rotorDiskSource.C b/src/finiteVolume/cfdTools/general/fieldSources/basicSource/rotorDiskSource/rotorDiskSource.C new file mode 100644 index 00000000000..03eb60364b9 --- /dev/null +++ b/src/finiteVolume/cfdTools/general/fieldSources/basicSource/rotorDiskSource/rotorDiskSource.C @@ -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; + } +} + + +// ************************************************************************* // diff --git a/src/finiteVolume/cfdTools/general/fieldSources/basicSource/rotorDiskSource/rotorDiskSource.H b/src/finiteVolume/cfdTools/general/fieldSources/basicSource/rotorDiskSource/rotorDiskSource.H new file mode 100644 index 00000000000..0d646b98996 --- /dev/null +++ b/src/finiteVolume/cfdTools/general/fieldSources/basicSource/rotorDiskSource/rotorDiskSource.H @@ -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 + +// ************************************************************************* // + diff --git a/src/finiteVolume/cfdTools/general/fieldSources/basicSource/rotorDiskSource/rotorDiskSourceTemplates.C b/src/finiteVolume/cfdTools/general/fieldSources/basicSource/rotorDiskSource/rotorDiskSourceTemplates.C new file mode 100644 index 00000000000..5bc97c703f9 --- /dev/null +++ b/src/finiteVolume/cfdTools/general/fieldSources/basicSource/rotorDiskSource/rotorDiskSourceTemplates.C @@ -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; +} + + +// ************************************************************************* // -- GitLab