rotorDiskTemplates.C
Go to the documentation of this file.
1 /*---------------------------------------------------------------------------*\
2  ========= |
3  \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
4  \\ / O peration | Website: https://openfoam.org
5  \\ / A nd | Copyright (C) 2011-2024 OpenFOAM Foundation
6  \\/ M anipulation |
7 -------------------------------------------------------------------------------
8 License
9  This file is part of OpenFOAM.
10 
11  OpenFOAM is free software: you can redistribute it and/or modify it
12  under the terms of the GNU General Public License as published by
13  the Free Software Foundation, either version 3 of the License, or
14  (at your option) any later version.
15 
16  OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
17  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
18  FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
19  for more details.
20 
21  You should have received a copy of the GNU General Public License
22  along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
23 
24 \*---------------------------------------------------------------------------*/
25 
26 #include "rotorDisk.H"
27 #include "volFields.H"
28 
29 using namespace Foam::constant;
30 
31 // * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * //
32 
33 template<class RhoFieldType>
35 (
36  const RhoFieldType& rho,
37  const vectorField& U,
38  const scalarField& thetag,
39  vectorField& force,
40  const bool divideVolume,
41  const bool output
42 ) const
43 {
44  const scalarField& V = mesh().V();
45 
46  // Logging info
47  scalar dragEff = 0;
48  scalar liftEff = 0;
49  scalar AOAmin = great;
50  scalar AOAmax = -great;
51  scalar powerEff = 0;
52 
53  const labelUList cells = set_.cells();
54 
55  forAll(cells, i)
56  {
57  if (area_[i] > rootVSmall)
58  {
59  const label celli = cells[i];
60 
61  const scalar radius = x_[i].x();
62 
63  // Transform velocity into local cylindrical reference frame
64  vector Uc = cylindrical_->invTransform(U[celli], i);
65  // Uc.x(): radial direction.
66  // Uc.y(): drag direction.
67  // Uc.z(): lift / thrust direction.
68 
69  // Transform velocity into local coning system
70  Uc = R_[i] & Uc;
71 
72  // Set radial component of velocity to zero
73  Uc.x() = 0;
74 
75  // Set blade normal component of velocity
76  Uc.y() = radius*omega_ - Uc.y();
77 
78  // Determine blade data for this radius
79  // i2 = index of upper radius bound data point in blade list
80  scalar twist = 0;
81  scalar chord = 0;
82  label i1 = -1;
83  label i2 = -1;
84  scalar invDr = 0;
85  blade_.interpolate(radius, twist, chord, i1, i2, invDr);
86 
87  const scalar alphaGeom = thetag[i] + twist;
88 
89  // Effective angle of attack
90  const int rotationSign = sign(omega_);
91  const scalar alphaEff =
92  alphaGeom - atan2(-Uc.z(), rotationSign*Uc.y());
93 
94  AOAmin = min(AOAmin, alphaEff);
95  AOAmax = max(AOAmax, alphaEff);
96 
97  // Determine profile data for this radius and angle of attack
98  const label profile1 = blade_.profileIndex()[i1];
99  const label profile2 = blade_.profileIndex()[i2];
100 
101  scalar Cd1 = 0;
102  scalar Cl1 = 0;
103  profiles_[profile1].Cdl(alphaEff, Cd1, Cl1);
104 
105  scalar Cd2 = 0;
106  scalar Cl2 = 0;
107  profiles_[profile2].Cdl(alphaEff, Cd2, Cl2);
108 
109  const scalar Cd = invDr*(Cd2 - Cd1) + Cd1;
110  const scalar Cl = invDr*(Cl2 - Cl1) + Cl1;
111 
112  // Apply tip effect for blade lift
113  const scalar tipFactor = neg(radius/rMax_ - tipEffect_);
114 
115  // Calculate forces perpendicular to blade
116  const scalar pDyn = 0.5*rho[celli]*magSqr(Uc);
117 
118  const scalar f =
119  pDyn*chord*nBlades_*area_[i]/radius/mathematical::twoPi;
120 
121  vector localForce = vector(0, rotationSign*-f*Cd, tipFactor*f*Cl);
122 
123  // Accumulate forces
124  dragEff += rhoRef_*localForce.y();
125  liftEff += rhoRef_*localForce.z();
126  powerEff += rhoRef_*localForce.y()*radius*omega_;
127 
128  // Transform force from local coning system into rotor cylindrical
129  localForce = invR_[i] & localForce;
130 
131  // Transform force into global Cartesian co-ordinate system
132  force[celli] = cylindrical_->transform(localForce, i);
133 
134  if (divideVolume)
135  {
136  force[celli] /= V[celli];
137  }
138  }
139  }
140 
141  if (output)
142  {
143  reduce(AOAmin, minOp<scalar>());
144  reduce(AOAmax, maxOp<scalar>());
145  reduce(dragEff, sumOp<scalar>());
146  reduce(liftEff, sumOp<scalar>());
147 
148  Info<< type() << " output:" << nl
149  << " min/max(AOA) = " << radToDeg(AOAmin) << ", "
150  << radToDeg(AOAmax) << nl
151  << " Effective power = " << powerEff << nl
152  << " Effective drag = " << dragEff << nl
153  << " Effective lift = " << liftEff << endl;
154  }
155 }
156 
157 
158 template<class Type>
159 void Foam::fv::rotorDisk::writeField
160 (
161  const word& name,
162  const List<Type>& values
163 ) const
164 {
166  (
167  new VolField<Type>
168  (
169  IOobject
170  (
171  name,
172  mesh().time().name(),
173  mesh(),
176  ),
177  mesh(),
178  dimensioned<Type>("zero", dimless, Zero)
179  )
180  );
181 
182  Field<Type>& field = tfield.ref();
183 
184  const labelUList cells = set_.cells();
185 
186  if (cells.size() != values.size())
187  {
189  }
190 
191  forAll(cells, i)
192  {
193  field[cells[i]] = values[i];
194  }
195 
196  tfield().write();
197 }
198 
199 
200 // ************************************************************************* //
#define forAll(list, i)
Loop across all elements in list.
Definition: UList.H:434
Generic GeometricField class.
IOobject defines the attributes of an object for which implicit objectRegistry management is supporte...
Definition: IOobject.H:99
void size(const label)
Override size to be inconsistent with allocated storage.
Definition: ListI.H:164
const Cmpt & z() const
Definition: VectorI.H:87
const Cmpt & y() const
Definition: VectorI.H:81
const Cmpt & x() const
Definition: VectorI.H:75
Generic dimensioned Type class.
void calculate(const RhoFieldType &rho, const vectorField &U, const scalarField &thetag, vectorField &force, const bool divideVolume=true, const bool output=true) const
Calculate forces.
A class for managing temporary objects.
Definition: tmp.H:55
A class for handling words, derived from string.
Definition: word.H:62
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:334
const cellShapeList & cells
U
Definition: pEqn.H:72
const scalar twoPi(2 *pi)
Collection of constants.
static const zero Zero
Definition: zero.H:97
scalar radToDeg(const scalar rad)
Convert radians to degrees.
dimensionedScalar sign(const dimensionedScalar &ds)
intWM_LABEL_SIZE_t label
A label is an int32_t or int64_t as specified by the pre-processor macro WM_LABEL_SIZE.
Definition: label.H:59
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:257
word name(const bool)
Return a word representation of a bool.
Definition: boolIO.C:39
errorManip< error > abort(error &err)
Definition: errorManip.H:131
const dimensionSet dimless
messageStream Info
layerAndWeight min(const layerAndWeight &a, const layerAndWeight &b)
dimensionedScalar atan2(const dimensionedScalar &x, const dimensionedScalar &y)
Vector< scalar > vector
A scalar version of the templated Vector.
Definition: vector.H:49
void reduce(const List< UPstream::commsStruct > &comms, T &Value, const BinaryOp &bop, const int tag, const label comm)
layerAndWeight max(const layerAndWeight &a, const layerAndWeight &b)
dimensionedScalar neg(const dimensionedScalar &ds)
error FatalError
static const char nl
Definition: Ostream.H:266
dimensioned< scalar > magSqr(const dimensioned< Type > &)
fileType type(const fileName &, const bool checkVariants=true, const bool followLink=true)
Return the file type: directory or file.
Definition: POSIX.C:488
labelList f(nPoints)