45 template<
class RhoFieldType>
48 const RhoFieldType&
rho,
54 rotor_.calculate(
rho,
U, thetag,
force,
false,
false);
60 const vector& origin = rotor_.coordSys().origin();
61 const vector& rollAxis = rotor_.coordSys().R().e1();
62 const vector& pitchAxis = rotor_.coordSys().R().e2();
63 const vector& yawAxis = rotor_.coordSys().R().e3();
73 vector mc = fc^(
C[celli] - origin);
77 scalar radius =
x[i].x();
78 scalar coeff2 =
rho[celli]*coeff1*
pow4(radius);
81 cf[0] += (fc & yawAxis)/(coeff2 + rootVSmall);
82 cf[1] += (mc & pitchAxis)/(coeff2*radius + rootVSmall);
83 cf[2] += (mc & rollAxis)/(coeff2*radius + rootVSmall);
87 cf[0] += fc & yawAxis;
88 cf[1] += mc & pitchAxis;
89 cf[2] += mc & rollAxis;
99 template<
class RhoFieldType>
102 const RhoFieldType&
rho,
107 if (rotor_.mesh().time().timeIndex() % calcFrequency_ == 0)
117 <<
" solving for target trim " <<
calcType <<
nl;
119 const scalar rhoRef = rotor_.rhoRef();
127 while ((err > tol_) && (iter < nIter_))
133 old = calcCoeffs(
rho,
U, thetag(),
force);
137 for (
label pitchI = 0; pitchI < 3; pitchI++)
139 theta_[pitchI] -= dTheta_/2.0;
142 theta_[pitchI] += dTheta_;
145 vector ddTheta = (cf1 - cf0)/dTheta_;
147 J[pitchI + 0] = ddTheta[0];
148 J[pitchI + 3] = ddTheta[1];
149 J[pitchI + 6] = ddTheta[2];
155 vector dt =
inv(J) & (target_/rhoRef - old);
158 vector thetaNew = theta_ + relax_*dt;
161 err =
mag(thetaNew - theta_);
170 Info<<
indent <<
"solution not converged in " << iter
171 <<
" iterations, final residual = " << err
172 <<
"(" << tol_ <<
")" <<
endl;
176 Info<<
indent <<
"final residual = " << err <<
"(" << tol_
177 <<
"), iterations = " << iter <<
endl;
181 <<
indent <<
" thrust = " << old[0]*rhoRef
182 <<
", " << target_[0] <<
nl
183 <<
indent <<
" pitch = " << old[1]*rhoRef
184 <<
", " << target_[1] <<
nl
185 <<
indent <<
" roll = " << old[2]*rhoRef
186 <<
", " << target_[2] <<
nl
187 <<
indent <<
" new pitch angles [deg]:" <<
nl
231 const dictionary& targetDict(coeffs_.subDict(
"target"));
239 target_[0] = targetDict.
lookup<scalar>(
"thrust" + ext);
240 target_[1] = targetDict.
lookup<scalar>(
"pitch" + ext);
241 target_[2] = targetDict.
lookup<scalar>(
"roll" + ext);
243 const dictionary& pitchAngleDict(coeffs_.subDict(
"pitchAngles"));
244 theta_[0] = pitchAngleDict.lookup<scalar>(
"theta0Ini",
units::degrees);
245 theta_[1] = pitchAngleDict.lookup<scalar>(
"theta1cIni",
units::degrees);
246 theta_[2] = pitchAngleDict.lookup<scalar>(
"theta1sIni",
units::degrees);
248 coeffs_.lookup(
"calcFrequency") >> calcFrequency_;
250 coeffs_.readIfPresent(
"nIter", nIter_);
251 coeffs_.readIfPresent(
"tol", tol_);
252 coeffs_.readIfPresent(
"relax", relax_);
256 alpha_ = coeffs_.lookup<scalar>(
"alpha");
269 scalar
psi =
x[i].y();
270 t[i] = theta_[0] + theta_[1]*
cos(
psi) + theta_[2]*
sin(
psi);
#define forAll(list, i)
Loop across all elements in list.
Macros for easy insertion into run-time selection tables.
Graphite solid properties.
Generic GeometricField class.
A list of keywords followed by any number of values (e.g. words and numbers) or sub-dictionaries.
T lookupOrDefault(const word &, const T &) const
Find and return a T, if not found return the given default.
ITstream & lookup(const word &, bool recursive=false, bool patternMatch=true) const
Find and return an entry data stream.
Cell based momentum source which approximates the mean effects of rotor forces on a cylindrical regio...
A class representing the concept of a GeometricField of 1 used to avoid unnecessary manipulations for...
Target trim forces/coefficients.
virtual ~targetCoeffTrim()
Destructor.
virtual tmp< scalarField > thetag() const
Return the geometric angle of attack [rad].
targetCoeffTrim(const fv::rotorDisk &rotor, const dictionary &dict)
Constructor.
void read(const dictionary &dict)
Read.
virtual void correct(const vectorField &U, vectorField &force) const
Correct the model.
void correctTrim(const RhoFieldType &rho, const vectorField &U, vectorField &force) const
Correct the model.
vector calcCoeffs(const RhoFieldType &rho, const vectorField &U, const scalarField &alphag, vectorField &force) const
Calculate the rotor force and moment coefficients vector.
A class for managing temporary objects.
T & ref() const
Return non-const reference or generate a fatal error.
virtual void read(const dictionary &dict)
Read.
Template function which returns the un-mangled name of a given type. Useful for types which do not ha...
A class for handling words, derived from string.
const volScalarField & psi
scalar radToDeg(const scalar rad)
Convert radians to degrees.
scalar degToRad(const scalar deg)
Convert degrees to radians.
intWM_LABEL_SIZE_t label
A label is an int32_t or int64_t as specified by the pre-processor macro WM_LABEL_SIZE.
addToRunTimeSelectionTable(polyPatch, mergedCyclicPolyPatch, word)
Ostream & endl(Ostream &os)
Add newline and flush stream.
dimensionedScalar sin(const dimensionedScalar &ds)
void pow4(LagrangianPatchField< scalar > &f, const LagrangianPatchField< scalar > &f1)
Field< scalar > scalarField
Specialisation of Field<T> for scalar.
tmp< DimensionedField< typename outerProduct< Type, Type >::type, GeoMesh, Field >> sqr(const DimensionedField< Type, GeoMesh, PrimitiveField > &df)
void reduce(const List< UPstream::commsStruct > &comms, T &Value, const BinaryOp &bop, const int tag, const label comm)
void inv(pointPatchField< tensor > &, const pointPatchField< tensor > &)
tmp< DimensionedField< scalar, GeoMesh, Field > > mag(const DimensionedField< Type, GeoMesh, PrimitiveField > &df)
defineTypeNameAndDebug(atmosphericBoundaryLayer, 0)
Ostream & indent(Ostream &os)
Indent stream.
dimensionedScalar cos(const dimensionedScalar &ds)
fileType type(const fileName &, const bool checkVariants=true, const bool followLink=true)
Return the file type: directory or file.