1 /*---------------------------------------------------------------------------*\
3 \\ / F ield | foam-extend: Open Source CFD
4 \\ / O peration | Version: 3.2
5 \\ / A nd | Web: http://www.foam-extend.org
6 \\/ M anipulation | For copyright notice see file Copyright
7 -------------------------------------------------------------------------------
9 This file is part of foam-extend.
11 foam-extend is free software: you can redistribute it and/or modify it
12 under the terms of the GNU General Public License as published by the
13 Free Software Foundation, either version 3 of the License, or (at your
14 option) any later version.
16 foam-extend is distributed in the hope that it will be useful, but
17 WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 General Public License for more details.
21 You should have received a copy of the GNU General Public License
22 along with foam-extend. If not, see <http://www.gnu.org/licenses/>.
28 6-DOF solver using quaternions
31 Dubravko Matijasevic, FSB Zagreb. All rights reserved.
33 \*---------------------------------------------------------------------------*/
35 #include "objectRegistry.H"
36 #include "sixDOFqODE.H"
38 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
40 void Foam::sixDOFqODE::setCoeffs()
42 // Set ODE coefficients from position and rotation
44 // Linear displacement relative to spring equilibrium
45 const vector& Xval = Xrel_.value();
46 coeffs_[0] = Xval.x();
47 coeffs_[1] = Xval.y();
48 coeffs_[2] = Xval.z();
51 const vector& Uval = U_.value();
52 coeffs_[3] = Uval.x();
53 coeffs_[4] = Uval.y();
54 coeffs_[5] = Uval.z();
56 // Rotational velocity in non - inertial coordinate system
57 const vector& omegaVal = omega_.value();
58 coeffs_[6] = omegaVal.x();
59 coeffs_[7] = omegaVal.y();
60 coeffs_[8] = omegaVal.z();
63 coeffs_[9] = rotation_.eInitial().e0();
64 coeffs_[10] = rotation_.eInitial().e1();
65 coeffs_[11] = rotation_.eInitial().e2();
66 coeffs_[12] = rotation_.eInitial().e3();
70 Foam::dimensionedVector Foam::sixDOFqODE::A
72 const dimensionedVector& xR,
73 const dimensionedVector& uR,
74 const HamiltonRodriguezRot& rotation
77 // Fix the global force for global rotation constraints
78 dimensionedVector fAbs = force();
80 // Constrain translation
81 constrainTranslation(fAbs.value());
85 - (linSpringCoeffs_ & xR) // spring
86 - (linDampingCoeffs_ & uR) // damping
89 + (rotation.invR() & forceRelative())
94 Foam::dimensionedVector Foam::sixDOFqODE::OmegaDot
96 const HamiltonRodriguezRot& rotation,
97 const dimensionedVector& omega
100 // Fix the global moment for global rotation constraints
101 dimensionedVector mAbs = moment();
103 // Constrain rotation
104 constrainRotation(mAbs.value());
107 inv(momentOfInertia_)
111 + (rotation.R() & mAbs)
117 Foam::dimensionedVector Foam::sixDOFqODE::E
119 const dimensionedVector& omega
122 return (*(momentOfInertia_ & omega) & omega);
126 void Foam::sixDOFqODE::constrainRotation(vector& vec) const
128 vector consVec(vector::zero);
130 // Constrain the vector in respect to referent or global coordinate system
131 if (referentMotionConstraints_)
133 consVec = referentRotation_.R() & vec;
148 vec = referentRotation_.invR() & consVec;
168 void Foam::sixDOFqODE::constrainTranslation(vector& vec) const
170 vector consVec(vector::zero);
172 // Constrain the vector in respect to referent or global coordinate system
173 if (referentMotionConstraints_)
175 consVec = referentRotation_.R() & vec;
190 vec = referentRotation_.invR() & consVec;
210 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
212 // Construct from components
213 Foam::sixDOFqODE::sixDOFqODE(const IOobject& io)
217 mass_(lookup("mass")),
218 momentOfInertia_(lookup("momentOfInertia")),
220 Xequilibrium_(lookup("equilibriumPosition")),
221 linSpringCoeffs_(lookup("linearSpring")),
222 linDampingCoeffs_(lookup("linearDamping")),
224 Xrel_(lookup("Xrel")),
229 vector(lookup("rotationVector")),
230 dimensionedScalar(lookup("rotationAngle")).value()
232 omega_(lookup("omega")),
233 omegaAverage_(omega_),
234 omegaAverageAbsolute_(omega_),
236 force_(lookup("force")),
237 moment_(lookup("moment")),
238 forceRelative_(lookup("forceRelative")),
239 momentRelative_(lookup("momentRelative")),
243 fixedSurge_(lookup("fixedSurge")),
244 fixedSway_(lookup("fixedSway")),
245 fixedHeave_(lookup("fixedHeave")),
246 fixedRoll_(lookup("fixedRoll")),
247 fixedPitch_(lookup("fixedPitch")),
248 fixedYaw_(lookup("fixedYaw")),
249 referentMotionConstraints_
251 lookupOrDefault<Switch>
253 "referentMotionConstraints",
257 referentRotation_(vector(1, 0, 0), 0)
264 Foam::sixDOFqODE::sixDOFqODE
283 mass_(sd.mass_.name(), sd.mass_),
284 momentOfInertia_(sd.momentOfInertia_.name(), sd.momentOfInertia_),
286 Xequilibrium_(sd.Xequilibrium_.name(), sd.Xequilibrium_),
287 linSpringCoeffs_(sd.linSpringCoeffs_.name(), sd.linSpringCoeffs_),
288 linDampingCoeffs_(sd.linDampingCoeffs_.name(), sd.linDampingCoeffs_),
290 Xrel_(sd.Xrel_.name(), sd.Xrel_),
291 U_(sd.U_.name(), sd.U_),
292 Uaverage_(sd.Uaverage_.name(), sd.Uaverage_),
293 rotation_(sd.rotation_),
294 omega_(sd.omega_.name(), sd.omega_),
295 omegaAverage_(sd.omegaAverage_.name(), sd.omegaAverage_),
296 omegaAverageAbsolute_
298 sd.omegaAverageAbsolute_.name(),
299 sd.omegaAverageAbsolute_
302 force_(sd.force_.name(), sd.force_),
303 moment_(sd.moment_.name(), sd.moment_),
304 forceRelative_(sd.forceRelative_.name(), sd.forceRelative_),
305 momentRelative_(sd.momentRelative_.name(), sd.momentRelative_),
309 fixedSurge_(sd.fixedSurge_),
310 fixedSway_(sd.fixedSway_),
311 fixedHeave_(sd.fixedHeave_),
312 fixedRoll_(sd.fixedRoll_),
313 fixedPitch_(sd.fixedPitch_),
314 fixedYaw_(sd.fixedYaw_),
315 referentMotionConstraints_(sd.referentMotionConstraints_),
316 referentRotation_(sd.referentRotation_)
320 // * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
322 Foam::sixDOFqODE::~sixDOFqODE()
326 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
328 void Foam::sixDOFqODE::setState(const sixDOFqODE& sd)
331 momentOfInertia_ = sd.momentOfInertia_;
333 Xequilibrium_ = sd.Xequilibrium_;
334 linSpringCoeffs_ = sd.linSpringCoeffs_;
335 linDampingCoeffs_ = sd.linDampingCoeffs_;
339 Uaverage_ = sd.Uaverage_;
340 rotation_ = sd.rotation_;
342 omegaAverage_ = sd.omegaAverage_;
343 omegaAverageAbsolute_ = sd.omegaAverageAbsolute_;
346 moment_ = sd.moment_;
347 forceRelative_ = sd.forceRelative_;
348 momentRelative_ = sd.momentRelative_;
350 // Copy ODE coefficients: this carries actual ODE state
352 coeffs_ = sd.coeffs_;
354 fixedSurge_ = sd.fixedSurge_;
355 fixedSway_ = sd.fixedSway_;
356 fixedHeave_ = sd.fixedHeave_;
357 fixedRoll_ = sd.fixedRoll_;
358 fixedPitch_ = sd.fixedPitch_;
359 fixedYaw_ = sd.fixedYaw_;
363 void Foam::sixDOFqODE::derivatives
366 const scalarField& y,
370 // Set the derivatives for displacement
375 dimensionedVector curX("curX", dimLength, vector(y[0], y[1], y[2]));
376 dimensionedVector curU("curU", dimVelocity, vector(y[3], y[4], y[5]));
377 const HamiltonRodriguezRot curRotation
385 const vector accel = A(curX, curU, curRotation).value();
391 // // Add translational constraints by setting RHS of given components to zero
394 // dydx[0] = 0; // Surge velocity
395 // dydx[3] = 0; // Surge acceleration
399 // dydx[1] = 0; // Sway velocity
400 // dydx[4] = 0; // Sway acceleration
404 // dydx[2] = 0; // Heave velocity
405 // dydx[5] = 0; // Heave acceleration
408 // Set the derivatives for rotation
409 dimensionedVector curOmega
413 vector(y[6], y[7], y[8])
416 // dimensionedVector curGlobalOmega = curRotation.invR() & curOmega;
418 // // Add rotational constraints by setting RHS of given components to zero
421 // curGlobalOmega.value().x() = 0;
425 // curGlobalOmega.value().y() = 0;
429 // curGlobalOmega.value().z() = 0;
433 // curOmega = curRotation.R() & curGlobalOmega;
435 const vector omegaDot = OmegaDot(curRotation, curOmega).value();
437 dydx[6] = omegaDot.x();
438 dydx[7] = omegaDot.y();
439 dydx[8] = omegaDot.z();
441 dydx[9] = curRotation.eDot(curOmega.value(), 0);
442 dydx[10] = curRotation.eDot(curOmega.value(), 1);
443 dydx[11] = curRotation.eDot(curOmega.value(), 2);
444 dydx[12] = curRotation.eDot(curOmega.value(), 3);
446 // Add rotational constraints by setting RHS of given components to zero
449 dydx[10] = 0; // Roll axis (roll quaternion evolution RHS)
453 dydx[11] = 0; // Pitch axis (pitch quaternion evolution RHS)
457 dydx[12] = 0; // Yaw axis (yaw quaternion evolution RHS)
462 void Foam::sixDOFqODE::jacobian
465 const scalarField& y,
467 scalarSquareMatrix& dfdy
470 Info << "jacobian(...)" << endl;
471 notImplemented("sixDOFqODE::jacobian(...) const");
475 void Foam::sixDOFqODE::update(const scalar delta)
478 vector Xold = Xrel_.value();
480 vector& Xval = Xrel_.value();
482 Xval.x() = coeffs_[0];
483 Xval.y() = coeffs_[1];
484 Xval.z() = coeffs_[2];
487 Uaverage_.value() = (Xval - Xold)/delta;
489 vector& Uval = U_.value();
491 Uval.x() = coeffs_[3];
492 Uval.y() = coeffs_[4];
493 Uval.z() = coeffs_[5];
495 // Constrain velocity
496 constrainTranslation(Uval);
497 coeffs_[3] = Uval.x();
498 coeffs_[4] = Uval.y();
499 coeffs_[5] = Uval.z();
502 vector& omegaVal = omega_.value();
504 omegaVal.x() = coeffs_[6];
505 omegaVal.y() = coeffs_[7];
506 omegaVal.z() = coeffs_[8];
509 constrainRotation(omegaVal);
510 coeffs_[6] = omegaVal.x();
511 coeffs_[7] = omegaVal.y();
512 coeffs_[8] = omegaVal.z();
514 rotation_.updateRotation
525 omegaAverage_.value() = rotation_.omegaAverage(delta);
527 // Calculate and constrain omegaAverageAbsolute appropriately
528 vector& omegaAverageAbsoluteValue = omegaAverageAbsolute_.value();
529 omegaAverageAbsoluteValue = rotation_.omegaAverageAbsolute(delta);
533 omegaAverageAbsoluteValue.x() = 0;
537 omegaAverageAbsoluteValue.y() = 0;
541 omegaAverageAbsoluteValue.z() = 0;
546 // * * * * * * * * * * * * * * * Friend Operators * * * * * * * * * * * * * //
548 bool Foam::sixDOFqODE::writeData(Ostream& os) const
555 // * * * * * * * * * * * * * * IOstream Operators * * * * * * * * * * * * * //
557 Foam::Ostream& Foam::operator<<(Ostream& os, const sixDOFqODE& sds)
559 os.writeKeyword("mass") << tab << sds.mass_ << token::END_STATEMENT << nl;
560 os.writeKeyword("momentOfInertia") << tab << sds.momentOfInertia_
561 << token::END_STATEMENT << nl << nl;
563 os.writeKeyword("equilibriumPosition") << tab << sds.Xequilibrium_
564 << token::END_STATEMENT << nl;
565 os.writeKeyword("linearSpring") << tab << sds.linSpringCoeffs_
566 << token::END_STATEMENT << nl;
567 os.writeKeyword("linearDamping") << tab << sds.linDampingCoeffs_
568 << token::END_STATEMENT << nl << nl;
570 os.writeKeyword("Xrel") << tab << sds.Xrel() << token::END_STATEMENT << nl;
571 os.writeKeyword("U") << tab << sds.U() << token::END_STATEMENT << nl;
572 os.writeKeyword("rotationVector") << tab << sds.rotVector()
573 << token::END_STATEMENT << nl;
574 os.writeKeyword("rotationAngle") << tab << sds.rotAngle()
575 << token::END_STATEMENT << nl;
576 os.writeKeyword("omega") << tab << sds.omega()
577 << token::END_STATEMENT << nl << nl;
579 os.writeKeyword("force") << tab << sds.force()
580 << token::END_STATEMENT << nl;
581 os.writeKeyword("moment") << tab << sds.moment()
582 << token::END_STATEMENT << nl;
583 os.writeKeyword("forceRelative") << tab << sds.forceRelative()
584 << token::END_STATEMENT << nl;
585 os.writeKeyword("momentRelative") << tab << sds.momentRelative()
586 << token::END_STATEMENT << endl;
588 os.writeKeyword("fixedSurge") << tab << sds.fixedSurge_ <<
589 token::END_STATEMENT << endl;
590 os.writeKeyword("fixedSway") << tab << sds.fixedSway_ <<
591 token::END_STATEMENT << endl;
592 os.writeKeyword("fixedHeave") << tab << sds.fixedHeave_ <<
593 token::END_STATEMENT << endl;
594 os.writeKeyword("fixedRoll") << tab << sds.fixedRoll_ <<
595 token::END_STATEMENT << endl;
596 os.writeKeyword("fixedPitch") << tab << sds.fixedPitch_ <<
597 token::END_STATEMENT << endl;
598 os.writeKeyword("fixedYaw") << tab << sds.fixedYaw_ <<
599 token::END_STATEMENT << endl;
605 // ************************************************************************* //