momentOfInertia.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-2025 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 "momentOfInertia.H"
28 
29 // * * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * //
30 
32 (
33  const pointField& pts,
34  const triFaceList& triFaces,
35  scalar density,
36  scalar& mass,
37  vector& cM,
38  symmTensor& J
39 )
40 {
41  // Reimplemented from: Wm4PolyhedralMassProperties.cpp
42  // File Version: 4.10.0 (2009/11/18)
43 
44  // Geometric Tools, LC
45  // Copyright (c) 1998-2010
46  // Distributed under the Boost Software License, Version 1.0.
47  // http://www.boost.org/LICENSE_1_0.txt
48  // http://www.geometrictools.com/License/Boost/LICENSE_1_0.txt
49 
50  // Boost Software License - Version 1.0 - August 17th, 2003
51 
52  // Permission is hereby granted, free of charge, to any person or
53  // organisation obtaining a copy of the software and accompanying
54  // documentation covered by this license (the "Software") to use,
55  // reproduce, display, distribute, execute, and transmit the
56  // Software, and to prepare derivative works of the Software, and
57  // to permit third-parties to whom the Software is furnished to do
58  // so, all subject to the following:
59 
60  // The copyright notices in the Software and this entire
61  // statement, including the above license grant, this restriction
62  // and the following disclaimer, must be included in all copies of
63  // the Software, in whole or in part, and all derivative works of
64  // the Software, unless such copies or derivative works are solely
65  // in the form of machine-executable object code generated by a
66  // source language processor.
67 
68  // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
69  // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
70  // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND
71  // NON-INFRINGEMENT. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR
72  // ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE FOR ANY DAMAGES OR
73  // OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
74  // ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
75  // USE OR OTHER DEALINGS IN THE SOFTWARE.
76 
77  const scalar r6 = 1.0/6.0;
78  const scalar r24 = 1.0/24.0;
79  const scalar r60 = 1.0/60.0;
80  const scalar r120 = 1.0/120.0;
81 
82  // order: 1, x, y, z, x^2, y^2, z^2, xy, yz, zx
83  scalarField integrals(10, 0.0);
84 
85  forAll(triFaces, i)
86  {
87  const triFace& tri(triFaces[i]);
88 
89  // vertices of triangle i
90  const vector& v0 = pts[tri[0]];
91  const vector& v1 = pts[tri[1]];
92  const vector& v2 = pts[tri[2]];
93 
94  // cross product of edges
95  const vector eA(v1 - v0);
96  const vector eB(v2 - v0);
97  const vector n(eA ^ eB);
98 
99  // compute integral terms
100  scalar tmp0, tmp1, tmp2;
101 
102  scalar f1x, f2x, f3x, g0x, g1x, g2x;
103 
104  tmp0 = v0.x() + v1.x();
105  f1x = tmp0 + v2.x();
106  tmp1 = v0.x()*v0.x();
107  tmp2 = tmp1 + v1.x()*tmp0;
108  f2x = tmp2 + v2.x()*f1x;
109  f3x = v0.x()*tmp1 + v1.x()*tmp2 + v2.x()*f2x;
110  g0x = f2x + v0.x()*(f1x + v0.x());
111  g1x = f2x + v1.x()*(f1x + v1.x());
112  g2x = f2x + v2.x()*(f1x + v2.x());
113 
114  scalar f1y, f2y, f3y, g0y, g1y, g2y;
115 
116  tmp0 = v0.y() + v1.y();
117  f1y = tmp0 + v2.y();
118  tmp1 = v0.y()*v0.y();
119  tmp2 = tmp1 + v1.y()*tmp0;
120  f2y = tmp2 + v2.y()*f1y;
121  f3y = v0.y()*tmp1 + v1.y()*tmp2 + v2.y()*f2y;
122  g0y = f2y + v0.y()*(f1y + v0.y());
123  g1y = f2y + v1.y()*(f1y + v1.y());
124  g2y = f2y + v2.y()*(f1y + v2.y());
125 
126  scalar f1z, f2z, f3z, g0z, g1z, g2z;
127 
128  tmp0 = v0.z() + v1.z();
129  f1z = tmp0 + v2.z();
130  tmp1 = v0.z()*v0.z();
131  tmp2 = tmp1 + v1.z()*tmp0;
132  f2z = tmp2 + v2.z()*f1z;
133  f3z = v0.z()*tmp1 + v1.z()*tmp2 + v2.z()*f2z;
134  g0z = f2z + v0.z()*(f1z + v0.z());
135  g1z = f2z + v1.z()*(f1z + v1.z());
136  g2z = f2z + v2.z()*(f1z + v2.z());
137 
138  // update integrals
139  integrals[0] += n.x()*f1x;
140  integrals[1] += n.x()*f2x;
141  integrals[2] += n.y()*f2y;
142  integrals[3] += n.z()*f2z;
143  integrals[4] += n.x()*f3x;
144  integrals[5] += n.y()*f3y;
145  integrals[6] += n.z()*f3z;
146  integrals[7] += n.x()*(v0.y()*g0x + v1.y()*g1x + v2.y()*g2x);
147  integrals[8] += n.y()*(v0.z()*g0y + v1.z()*g1y + v2.z()*g2y);
148  integrals[9] += n.z()*(v0.x()*g0z + v1.x()*g1z + v2.x()*g2z);
149  }
150 
151  integrals[0] *= r6;
152  integrals[1] *= r24;
153  integrals[2] *= r24;
154  integrals[3] *= r24;
155  integrals[4] *= r60;
156  integrals[5] *= r60;
157  integrals[6] *= r60;
158  integrals[7] *= r120;
159  integrals[8] *= r120;
160  integrals[9] *= r120;
161 
162  // mass
163  mass = integrals[0];
164 
165  // center of mass
166  cM = vector(integrals[1], integrals[2], integrals[3])/mass;
167 
168  // inertia relative to origin
169  J.xx() = integrals[5] + integrals[6];
170  J.xy() = -integrals[7];
171  J.xz() = -integrals[9];
172  J.yy() = integrals[4] + integrals[6];
173  J.yz() = -integrals[8];
174  J.zz() = integrals[4] + integrals[5];
175 
176  // inertia relative to center of mass
177  J -= mass*((cM & cM)*I - sqr(cM));
178 
179  // Apply density
180  mass *= density;
181  J *= density;
182 }
183 
184 
186 (
187  const pointField& pts,
188  const triFaceList& triFaces,
189  scalar density,
190  scalar& mass,
191  vector& cM,
192  symmTensor& J
193 )
194 {
195  // Reset properties for accumulation
196 
197  mass = 0;
198  cM = Zero;
199  J = Zero;
200 
201  // Find centre of mass
202 
203  forAll(triFaces, i)
204  {
205  const triFace& tri(triFaces[i]);
206 
207  const triPointRef t
208  (
209  pts[tri[0]],
210  pts[tri[1]],
211  pts[tri[2]]
212  );
213 
214  const scalar triMag = t.mag();
215 
216  cM += triMag*t.centre();
217 
218  mass += triMag;
219  }
220 
221  cM /= mass;
222 
223  mass *= density;
224 
225  // Find inertia around centre of mass
226 
227  forAll(triFaces, i)
228  {
229  const triFace& tri(triFaces[i]);
230 
231  J += triPointRef
232  (
233  pts[tri[0]],
234  pts[tri[1]],
235  pts[tri[2]]
236  ).inertia(cM, density);
237  }
238 }
239 
240 
242 (
243  const triSurface& surf,
244  scalar density,
245  scalar& mass,
246  vector& cM,
247  symmTensor& J
248 )
249 {
250  triFaceList faces(surf.size());
251 
252  forAll(surf, i)
253  {
254  faces[i] = triFace(surf[i]);
255  }
256 
257  massPropertiesSolid(surf.points(), faces, density, mass, cM, J);
258 }
259 
260 
262 (
263  const triSurface& surf,
264  scalar density,
265  scalar& mass,
266  vector& cM,
267  symmTensor& J
268 )
269 {
270  triFaceList faces(surf.size());
271 
272  forAll(surf, i)
273  {
274  faces[i] = triFace(surf[i]);
275  }
276 
277  massPropertiesShell(surf.points(), faces, density, mass, cM, J);
278 }
279 
280 
282 (
283  scalar mass,
284  const vector& cM,
285  const symmTensor& J,
286  const vector& refPt
287 )
288 {
289  // The displacement vector (refPt = cM) is the displacement of the
290  // new reference point from the centre of mass of the body that
291  // the inertia tensor applies to.
292 
293  const vector d(refPt - cM);
294 
295  return J + mass*(magSqr(d)*I - sqr(d));
296 }
297 
298 
300 (
301  const polyMesh& mesh
302 )
303 {
305 
306  tensorField& tf = tTf.ref();
307 
308  forAll(tf, cI)
309  {
310  tf[cI] = meshInertia(mesh, cI);
311  }
312 
313  return tTf;
314 }
315 
316 
318 (
319  const polyMesh& mesh,
320  label celli
321 )
322 {
324  (
325  mesh,
326  celli
327  );
328 
329  triFaceList faces(cellTets.size());
330 
331  forAll(cellTets, cTI)
332  {
333  faces[cTI] = cellTets[cTI].faceTriIs(mesh);
334  }
335 
336  scalar m = 0;
337  vector cM = Zero;
338  symmTensor J = Zero;
339 
340  massPropertiesSolid(mesh.points(), faces, 1.0, m, cM, J);
341 
342  return J;
343 }
344 
345 
346 // ************************************************************************* //
label n
#define forAll(list, i)
Loop across all elements in list.
Definition: UList.H:433
A 1D array of objects of type <T>, where the size of the vector is known and used for subscript bound...
Definition: List.H:91
void size(const label)
Override size to be inconsistent with allocated storage.
Definition: ListI.H:164
const Field< PointType > & points() const
Return reference to global points.
const Cmpt & xx() const
Definition: SymmTensorI.H:87
const Cmpt & yz() const
Definition: SymmTensorI.H:117
const Cmpt & xz() const
Definition: SymmTensorI.H:99
const Cmpt & zz() const
Definition: SymmTensorI.H:135
const Cmpt & xy() const
Definition: SymmTensorI.H:93
const Cmpt & yy() const
Definition: SymmTensorI.H:111
const Cmpt & z() const
Definition: VectorI.H:87
const Cmpt & y() const
Definition: VectorI.H:81
const Cmpt & x() const
Definition: VectorI.H:75
static void massPropertiesSolid(const pointField &pts, const triFaceList &triFaces, scalar density, scalar &mass, vector &cM, symmTensor &J)
static tmp< tensorField > meshInertia(const polyMesh &mesh)
static tensor applyParallelAxisTheorem(scalar mass, const vector &cM, const symmTensor &J, const vector &refPt)
static void massPropertiesShell(const pointField &pts, const triFaceList &triFaces, scalar density, scalar &mass, vector &cM, symmTensor &J)
static List< tetIndices > cellTetIndices(const polyMesh &mesh, label cI)
Return the tet decomposition of the given cell, see.
Mesh consisting of general polyhedral cells.
Definition: polyMesh.H:80
virtual const pointField & points() const
Return raw points.
Definition: polyMesh.C:1331
label nCells() const
A class for managing temporary objects.
Definition: tmp.H:55
T & ref() const
Return non-const reference or generate a fatal error.
Definition: tmpI.H:197
A triangular face using a FixedList of labels corresponding to mesh vertices.
Definition: triFace.H:71
Triangulated surface description with patch information.
Definition: triSurface.H:69
A triangle primitive used to calculate face areas and swept volumes.
Definition: triangle.H:80
Point centre() const
Return centre (centroid)
Definition: triangleI.H:89
scalar mag() const
Return scalar magnitude.
Definition: triangleI.H:103
Foam::fvMesh mesh(Foam::IOobject(regionName, runTime.name(), runTime, Foam::IOobject::MUST_READ), false)
const tensorField & tf
static const zero Zero
Definition: zero.H:97
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
static const Identity< scalar > I
Definition: Identity.H:93
Vector< scalar > vector
A scalar version of the templated Vector.
Definition: vector.H:49
void sqr(LagrangianPatchField< typename outerProduct< Type, Type >::type > &f, const LagrangianPatchField< Type > &f1)
triangle< point, const point & > triPointRef
Definition: triPointRef.H:44
Field< tensor > tensorField
Specialisation of Field<T> for tensor.
void magSqr(LagrangianPatchField< scalar > &f, const LagrangianPatchField< Type > &f1)
face triFace(3)