Go to the documentation of this file.
47 template<
class RhoFieldType>
50 const RhoFieldType&
rho,
56 rotor_.calculate(
rho,
U, thetag, force,
false,
false);
62 const vector& origin = rotor_.coordSys().origin();
63 const vector& rollAxis = rotor_.coordSys().e1();
64 const vector& pitchAxis = rotor_.coordSys().e2();
65 const vector& yawAxis = rotor_.coordSys().e3();
72 label celli =
cells[i];
75 vector mc = fc^(
C[celli] - origin);
79 scalar radius =
x[i].x();
80 scalar coeff2 =
rho[celli]*coeff1*
pow4(radius);
83 cf[0] += (fc & yawAxis)/(coeff2 + ROOTVSMALL);
84 cf[1] += (mc & pitchAxis)/(coeff2*radius + ROOTVSMALL);
85 cf[2] += (mc & rollAxis)/(coeff2*radius + ROOTVSMALL);
89 cf[0] += fc & yawAxis;
90 cf[1] += mc & pitchAxis;
91 cf[2] += mc & rollAxis;
101 template<
class RhoFieldType>
104 const RhoFieldType&
rho,
109 if (rotor_.mesh().time().timeIndex() % calcFrequency_ == 0)
111 word calcType =
"forces";
114 calcType =
"coefficients";
118 <<
" solving for target trim " << calcType <<
nl;
120 const scalar rhoRef = rotor_.rhoRef();
128 while ((err > tol_) && (iter < nIter_))
134 old = calcCoeffs(
rho,
U, thetag(), force);
138 for (label pitchI = 0; pitchI < 3; pitchI++)
140 theta_[pitchI] -= dTheta_/2.0;
141 vector cf0 = calcCoeffs(
rho,
U, thetag(), force);
143 theta_[pitchI] += dTheta_;
144 vector cf1 = calcCoeffs(
rho,
U, thetag(), force);
146 vector ddTheta = (cf1 - cf0)/dTheta_;
148 J[pitchI + 0] = ddTheta[0];
149 J[pitchI + 3] = ddTheta[1];
150 J[pitchI + 6] = ddTheta[2];
156 vector dt =
inv(J) & (target_/rhoRef - old);
159 vector thetaNew = theta_ + relax_*dt;
162 err =
mag(thetaNew - theta_);
171 Info<<
" solution not converged in " << iter
172 <<
" iterations, final residual = " << err
173 <<
"(" << tol_ <<
")" <<
endl;
177 Info<<
" final residual = " << err <<
"(" << tol_
178 <<
"), iterations = " << iter <<
endl;
181 Info<<
" current and target " << calcType <<
nl
182 <<
" thrust = " << old[0]*rhoRef <<
", " << target_[0] <<
nl
183 <<
" pitch = " << old[1]*rhoRef <<
", " << target_[1] <<
nl
184 <<
" roll = " << old[2]*rhoRef <<
", " << target_[2] <<
nl
185 <<
" new pitch angles [deg]:" <<
nl
223 const dictionary& targetDict(coeffs_.subDict(
"target"));
224 useCoeffs_ = targetDict.
getOrDefault(
"useCoeffs",
true);
231 targetDict.readEntry(
"thrust" + ext, target_[0]);
232 targetDict.readEntry(
"pitch" + ext, target_[1]);
233 targetDict.readEntry(
"roll" + ext, target_[2]);
235 const dictionary& pitchAngleDict(coeffs_.subDict(
"pitchAngles"));
236 theta_[0] =
degToRad(pitchAngleDict.get<scalar>(
"theta0Ini"));
237 theta_[1] =
degToRad(pitchAngleDict.get<scalar>(
"theta1cIni"));
238 theta_[2] =
degToRad(pitchAngleDict.get<scalar>(
"theta1sIni"));
240 coeffs_.readEntry(
"calcFrequency", calcFrequency_);
242 coeffs_.readIfPresent(
"nIter", nIter_);
243 coeffs_.readIfPresent(
"tol", tol_);
244 coeffs_.readIfPresent(
"relax", relax_);
246 if (coeffs_.readIfPresent(
"dTheta", dTheta_))
251 coeffs_.readEntry(
"alpha", alpha_);
260 auto& t = ttheta.ref();
264 scalar
psi =
x[i].y();
265 t[i] = theta_[0] + theta_[1]*
cos(
psi) + theta_[2]*
sin(
psi);
289 correctTrim(
rho,
U, force);
addToRunTimeSelectionTable(decompositionMethod, kahipDecomp, dictionary)
void read(const dictionary &dict)
Read.
A class for handling words, derived from Foam::string.
A class for managing temporary objects.
static constexpr const zero Zero
Global zero (0)
Different types of constants.
dimensionedScalar sin(const dimensionedScalar &ds)
bool read(const char *buf, int32_t &val)
Same as readInt32.
A class representing the concept of a GeometricField of 1 used to avoid unnecessary manipulations for...
Ostream & endl(Ostream &os)
Add newline and flush stream.
void correctTrim(const RhoFieldType &rho, const vectorField &U, vectorField &force)
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.
#define forAll(list, i)
Loop across all elements in list.
void reduce(const List< UPstream::commsStruct > &comms, T &Value, const BinaryOp &bop, const int tag, const label comm)
dimensionedScalar pow4(const dimensionedScalar &ds)
virtual void read(const dictionary &dict)
Read.
virtual tmp< scalarField > thetag() const
Return the geometric angle of attack [rad].
dimensionedSphericalTensor inv(const dimensionedSphericalTensor &dt)
messageStream Info
Information stream (uses stdout - output is on the master only)
constexpr scalar radToDeg(const scalar rad) noexcept
Conversion from radians to degrees.
A list of keyword definitions, which are a keyword followed by a number of values (eg,...
Macros for easy insertion into run-time selection tables.
constexpr scalar degToRad(const scalar deg) noexcept
Conversion from degrees to radians.
dimensionedSymmTensor sqr(const dimensionedVector &dv)
constexpr scalar pi(M_PI)
dimensioned< typename typeOfMag< Type >::type > mag(const dimensioned< Type > &dt)
fileName::Type type(const fileName &name, const bool followLink=true)
Return the file type: DIRECTORY or FILE, normally following symbolic links.
const dimensionedScalar e
Elementary charge.
static tmp< T > New(Args &&... args)
Construct tmp of T with forwarding arguments.
targetCoeffTrim(const fv::rotorDiskSource &rotor, const dictionary &dict)
Constructor.
Graphite solid properties.
T getOrDefault(const word &keyword, const T &deflt, enum keyType::option matchOpt=keyType::REGEX) const
const volScalarField & psi
virtual void correct(const vectorField &U, vectorField &force)
Correct the model.
defineTypeNameAndDebug(combustionModel, 0)
dimensionedScalar cos(const dimensionedScalar &ds)