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/>.
24 \*---------------------------------------------------------------------------*/
26 #include "RodriguesRotation.H"
27 #include "mathematicalConstants.H"
29 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
31 Foam::tensor Foam::RodriguesRotation
33 const vector& rotationAxis,
34 const scalar& rotationAngle,
39 scalar theta = rotationAngle;
43 theta *= mathematicalConstant::pi/180.0;
46 scalar sinTheta = sin(theta);
47 scalar cosTheta = cos(theta);
48 scalar oneMinusCosTheta = 1.0 - cosTheta;
50 scalar magRotAxis = mag(rotationAxis);
52 if (magRotAxis < SMALL)
56 "tensor RodriguesRotation\n"
58 " const vector& rotationAxis,\n"
59 " const scalar& rotationAngle\n"
61 ) << "Incorrectly defined axis: " << rotationAxis
65 vector unitVector = rotationAxis/magRotAxis;
67 scalar wx = unitVector.x();
68 scalar wy = unitVector.y();
69 scalar wz = unitVector.z();
71 rotTensor.xx() = cosTheta + sqr(wx)*oneMinusCosTheta;
72 rotTensor.yy() = cosTheta + sqr(wy)*oneMinusCosTheta;
73 rotTensor.zz() = cosTheta + sqr(wz)*oneMinusCosTheta;
75 rotTensor.xy() = wx*wy*oneMinusCosTheta - wz*sinTheta;
76 rotTensor.xz() = wy*sinTheta + wx*wz*oneMinusCosTheta;
78 rotTensor.yx() = wz*sinTheta + wx*wy*oneMinusCosTheta;
79 rotTensor.yz() = -wx*sinTheta + wy*wz*oneMinusCosTheta;
81 rotTensor.zx() = -wy*sinTheta + wx*wz*oneMinusCosTheta;
82 rotTensor.zy() = wx*sinTheta + wy*wz*oneMinusCosTheta;
87 Foam::tensor Foam::RodriguesRotation2
89 const vector& rotationAxis,
90 const scalar& rotationAngle,
94 scalar magRotAxis = mag(rotationAxis);
96 if (magRotAxis < SMALL)
100 "tensor RodriguesRotation2\n"
102 " const vector& rotationAxis,\n"
103 " const scalar& rotationAngle\n"
105 ) << "Incorrectly defined axis: " << rotationAxis
106 << abort(FatalError);
109 scalar theta = rotationAngle;
113 theta *= mathematicalConstant::pi/180.0;
116 const vector k = rotationAxis/magRotAxis;
117 const scalar k1 = k[0];
118 const scalar k2 = k[1];
119 const scalar k3 = k[2];
122 const tensor rotationT (
129 const tensor projectionT (
130 k1*k1 - 1.0, k1*k2, k1*k3,
131 k2*k1, k2*k2 - 1.0, k2*k3,
132 k3*k1, k3*k2, k3*k3 - 1.0);
134 const scalar cosTheta = cos(theta);
135 const scalar sinTheta = sin(theta);
137 return I + sinTheta*rotationT + (1 - cosTheta)*projectionT;
141 Foam::tensor Foam::RodriguesRotation
143 const vector& rotationAxis,
148 scalar magRotAxis = mag(rotationAxis);
150 if (magRotAxis < SMALL)
154 "tensor RodriguesRotation\n"
156 " const vector& rotationAxis,\n"
157 " const vector& vi\n"
158 " const vector& vf\n"
160 ) << "Incorrectly defined axis: " << rotationAxis
161 << abort(FatalError);
164 const vector k = rotationAxis/magRotAxis;
165 const scalar k1 = k[0];
166 const scalar k2 = k[1];
167 const scalar k3 = k[2];
170 const tensor rotationT (
177 const tensor projectionT (
178 k1*k1 - 1.0, k1*k2, k1*k3,
179 k2*k1, k2*k2 - 1.0, k2*k3,
180 k3*k1, k3*k2, k3*k3 - 1.0);
182 // Project both vectors onto the plane defined by the rotation axis
183 vector nvi = -(projectionT & vi);
184 vector nvf = -(projectionT & vf);
188 const vector crossNviNvf = nvi ^ nvf;
189 const scalar cosTheta = nvi & nvf;
190 const scalar sinTheta = mag(crossNviNvf) * sign(crossNviNvf & k);
192 return I + sinTheta*rotationT + (1 - cosTheta)*projectionT;
195 Foam::tensorField Foam::RodriguesRotation
197 const vector& rotationAxis,
198 const vectorField& vi,
199 const vectorField& vf
202 scalar magRotAxis = mag(rotationAxis);
204 if (magRotAxis < SMALL)
208 "tensor RodriguesRotation\n"
210 " const vector& rotationAxis,\n"
211 " const vectorField& vi\n"
212 " const vectorField& vf\n"
214 ) << "Incorrectly defined axis: " << rotationAxis
215 << abort(FatalError);
218 const vector k = rotationAxis/magRotAxis;
219 const scalar k1 = k[0];
220 const scalar k2 = k[1];
221 const scalar k3 = k[2];
224 const tensor rotationT (
231 const tensor projectionT (
232 k1*k1 - 1.0, k1*k2, k1*k3,
233 k2*k1, k2*k2 - 1.0, k2*k3,
234 k3*k1, k3*k2, k3*k3 - 1.0);
236 // Project both vectors onto the plane defined by the rotation axis
237 vectorField nvi = -(projectionT & vi);
238 vectorField nvf = -(projectionT & vf);
242 const vectorField crossNviNvf = nvi ^ nvf;
243 const scalarField cosTheta = nvi & nvf;
244 const scalarField sinTheta = mag(crossNviNvf) * sign(crossNviNvf & k);
246 const tensorField I_F(vi.size(), I);
247 const tensorField rotationT_F(vi.size(), rotationT);
248 const tensorField projectionT_F(vi.size(), projectionT);
250 return I_F + sinTheta*rotationT_F + (1 - cosTheta)*projectionT_F;
254 // ************************************************************************* //