mirror of
https://develop.openfoam.com/Development/openfoam.git
synced 2025-11-28 03:28:01 +00:00
ENH: Transferring momentOfInertia calc from utils to meshTools lib.
Adding mesh cell inertia calc.
This commit is contained in:
@ -1,5 +1,6 @@
|
|||||||
EXE_INC = \
|
EXE_INC = \
|
||||||
-I$(LIB_SRC)/meshTools/lnInclude
|
-I$(LIB_SRC)/meshTools/lnInclude \
|
||||||
|
-I$(LIB_SRC)/triSurface/lnInclude
|
||||||
|
|
||||||
EXE_LIBS = \
|
EXE_LIBS = \
|
||||||
-lmeshTools
|
-lmeshTools
|
||||||
|
|||||||
@ -26,180 +26,38 @@ Application
|
|||||||
|
|
||||||
Description
|
Description
|
||||||
Calculates the inertia tensor and principal axes and moments of a
|
Calculates the inertia tensor and principal axes and moments of a
|
||||||
test face and tetrahedron.
|
test face, tetrahedron and mesh.
|
||||||
|
|
||||||
\*---------------------------------------------------------------------------*/
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
#include "argList.H"
|
||||||
|
#include "Time.H"
|
||||||
|
#include "polyMesh.H"
|
||||||
#include "ListOps.H"
|
#include "ListOps.H"
|
||||||
#include "face.H"
|
#include "face.H"
|
||||||
#include "tetPointRef.H"
|
#include "tetPointRef.H"
|
||||||
#include "triFaceList.H"
|
#include "triFaceList.H"
|
||||||
#include "OFstream.H"
|
#include "OFstream.H"
|
||||||
#include "meshTools.H"
|
#include "meshTools.H"
|
||||||
|
#include "momentOfInertia.H"
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
using namespace Foam;
|
using namespace Foam;
|
||||||
|
|
||||||
void massPropertiesSolid
|
|
||||||
(
|
|
||||||
const pointField& pts,
|
|
||||||
const triFaceList triFaces,
|
|
||||||
scalar density,
|
|
||||||
scalar& mass,
|
|
||||||
vector& cM,
|
|
||||||
tensor& J
|
|
||||||
)
|
|
||||||
{
|
|
||||||
// Reimplemented from: Wm4PolyhedralMassProperties.cpp
|
|
||||||
// File Version: 4.10.0 (2009/11/18)
|
|
||||||
|
|
||||||
// Geometric Tools, LC
|
|
||||||
// Copyright (c) 1998-2010
|
|
||||||
// Distributed under the Boost Software License, Version 1.0.
|
|
||||||
// http://www.boost.org/LICENSE_1_0.txt
|
|
||||||
// http://www.geometrictools.com/License/Boost/LICENSE_1_0.txt
|
|
||||||
|
|
||||||
// Boost Software License - Version 1.0 - August 17th, 2003
|
|
||||||
|
|
||||||
// Permission is hereby granted, free of charge, to any person or
|
|
||||||
// organization obtaining a copy of the software and accompanying
|
|
||||||
// documentation covered by this license (the "Software") to use,
|
|
||||||
// reproduce, display, distribute, execute, and transmit the
|
|
||||||
// Software, and to prepare derivative works of the Software, and
|
|
||||||
// to permit third-parties to whom the Software is furnished to do
|
|
||||||
// so, all subject to the following:
|
|
||||||
|
|
||||||
// The copyright notices in the Software and this entire
|
|
||||||
// statement, including the above license grant, this restriction
|
|
||||||
// and the following disclaimer, must be included in all copies of
|
|
||||||
// the Software, in whole or in part, and all derivative works of
|
|
||||||
// the Software, unless such copies or derivative works are solely
|
|
||||||
// in the form of machine-executable object code generated by a
|
|
||||||
// source language processor.
|
|
||||||
|
|
||||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
||||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
|
||||||
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND
|
|
||||||
// NON-INFRINGEMENT. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR
|
|
||||||
// ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE FOR ANY DAMAGES OR
|
|
||||||
// OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
|
|
||||||
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
|
||||||
// USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
||||||
|
|
||||||
const scalar r6 = 1.0/6.0;
|
|
||||||
const scalar r24 = 1.0/24.0;
|
|
||||||
const scalar r60 = 1.0/60.0;
|
|
||||||
const scalar r120 = 1.0/120.0;
|
|
||||||
|
|
||||||
// order: 1, x, y, z, x^2, y^2, z^2, xy, yz, zx
|
|
||||||
scalarField integrals(10, 0.0);
|
|
||||||
|
|
||||||
forAll(triFaces, i)
|
|
||||||
{
|
|
||||||
const triFace& tri(triFaces[i]);
|
|
||||||
|
|
||||||
// vertices of triangle i
|
|
||||||
vector v0 = pts[tri[0]];
|
|
||||||
vector v1 = pts[tri[1]];
|
|
||||||
vector v2 = pts[tri[2]];
|
|
||||||
|
|
||||||
// cross product of edges
|
|
||||||
vector eA = v1 - v0;
|
|
||||||
vector eB = v2 - v0;
|
|
||||||
vector n = eA ^ eB;
|
|
||||||
|
|
||||||
// compute integral terms
|
|
||||||
scalar tmp0, tmp1, tmp2;
|
|
||||||
|
|
||||||
scalar f1x, f2x, f3x, g0x, g1x, g2x;
|
|
||||||
|
|
||||||
tmp0 = v0.x() + v1.x();
|
|
||||||
f1x = tmp0 + v2.x();
|
|
||||||
tmp1 = v0.x()*v0.x();
|
|
||||||
tmp2 = tmp1 + v1.x()*tmp0;
|
|
||||||
f2x = tmp2 + v2.x()*f1x;
|
|
||||||
f3x = v0.x()*tmp1 + v1.x()*tmp2 + v2.x()*f2x;
|
|
||||||
g0x = f2x + v0.x()*(f1x + v0.x());
|
|
||||||
g1x = f2x + v1.x()*(f1x + v1.x());
|
|
||||||
g2x = f2x + v2.x()*(f1x + v2.x());
|
|
||||||
|
|
||||||
scalar f1y, f2y, f3y, g0y, g1y, g2y;
|
|
||||||
|
|
||||||
tmp0 = v0.y() + v1.y();
|
|
||||||
f1y = tmp0 + v2.y();
|
|
||||||
tmp1 = v0.y()*v0.y();
|
|
||||||
tmp2 = tmp1 + v1.y()*tmp0;
|
|
||||||
f2y = tmp2 + v2.y()*f1y;
|
|
||||||
f3y = v0.y()*tmp1 + v1.y()*tmp2 + v2.y()*f2y;
|
|
||||||
g0y = f2y + v0.y()*(f1y + v0.y());
|
|
||||||
g1y = f2y + v1.y()*(f1y + v1.y());
|
|
||||||
g2y = f2y + v2.y()*(f1y + v2.y());
|
|
||||||
|
|
||||||
scalar f1z, f2z, f3z, g0z, g1z, g2z;
|
|
||||||
|
|
||||||
tmp0 = v0.z() + v1.z();
|
|
||||||
f1z = tmp0 + v2.z();
|
|
||||||
tmp1 = v0.z()*v0.z();
|
|
||||||
tmp2 = tmp1 + v1.z()*tmp0;
|
|
||||||
f2z = tmp2 + v2.z()*f1z;
|
|
||||||
f3z = v0.z()*tmp1 + v1.z()*tmp2 + v2.z()*f2z;
|
|
||||||
g0z = f2z + v0.z()*(f1z + v0.z());
|
|
||||||
g1z = f2z + v1.z()*(f1z + v1.z());
|
|
||||||
g2z = f2z + v2.z()*(f1z + v2.z());
|
|
||||||
|
|
||||||
// update integrals
|
|
||||||
integrals[0] += n.x()*f1x;
|
|
||||||
integrals[1] += n.x()*f2x;
|
|
||||||
integrals[2] += n.y()*f2y;
|
|
||||||
integrals[3] += n.z()*f2z;
|
|
||||||
integrals[4] += n.x()*f3x;
|
|
||||||
integrals[5] += n.y()*f3y;
|
|
||||||
integrals[6] += n.z()*f3z;
|
|
||||||
integrals[7] += n.x()*(v0.y()*g0x + v1.y()*g1x + v2.y()*g2x);
|
|
||||||
integrals[8] += n.y()*(v0.z()*g0y + v1.z()*g1y + v2.z()*g2y);
|
|
||||||
integrals[9] += n.z()*(v0.x()*g0z + v1.x()*g1z + v2.x()*g2z);
|
|
||||||
}
|
|
||||||
|
|
||||||
integrals[0] *= r6;
|
|
||||||
integrals[1] *= r24;
|
|
||||||
integrals[2] *= r24;
|
|
||||||
integrals[3] *= r24;
|
|
||||||
integrals[4] *= r60;
|
|
||||||
integrals[5] *= r60;
|
|
||||||
integrals[6] *= r60;
|
|
||||||
integrals[7] *= r120;
|
|
||||||
integrals[8] *= r120;
|
|
||||||
integrals[9] *= r120;
|
|
||||||
|
|
||||||
// mass
|
|
||||||
mass = integrals[0];
|
|
||||||
|
|
||||||
// center of mass
|
|
||||||
cM = vector(integrals[1], integrals[2], integrals[3])/mass;
|
|
||||||
|
|
||||||
// inertia relative to origin
|
|
||||||
J.xx() = integrals[5] + integrals[6];
|
|
||||||
J.xy() = -integrals[7];
|
|
||||||
J.xz() = -integrals[9];
|
|
||||||
J.yx() = J.xy();
|
|
||||||
J.yy() = integrals[4] + integrals[6];
|
|
||||||
J.yz() = -integrals[8];
|
|
||||||
J.zx() = J.xz();
|
|
||||||
J.zy() = J.yz();
|
|
||||||
J.zz() = integrals[4] + integrals[5];
|
|
||||||
|
|
||||||
// inertia relative to center of mass
|
|
||||||
J -= mass*((cM & cM)*I - cM*cM);
|
|
||||||
|
|
||||||
// Apply density
|
|
||||||
mass *= density;
|
|
||||||
J *= density;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int main(int argc, char *argv[])
|
int main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
|
argList::addOption
|
||||||
|
(
|
||||||
|
"cell",
|
||||||
|
"label",
|
||||||
|
"cell to use for inertia calculation, defaults to 0"
|
||||||
|
);
|
||||||
|
|
||||||
|
#include "setRootCase.H"
|
||||||
|
#include "createTime.H"
|
||||||
|
#include "createPolyMesh.H"
|
||||||
|
|
||||||
scalar density = 1.0;
|
scalar density = 1.0;
|
||||||
|
|
||||||
{
|
{
|
||||||
@ -286,16 +144,7 @@ int main(int argc, char *argv[])
|
|||||||
vector cM = vector::zero;
|
vector cM = vector::zero;
|
||||||
tensor J = tensor::zero;
|
tensor J = tensor::zero;
|
||||||
|
|
||||||
massPropertiesSolid
|
momentOfInertia::massPropertiesSolid(pts, tetFaces, density, m, cM, J);
|
||||||
(
|
|
||||||
|
|
||||||
pts,
|
|
||||||
tetFaces,
|
|
||||||
density,
|
|
||||||
m,
|
|
||||||
cM,
|
|
||||||
J
|
|
||||||
);
|
|
||||||
|
|
||||||
vector eVal = eigenValues(J);
|
vector eVal = eigenValues(J);
|
||||||
|
|
||||||
@ -344,7 +193,50 @@ int main(int argc, char *argv[])
|
|||||||
{
|
{
|
||||||
str << "l " << nPts + 1 << ' ' << i + 1 << endl;
|
str << "l " << nPts + 1 << ' ' << i + 1 << endl;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
const label cellI = args.optionLookupOrDefault("cell", 0);
|
||||||
|
|
||||||
|
tensorField mI = momentOfInertia::meshInertia(mesh);
|
||||||
|
|
||||||
|
tensor& J = mI[cellI];
|
||||||
|
|
||||||
|
vector eVal = eigenValues(J);
|
||||||
|
|
||||||
|
Info<< nl
|
||||||
|
<< "Inertia tensor of cell " << cellI << " " << J << nl
|
||||||
|
<< "eigenValues (principal moments) " << eVal << endl;
|
||||||
|
|
||||||
|
J /= cmptMax(eVal);
|
||||||
|
|
||||||
|
tensor eVec = eigenVectors(J);
|
||||||
|
|
||||||
|
Info<< "eigenVectors (principal axes, from normalised inertia) " << eVec
|
||||||
|
<< endl;
|
||||||
|
|
||||||
|
OFstream str("cell_" + name(cellI) + "_inertia.obj");
|
||||||
|
|
||||||
|
Info<< nl << "Writing scaled principal axes of cell " << cellI << " to "
|
||||||
|
<< str.name() << endl;
|
||||||
|
|
||||||
|
const point& cC = mesh.cellCentres()[cellI];
|
||||||
|
|
||||||
|
scalar scale = mag
|
||||||
|
(
|
||||||
|
(cC - mesh.faceCentres()[mesh.cells()[cellI][0]])
|
||||||
|
/eVal.component(findMin(eVal))
|
||||||
|
);
|
||||||
|
|
||||||
|
meshTools::writeOBJ(str, cC);
|
||||||
|
meshTools::writeOBJ(str, cC + scale*eVal.x()*eVec.x());
|
||||||
|
meshTools::writeOBJ(str, cC + scale*eVal.y()*eVec.y());
|
||||||
|
meshTools::writeOBJ(str, cC + scale*eVal.z()*eVec.z());
|
||||||
|
|
||||||
|
for (label i = 1; i < 4; i++)
|
||||||
|
{
|
||||||
|
str << "l " << 1 << ' ' << i + 1 << endl;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Info<< nl << "End" << nl << endl;
|
Info<< nl << "End" << nl << endl;
|
||||||
|
|||||||
@ -33,9 +33,6 @@ Description
|
|||||||
|
|
||||||
#include "argList.H"
|
#include "argList.H"
|
||||||
#include "ListOps.H"
|
#include "ListOps.H"
|
||||||
#include "face.H"
|
|
||||||
#include "tetPointRef.H"
|
|
||||||
#include "triFaceList.H"
|
|
||||||
#include "triSurface.H"
|
#include "triSurface.H"
|
||||||
#include "OFstream.H"
|
#include "OFstream.H"
|
||||||
#include "meshTools.H"
|
#include "meshTools.H"
|
||||||
@ -43,242 +40,12 @@ Description
|
|||||||
#include "transform.H"
|
#include "transform.H"
|
||||||
#include "IOmanip.H"
|
#include "IOmanip.H"
|
||||||
#include "Pair.H"
|
#include "Pair.H"
|
||||||
|
#include "momentOfInertia.H"
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
using namespace Foam;
|
using namespace Foam;
|
||||||
|
|
||||||
void massPropertiesSolid
|
|
||||||
(
|
|
||||||
const pointField& pts,
|
|
||||||
const triFaceList& triFaces,
|
|
||||||
scalar density,
|
|
||||||
scalar& mass,
|
|
||||||
vector& cM,
|
|
||||||
tensor& J
|
|
||||||
)
|
|
||||||
{
|
|
||||||
// Reimplemented from: Wm4PolyhedralMassProperties.cpp
|
|
||||||
// File Version: 4.10.0 (2009/11/18)
|
|
||||||
|
|
||||||
// Geometric Tools, LC
|
|
||||||
// Copyright (c) 1998-2010
|
|
||||||
// Distributed under the Boost Software License, Version 1.0.
|
|
||||||
// http://www.boost.org/LICENSE_1_0.txt
|
|
||||||
// http://www.geometrictools.com/License/Boost/LICENSE_1_0.txt
|
|
||||||
|
|
||||||
// Boost Software License - Version 1.0 - August 17th, 2003
|
|
||||||
|
|
||||||
// Permission is hereby granted, free of charge, to any person or
|
|
||||||
// organization obtaining a copy of the software and accompanying
|
|
||||||
// documentation covered by this license (the "Software") to use,
|
|
||||||
// reproduce, display, distribute, execute, and transmit the
|
|
||||||
// Software, and to prepare derivative works of the Software, and
|
|
||||||
// to permit third-parties to whom the Software is furnished to do
|
|
||||||
// so, all subject to the following:
|
|
||||||
|
|
||||||
// The copyright notices in the Software and this entire
|
|
||||||
// statement, including the above license grant, this restriction
|
|
||||||
// and the following disclaimer, must be included in all copies of
|
|
||||||
// the Software, in whole or in part, and all derivative works of
|
|
||||||
// the Software, unless such copies or derivative works are solely
|
|
||||||
// in the form of machine-executable object code generated by a
|
|
||||||
// source language processor.
|
|
||||||
|
|
||||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
||||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
|
||||||
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND
|
|
||||||
// NON-INFRINGEMENT. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR
|
|
||||||
// ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE FOR ANY DAMAGES OR
|
|
||||||
// OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
|
|
||||||
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
|
||||||
// USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
||||||
|
|
||||||
const scalar r6 = 1.0/6.0;
|
|
||||||
const scalar r24 = 1.0/24.0;
|
|
||||||
const scalar r60 = 1.0/60.0;
|
|
||||||
const scalar r120 = 1.0/120.0;
|
|
||||||
|
|
||||||
// order: 1, x, y, z, x^2, y^2, z^2, xy, yz, zx
|
|
||||||
scalarField integrals(10, 0.0);
|
|
||||||
|
|
||||||
forAll(triFaces, i)
|
|
||||||
{
|
|
||||||
const triFace& tri(triFaces[i]);
|
|
||||||
|
|
||||||
// vertices of triangle i
|
|
||||||
vector v0 = pts[tri[0]];
|
|
||||||
vector v1 = pts[tri[1]];
|
|
||||||
vector v2 = pts[tri[2]];
|
|
||||||
|
|
||||||
// cross product of edges
|
|
||||||
vector eA = v1 - v0;
|
|
||||||
vector eB = v2 - v0;
|
|
||||||
vector n = eA ^ eB;
|
|
||||||
|
|
||||||
// compute integral terms
|
|
||||||
scalar tmp0, tmp1, tmp2;
|
|
||||||
|
|
||||||
scalar f1x, f2x, f3x, g0x, g1x, g2x;
|
|
||||||
|
|
||||||
tmp0 = v0.x() + v1.x();
|
|
||||||
f1x = tmp0 + v2.x();
|
|
||||||
tmp1 = v0.x()*v0.x();
|
|
||||||
tmp2 = tmp1 + v1.x()*tmp0;
|
|
||||||
f2x = tmp2 + v2.x()*f1x;
|
|
||||||
f3x = v0.x()*tmp1 + v1.x()*tmp2 + v2.x()*f2x;
|
|
||||||
g0x = f2x + v0.x()*(f1x + v0.x());
|
|
||||||
g1x = f2x + v1.x()*(f1x + v1.x());
|
|
||||||
g2x = f2x + v2.x()*(f1x + v2.x());
|
|
||||||
|
|
||||||
scalar f1y, f2y, f3y, g0y, g1y, g2y;
|
|
||||||
|
|
||||||
tmp0 = v0.y() + v1.y();
|
|
||||||
f1y = tmp0 + v2.y();
|
|
||||||
tmp1 = v0.y()*v0.y();
|
|
||||||
tmp2 = tmp1 + v1.y()*tmp0;
|
|
||||||
f2y = tmp2 + v2.y()*f1y;
|
|
||||||
f3y = v0.y()*tmp1 + v1.y()*tmp2 + v2.y()*f2y;
|
|
||||||
g0y = f2y + v0.y()*(f1y + v0.y());
|
|
||||||
g1y = f2y + v1.y()*(f1y + v1.y());
|
|
||||||
g2y = f2y + v2.y()*(f1y + v2.y());
|
|
||||||
|
|
||||||
scalar f1z, f2z, f3z, g0z, g1z, g2z;
|
|
||||||
|
|
||||||
tmp0 = v0.z() + v1.z();
|
|
||||||
f1z = tmp0 + v2.z();
|
|
||||||
tmp1 = v0.z()*v0.z();
|
|
||||||
tmp2 = tmp1 + v1.z()*tmp0;
|
|
||||||
f2z = tmp2 + v2.z()*f1z;
|
|
||||||
f3z = v0.z()*tmp1 + v1.z()*tmp2 + v2.z()*f2z;
|
|
||||||
g0z = f2z + v0.z()*(f1z + v0.z());
|
|
||||||
g1z = f2z + v1.z()*(f1z + v1.z());
|
|
||||||
g2z = f2z + v2.z()*(f1z + v2.z());
|
|
||||||
|
|
||||||
// update integrals
|
|
||||||
integrals[0] += n.x()*f1x;
|
|
||||||
integrals[1] += n.x()*f2x;
|
|
||||||
integrals[2] += n.y()*f2y;
|
|
||||||
integrals[3] += n.z()*f2z;
|
|
||||||
integrals[4] += n.x()*f3x;
|
|
||||||
integrals[5] += n.y()*f3y;
|
|
||||||
integrals[6] += n.z()*f3z;
|
|
||||||
integrals[7] += n.x()*(v0.y()*g0x + v1.y()*g1x + v2.y()*g2x);
|
|
||||||
integrals[8] += n.y()*(v0.z()*g0y + v1.z()*g1y + v2.z()*g2y);
|
|
||||||
integrals[9] += n.z()*(v0.x()*g0z + v1.x()*g1z + v2.x()*g2z);
|
|
||||||
}
|
|
||||||
|
|
||||||
integrals[0] *= r6;
|
|
||||||
integrals[1] *= r24;
|
|
||||||
integrals[2] *= r24;
|
|
||||||
integrals[3] *= r24;
|
|
||||||
integrals[4] *= r60;
|
|
||||||
integrals[5] *= r60;
|
|
||||||
integrals[6] *= r60;
|
|
||||||
integrals[7] *= r120;
|
|
||||||
integrals[8] *= r120;
|
|
||||||
integrals[9] *= r120;
|
|
||||||
|
|
||||||
// mass
|
|
||||||
mass = integrals[0];
|
|
||||||
|
|
||||||
// center of mass
|
|
||||||
cM = vector(integrals[1], integrals[2], integrals[3])/mass;
|
|
||||||
|
|
||||||
// inertia relative to origin
|
|
||||||
J.xx() = integrals[5] + integrals[6];
|
|
||||||
J.xy() = -integrals[7];
|
|
||||||
J.xz() = -integrals[9];
|
|
||||||
J.yx() = J.xy();
|
|
||||||
J.yy() = integrals[4] + integrals[6];
|
|
||||||
J.yz() = -integrals[8];
|
|
||||||
J.zx() = J.xz();
|
|
||||||
J.zy() = J.yz();
|
|
||||||
J.zz() = integrals[4] + integrals[5];
|
|
||||||
|
|
||||||
// inertia relative to center of mass
|
|
||||||
J -= mass*((cM & cM)*I - cM*cM);
|
|
||||||
|
|
||||||
// Apply density
|
|
||||||
mass *= density;
|
|
||||||
J *= density;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void massPropertiesShell
|
|
||||||
(
|
|
||||||
const pointField& pts,
|
|
||||||
const triFaceList& triFaces,
|
|
||||||
scalar density,
|
|
||||||
scalar& mass,
|
|
||||||
vector& cM,
|
|
||||||
tensor& J
|
|
||||||
)
|
|
||||||
{
|
|
||||||
// Reset properties for accumulation
|
|
||||||
|
|
||||||
mass = 0.0;
|
|
||||||
cM = vector::zero;
|
|
||||||
J = tensor::zero;
|
|
||||||
|
|
||||||
// Find centre of mass
|
|
||||||
|
|
||||||
forAll(triFaces, i)
|
|
||||||
{
|
|
||||||
const triFace& tri(triFaces[i]);
|
|
||||||
|
|
||||||
triPointRef t
|
|
||||||
(
|
|
||||||
pts[tri[0]],
|
|
||||||
pts[tri[1]],
|
|
||||||
pts[tri[2]]
|
|
||||||
);
|
|
||||||
|
|
||||||
scalar triMag = t.mag();
|
|
||||||
|
|
||||||
cM += triMag*t.centre();
|
|
||||||
|
|
||||||
mass += triMag;
|
|
||||||
}
|
|
||||||
|
|
||||||
cM /= mass;
|
|
||||||
|
|
||||||
mass *= density;
|
|
||||||
|
|
||||||
// Find inertia around centre of mass
|
|
||||||
|
|
||||||
forAll(triFaces, i)
|
|
||||||
{
|
|
||||||
const triFace& tri(triFaces[i]);
|
|
||||||
|
|
||||||
J += triPointRef
|
|
||||||
(
|
|
||||||
pts[tri[0]],
|
|
||||||
pts[tri[1]],
|
|
||||||
pts[tri[2]]
|
|
||||||
).inertia(cM, density);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
tensor applyParallelAxisTheorem
|
|
||||||
(
|
|
||||||
scalar m,
|
|
||||||
const vector& cM,
|
|
||||||
const tensor& J,
|
|
||||||
const vector& refPt
|
|
||||||
)
|
|
||||||
{
|
|
||||||
// The displacement vector (refPt = cM) is the displacement of the
|
|
||||||
// new reference point from the centre of mass of the body that
|
|
||||||
// the inertia tensor applies to.
|
|
||||||
|
|
||||||
vector d = (refPt - cM);
|
|
||||||
|
|
||||||
return J + m*((d & d)*I - d*d);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int main(int argc, char *argv[])
|
int main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
argList::addNote
|
argList::addNote
|
||||||
@ -321,40 +88,17 @@ int main(int argc, char *argv[])
|
|||||||
|
|
||||||
triSurface surf(surfFileName);
|
triSurface surf(surfFileName);
|
||||||
|
|
||||||
triFaceList faces(surf.size());
|
|
||||||
|
|
||||||
forAll(surf, i)
|
|
||||||
{
|
|
||||||
faces[i] = triFace(surf[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
scalar m = 0.0;
|
scalar m = 0.0;
|
||||||
vector cM = vector::zero;
|
vector cM = vector::zero;
|
||||||
tensor J = tensor::zero;
|
tensor J = tensor::zero;
|
||||||
|
|
||||||
if (args.optionFound("shellProperties"))
|
if (args.optionFound("shellProperties"))
|
||||||
{
|
{
|
||||||
massPropertiesShell
|
momentOfInertia::massPropertiesShell(surf, density, m, cM, J);
|
||||||
(
|
|
||||||
surf.points(),
|
|
||||||
faces,
|
|
||||||
density,
|
|
||||||
m,
|
|
||||||
cM,
|
|
||||||
J
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
massPropertiesSolid
|
momentOfInertia::massPropertiesSolid(surf, density, m, cM, J);
|
||||||
(
|
|
||||||
surf.points(),
|
|
||||||
faces,
|
|
||||||
density,
|
|
||||||
m,
|
|
||||||
cM,
|
|
||||||
J
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m < 0)
|
if (m < 0)
|
||||||
@ -583,7 +327,7 @@ int main(int argc, char *argv[])
|
|||||||
showTransform = false;
|
showTransform = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
Info<< nl << setprecision(10)
|
Info<< nl << setprecision(12)
|
||||||
<< "Density: " << density << nl
|
<< "Density: " << density << nl
|
||||||
<< "Mass: " << m << nl
|
<< "Mass: " << m << nl
|
||||||
<< "Centre of mass: " << cM << nl
|
<< "Centre of mass: " << cM << nl
|
||||||
@ -615,7 +359,7 @@ int main(int argc, char *argv[])
|
|||||||
if (calcAroundRefPt)
|
if (calcAroundRefPt)
|
||||||
{
|
{
|
||||||
Info<< nl << "Inertia tensor relative to " << refPt << ": " << nl
|
Info<< nl << "Inertia tensor relative to " << refPt << ": " << nl
|
||||||
<< applyParallelAxisTheorem(m, cM, J, refPt)
|
<< momentOfInertia::applyParallelAxisTheorem(m, cM, J, refPt)
|
||||||
<< endl;
|
<< endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -41,6 +41,7 @@ SourceFiles
|
|||||||
#include "tetPointRef.H"
|
#include "tetPointRef.H"
|
||||||
#include "triPointRef.H"
|
#include "triPointRef.H"
|
||||||
#include "polyMesh.H"
|
#include "polyMesh.H"
|
||||||
|
#include "triFace.H"
|
||||||
#include "face.H"
|
#include "face.H"
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
@ -146,6 +147,10 @@ public:
|
|||||||
// mesh face for this tet from the supplied mesh
|
// mesh face for this tet from the supplied mesh
|
||||||
inline triPointRef faceTri(const polyMesh& mesh) const;
|
inline triPointRef faceTri(const polyMesh& mesh) const;
|
||||||
|
|
||||||
|
//- Return the point indices corresponding to the tri on the mesh
|
||||||
|
// face for this tet from the supplied mesh
|
||||||
|
inline triFace faceTriIs(const polyMesh& mesh) const;
|
||||||
|
|
||||||
//- Return the geometry corresponding to the tri on the
|
//- Return the geometry corresponding to the tri on the
|
||||||
// mesh face for this tet from the supplied mesh using
|
// mesh face for this tet from the supplied mesh using
|
||||||
// the old position
|
// the old position
|
||||||
|
|||||||
@ -122,6 +122,21 @@ Foam::triPointRef Foam::tetIndices::faceTri(const polyMesh& mesh) const
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Foam::triFace Foam::tetIndices::faceTriIs(const polyMesh& mesh) const
|
||||||
|
{
|
||||||
|
const faceList& pFaces = mesh.faces();
|
||||||
|
|
||||||
|
const Foam::face& f = pFaces[faceI_];
|
||||||
|
|
||||||
|
return triFace
|
||||||
|
(
|
||||||
|
f[faceBasePtI_],
|
||||||
|
f[facePtAI_],
|
||||||
|
f[facePtBI_]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
Foam::triPointRef Foam::tetIndices::oldFaceTri(const polyMesh& mesh) const
|
Foam::triPointRef Foam::tetIndices::oldFaceTri(const polyMesh& mesh) const
|
||||||
{
|
{
|
||||||
const pointField& oldPPts = mesh.oldPoints();
|
const pointField& oldPPts = mesh.oldPoints();
|
||||||
|
|||||||
@ -127,6 +127,7 @@ $(cellZoneSources)/setToCellZone/setToCellZone.C
|
|||||||
pointZoneSources = sets/pointZoneSources
|
pointZoneSources = sets/pointZoneSources
|
||||||
$(pointZoneSources)/setToPointZone/setToPointZone.C
|
$(pointZoneSources)/setToPointZone/setToPointZone.C
|
||||||
|
|
||||||
|
momentOfInertia/momentOfInertia.C
|
||||||
|
|
||||||
surfaceSets/surfaceSets.C
|
surfaceSets/surfaceSets.C
|
||||||
|
|
||||||
|
|||||||
@ -21,382 +21,328 @@ License
|
|||||||
You should have received a copy of the GNU General Public License
|
You should have received a copy of the GNU General Public License
|
||||||
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
|
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
Class
|
\*---------------------------------------------------------------------------*/
|
||||||
momentOfInertia
|
|
||||||
|
|
||||||
Description
|
|
||||||
Reimplementation of volInt.c by Brian Mirtich.
|
|
||||||
* mirtich@cs.berkeley.edu *
|
|
||||||
* http://www.cs.berkeley.edu/~mirtich *
|
|
||||||
|
|
||||||
-------------------------------------------------------------------------------
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "momentOfInertia.H"
|
#include "momentOfInertia.H"
|
||||||
//#include "pyramidPointFaceRef.H"
|
|
||||||
|
|
||||||
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
|
// * * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * //
|
||||||
|
|
||||||
//Foam::tensor Foam::momentOfInertia
|
void Foam::momentOfInertia::massPropertiesSolid
|
||||||
//(
|
|
||||||
// const pointField& points,
|
|
||||||
// const faceList& faces,
|
|
||||||
// const cell& cFaces,
|
|
||||||
// const point& cc
|
|
||||||
//)
|
|
||||||
//{
|
|
||||||
// tensor t(tensor::zero);
|
|
||||||
//
|
|
||||||
// forAll(cFaces, i)
|
|
||||||
// {
|
|
||||||
// const face& f = faces[cFaces[i]];
|
|
||||||
//
|
|
||||||
// scalar pyrVol = pyramidPointFaceRef(f, cc).mag(points);
|
|
||||||
//
|
|
||||||
// vector pyrCentre = pyramidPointFaceRef(f, cc).centre(points);
|
|
||||||
//
|
|
||||||
// vector d = pyrCentre - cc;
|
|
||||||
//
|
|
||||||
// t.xx() += pyrVol*(sqr(d.y()) + sqr(d.z()));
|
|
||||||
// t.yy() += pyrVol*(sqr(d.x()) + sqr(d.z()));
|
|
||||||
// t.zz() += pyrVol*(sqr(d.x()) + sqr(d.y()));
|
|
||||||
//
|
|
||||||
// t.xy() -= pyrVol*d.x()*d.y();
|
|
||||||
// t.xz() -= pyrVol*d.x()*d.z();
|
|
||||||
// t.yz() -= pyrVol*d.y()*d.z();
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// // Symmetric
|
|
||||||
// t.yx() = t.xy();
|
|
||||||
// t.zx() = t.xz();
|
|
||||||
// t.zy() = t.yz();
|
|
||||||
//
|
|
||||||
// return t;
|
|
||||||
//}
|
|
||||||
|
|
||||||
|
|
||||||
#define sqr(x) ((x)*(x))
|
|
||||||
#define pow3(x) ((x)*(x)*(x))
|
|
||||||
|
|
||||||
// compute various integrations over projection of face
|
|
||||||
void Foam::compProjectionIntegrals
|
|
||||||
(
|
(
|
||||||
const pointField& points,
|
const pointField& pts,
|
||||||
const face& f,
|
const triFaceList& triFaces,
|
||||||
const direction A,
|
scalar density,
|
||||||
const direction B,
|
scalar& mass,
|
||||||
|
vector& cM,
|
||||||
scalar& P1,
|
|
||||||
scalar& Pa,
|
|
||||||
scalar& Pb,
|
|
||||||
scalar& Paa,
|
|
||||||
scalar& Pab,
|
|
||||||
scalar& Pbb,
|
|
||||||
scalar& Paaa,
|
|
||||||
scalar& Paab,
|
|
||||||
scalar& Pabb,
|
|
||||||
scalar& Pbbb
|
|
||||||
)
|
|
||||||
{
|
|
||||||
P1 = Pa = Pb = Paa = Pab = Pbb = Paaa = Paab = Pabb = Pbbb = 0.0;
|
|
||||||
|
|
||||||
forAll(f, i)
|
|
||||||
{
|
|
||||||
scalar a0 = points[f[i]][A];
|
|
||||||
scalar b0 = points[f[i]][B];
|
|
||||||
scalar a1 = points[f[(i+1) % f.size()]][A];
|
|
||||||
scalar b1 = points[f[(i+1) % f.size()]][B];
|
|
||||||
scalar da = a1 - a0;
|
|
||||||
scalar db = b1 - b0;
|
|
||||||
|
|
||||||
scalar a0_2 = a0 * a0;
|
|
||||||
scalar a0_3 = a0_2 * a0;
|
|
||||||
scalar a0_4 = a0_3 * a0;
|
|
||||||
|
|
||||||
scalar b0_2 = b0 * b0;
|
|
||||||
scalar b0_3 = b0_2 * b0;
|
|
||||||
scalar b0_4 = b0_3 * b0;
|
|
||||||
|
|
||||||
scalar a1_2 = a1 * a1;
|
|
||||||
scalar a1_3 = a1_2 * a1;
|
|
||||||
|
|
||||||
scalar b1_2 = b1 * b1;
|
|
||||||
scalar b1_3 = b1_2 * b1;
|
|
||||||
|
|
||||||
scalar C1 = a1 + a0;
|
|
||||||
|
|
||||||
scalar Ca = a1*C1 + a0_2;
|
|
||||||
scalar Caa = a1*Ca + a0_3;
|
|
||||||
scalar Caaa = a1*Caa + a0_4;
|
|
||||||
|
|
||||||
scalar Cb = b1*(b1 + b0) + b0_2;
|
|
||||||
scalar Cbb = b1*Cb + b0_3;
|
|
||||||
scalar Cbbb = b1*Cbb + b0_4;
|
|
||||||
|
|
||||||
scalar Cab = 3*a1_2 + 2*a1*a0 + a0_2;
|
|
||||||
scalar Kab = a1_2 + 2*a1*a0 + 3*a0_2;
|
|
||||||
|
|
||||||
scalar Caab = a0*Cab + 4*a1_3;
|
|
||||||
scalar Kaab = a1*Kab + 4*a0_3;
|
|
||||||
|
|
||||||
scalar Cabb = 4*b1_3 + 3*b1_2*b0 + 2*b1*b0_2 + b0_3;
|
|
||||||
scalar Kabb = b1_3 + 2*b1_2*b0 + 3*b1*b0_2 + 4*b0_3;
|
|
||||||
|
|
||||||
P1 += db*C1;
|
|
||||||
Pa += db*Ca;
|
|
||||||
Paa += db*Caa;
|
|
||||||
Paaa += db*Caaa;
|
|
||||||
Pb += da*Cb;
|
|
||||||
Pbb += da*Cbb;
|
|
||||||
Pbbb += da*Cbbb;
|
|
||||||
Pab += db*(b1*Cab + b0*Kab);
|
|
||||||
Paab += db*(b1*Caab + b0*Kaab);
|
|
||||||
Pabb += da*(a1*Cabb + a0*Kabb);
|
|
||||||
}
|
|
||||||
|
|
||||||
P1 /= 2.0;
|
|
||||||
Pa /= 6.0;
|
|
||||||
Paa /= 12.0;
|
|
||||||
Paaa /= 20.0;
|
|
||||||
Pb /= -6.0;
|
|
||||||
Pbb /= -12.0;
|
|
||||||
Pbbb /= -20.0;
|
|
||||||
Pab /= 24.0;
|
|
||||||
Paab /= 60.0;
|
|
||||||
Pabb /= -60.0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void Foam::compFaceIntegrals
|
|
||||||
(
|
|
||||||
const pointField& points,
|
|
||||||
const face& f,
|
|
||||||
const vector& n,
|
|
||||||
const scalar w,
|
|
||||||
const direction A,
|
|
||||||
const direction B,
|
|
||||||
const direction C,
|
|
||||||
|
|
||||||
scalar& Fa,
|
|
||||||
scalar& Fb,
|
|
||||||
scalar& Fc,
|
|
||||||
scalar& Faa,
|
|
||||||
scalar& Fbb,
|
|
||||||
scalar& Fcc,
|
|
||||||
scalar& Faaa,
|
|
||||||
scalar& Fbbb,
|
|
||||||
scalar& Fccc,
|
|
||||||
scalar& Faab,
|
|
||||||
scalar& Fbbc,
|
|
||||||
scalar& Fcca
|
|
||||||
)
|
|
||||||
{
|
|
||||||
scalar P1, Pa, Pb, Paa, Pab, Pbb, Paaa, Paab, Pabb, Pbbb;
|
|
||||||
|
|
||||||
compProjectionIntegrals
|
|
||||||
(
|
|
||||||
points,
|
|
||||||
f,
|
|
||||||
A,
|
|
||||||
B,
|
|
||||||
|
|
||||||
P1,
|
|
||||||
Pa,
|
|
||||||
Pb,
|
|
||||||
Paa,
|
|
||||||
Pab,
|
|
||||||
Pbb,
|
|
||||||
Paaa,
|
|
||||||
Paab,
|
|
||||||
Pabb,
|
|
||||||
Pbbb
|
|
||||||
);
|
|
||||||
|
|
||||||
scalar k1 = 1 / n[C];
|
|
||||||
scalar k2 = k1 * k1;
|
|
||||||
scalar k3 = k2 * k1;
|
|
||||||
scalar k4 = k3 * k1;
|
|
||||||
|
|
||||||
Fa = k1 * Pa;
|
|
||||||
Fb = k1 * Pb;
|
|
||||||
Fc = -k2 * (n[A]*Pa + n[B]*Pb + w*P1);
|
|
||||||
|
|
||||||
Faa = k1 * Paa;
|
|
||||||
Fbb = k1 * Pbb;
|
|
||||||
Fcc = k3 * (sqr(n[A])*Paa + 2*n[A]*n[B]*Pab + sqr(n[B])*Pbb
|
|
||||||
+ w*(2*(n[A]*Pa + n[B]*Pb) + w*P1));
|
|
||||||
|
|
||||||
Faaa = k1 * Paaa;
|
|
||||||
Fbbb = k1 * Pbbb;
|
|
||||||
Fccc = -k4 * (pow3(n[A])*Paaa + 3*sqr(n[A])*n[B]*Paab
|
|
||||||
+ 3*n[A]*sqr(n[B])*Pabb + pow3(n[B])*Pbbb
|
|
||||||
+ 3*w*(sqr(n[A])*Paa + 2*n[A]*n[B]*Pab + sqr(n[B])*Pbb)
|
|
||||||
+ w*w*(3*(n[A]*Pa + n[B]*Pb) + w*P1));
|
|
||||||
|
|
||||||
Faab = k1 * Paab;
|
|
||||||
Fbbc = -k2 * (n[A]*Pabb + n[B]*Pbbb + w*Pbb);
|
|
||||||
Fcca = k3 * (sqr(n[A])*Paaa + 2*n[A]*n[B]*Paab + sqr(n[B])*Pabb
|
|
||||||
+ w*(2*(n[A]*Paa + n[B]*Pab) + w*Pa));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void Foam::compVolumeIntegrals
|
|
||||||
(
|
|
||||||
const pointField& points,
|
|
||||||
const faceList& faces,
|
|
||||||
const cell& cFaces,
|
|
||||||
const vectorField& fNorm,
|
|
||||||
const scalarField& fW,
|
|
||||||
|
|
||||||
scalar& T0,
|
|
||||||
vector& T1,
|
|
||||||
vector& T2,
|
|
||||||
vector& TP
|
|
||||||
)
|
|
||||||
{
|
|
||||||
T0 = 0;
|
|
||||||
T1 = vector::zero;
|
|
||||||
T2 = vector::zero;
|
|
||||||
TP = vector::zero;
|
|
||||||
|
|
||||||
forAll(cFaces, i)
|
|
||||||
{
|
|
||||||
const vector& n = fNorm[i];
|
|
||||||
|
|
||||||
scalar nx = mag(n[0]);
|
|
||||||
scalar ny = mag(n[1]);
|
|
||||||
scalar nz = mag(n[2]);
|
|
||||||
|
|
||||||
direction A, B, C;
|
|
||||||
|
|
||||||
if (nx > ny && nx > nz)
|
|
||||||
{
|
|
||||||
C = 0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
C = (ny > nz) ? 1 : 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
A = (C + 1) % 3;
|
|
||||||
B = (A + 1) % 3;
|
|
||||||
|
|
||||||
scalar Fa, Fb, Fc, Faa, Fbb, Fcc, Faaa, Fbbb, Fccc, Faab, Fbbc, Fcca;
|
|
||||||
compFaceIntegrals
|
|
||||||
(
|
|
||||||
points,
|
|
||||||
faces[cFaces[i]],
|
|
||||||
n,
|
|
||||||
fW[i],
|
|
||||||
A,
|
|
||||||
B,
|
|
||||||
C,
|
|
||||||
|
|
||||||
Fa,
|
|
||||||
Fb,
|
|
||||||
Fc,
|
|
||||||
Faa,
|
|
||||||
Fbb,
|
|
||||||
Fcc,
|
|
||||||
Faaa,
|
|
||||||
Fbbb,
|
|
||||||
Fccc,
|
|
||||||
Faab,
|
|
||||||
Fbbc,
|
|
||||||
Fcca
|
|
||||||
);
|
|
||||||
|
|
||||||
T0 += n[0] * ((A == 0) ? Fa : ((B == 0) ? Fb : Fc));
|
|
||||||
|
|
||||||
T1[A] += n[A] * Faa;
|
|
||||||
T1[B] += n[B] * Fbb;
|
|
||||||
T1[C] += n[C] * Fcc;
|
|
||||||
|
|
||||||
T2[A] += n[A] * Faaa;
|
|
||||||
T2[B] += n[B] * Fbbb;
|
|
||||||
T2[C] += n[C] * Fccc;
|
|
||||||
|
|
||||||
TP[A] += n[A] * Faab;
|
|
||||||
TP[B] += n[B] * Fbbc;
|
|
||||||
TP[C] += n[C] * Fcca;
|
|
||||||
}
|
|
||||||
|
|
||||||
T1 /= 2;
|
|
||||||
T2 /= 3;
|
|
||||||
TP /= 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Calculate
|
|
||||||
// - r: centre of mass
|
|
||||||
// - J: inertia around origin (point 0,0,0)
|
|
||||||
void Foam::momentOfIntertia
|
|
||||||
(
|
|
||||||
const pointField& points,
|
|
||||||
const faceList& faces,
|
|
||||||
const cell& cFaces,
|
|
||||||
point& r,
|
|
||||||
tensor& J
|
tensor& J
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
// Face normals
|
// Reimplemented from: Wm4PolyhedralMassProperties.cpp
|
||||||
vectorField fNorm(cFaces.size());
|
// File Version: 4.10.0 (2009/11/18)
|
||||||
scalarField fW(cFaces.size());
|
|
||||||
|
|
||||||
forAll(cFaces, i)
|
// Geometric Tools, LC
|
||||||
|
// Copyright (c) 1998-2010
|
||||||
|
// Distributed under the Boost Software License, Version 1.0.
|
||||||
|
// http://www.boost.org/LICENSE_1_0.txt
|
||||||
|
// http://www.geometrictools.com/License/Boost/LICENSE_1_0.txt
|
||||||
|
|
||||||
|
// Boost Software License - Version 1.0 - August 17th, 2003
|
||||||
|
|
||||||
|
// Permission is hereby granted, free of charge, to any person or
|
||||||
|
// organization obtaining a copy of the software and accompanying
|
||||||
|
// documentation covered by this license (the "Software") to use,
|
||||||
|
// reproduce, display, distribute, execute, and transmit the
|
||||||
|
// Software, and to prepare derivative works of the Software, and
|
||||||
|
// to permit third-parties to whom the Software is furnished to do
|
||||||
|
// so, all subject to the following:
|
||||||
|
|
||||||
|
// The copyright notices in the Software and this entire
|
||||||
|
// statement, including the above license grant, this restriction
|
||||||
|
// and the following disclaimer, must be included in all copies of
|
||||||
|
// the Software, in whole or in part, and all derivative works of
|
||||||
|
// the Software, unless such copies or derivative works are solely
|
||||||
|
// in the form of machine-executable object code generated by a
|
||||||
|
// source language processor.
|
||||||
|
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||||
|
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND
|
||||||
|
// NON-INFRINGEMENT. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR
|
||||||
|
// ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE FOR ANY DAMAGES OR
|
||||||
|
// OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
|
||||||
|
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
||||||
|
// USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
|
||||||
|
const scalar r6 = 1.0/6.0;
|
||||||
|
const scalar r24 = 1.0/24.0;
|
||||||
|
const scalar r60 = 1.0/60.0;
|
||||||
|
const scalar r120 = 1.0/120.0;
|
||||||
|
|
||||||
|
// order: 1, x, y, z, x^2, y^2, z^2, xy, yz, zx
|
||||||
|
scalarField integrals(10, 0.0);
|
||||||
|
|
||||||
|
forAll(triFaces, i)
|
||||||
{
|
{
|
||||||
label faceI = cFaces[i];
|
const triFace& tri(triFaces[i]);
|
||||||
|
|
||||||
const face& f = faces[faceI];
|
// vertices of triangle i
|
||||||
|
vector v0 = pts[tri[0]];
|
||||||
|
vector v1 = pts[tri[1]];
|
||||||
|
vector v2 = pts[tri[2]];
|
||||||
|
|
||||||
fNorm[i] = f.normal(points);
|
// cross product of edges
|
||||||
fNorm[i] /= mag(fNorm[i]) + VSMALL;
|
vector eA = v1 - v0;
|
||||||
|
vector eB = v2 - v0;
|
||||||
|
vector n = eA ^ eB;
|
||||||
|
|
||||||
fW[i] = - (fNorm[i] & points[f[0]]);
|
// compute integral terms
|
||||||
|
scalar tmp0, tmp1, tmp2;
|
||||||
|
|
||||||
|
scalar f1x, f2x, f3x, g0x, g1x, g2x;
|
||||||
|
|
||||||
|
tmp0 = v0.x() + v1.x();
|
||||||
|
f1x = tmp0 + v2.x();
|
||||||
|
tmp1 = v0.x()*v0.x();
|
||||||
|
tmp2 = tmp1 + v1.x()*tmp0;
|
||||||
|
f2x = tmp2 + v2.x()*f1x;
|
||||||
|
f3x = v0.x()*tmp1 + v1.x()*tmp2 + v2.x()*f2x;
|
||||||
|
g0x = f2x + v0.x()*(f1x + v0.x());
|
||||||
|
g1x = f2x + v1.x()*(f1x + v1.x());
|
||||||
|
g2x = f2x + v2.x()*(f1x + v2.x());
|
||||||
|
|
||||||
|
scalar f1y, f2y, f3y, g0y, g1y, g2y;
|
||||||
|
|
||||||
|
tmp0 = v0.y() + v1.y();
|
||||||
|
f1y = tmp0 + v2.y();
|
||||||
|
tmp1 = v0.y()*v0.y();
|
||||||
|
tmp2 = tmp1 + v1.y()*tmp0;
|
||||||
|
f2y = tmp2 + v2.y()*f1y;
|
||||||
|
f3y = v0.y()*tmp1 + v1.y()*tmp2 + v2.y()*f2y;
|
||||||
|
g0y = f2y + v0.y()*(f1y + v0.y());
|
||||||
|
g1y = f2y + v1.y()*(f1y + v1.y());
|
||||||
|
g2y = f2y + v2.y()*(f1y + v2.y());
|
||||||
|
|
||||||
|
scalar f1z, f2z, f3z, g0z, g1z, g2z;
|
||||||
|
|
||||||
|
tmp0 = v0.z() + v1.z();
|
||||||
|
f1z = tmp0 + v2.z();
|
||||||
|
tmp1 = v0.z()*v0.z();
|
||||||
|
tmp2 = tmp1 + v1.z()*tmp0;
|
||||||
|
f2z = tmp2 + v2.z()*f1z;
|
||||||
|
f3z = v0.z()*tmp1 + v1.z()*tmp2 + v2.z()*f2z;
|
||||||
|
g0z = f2z + v0.z()*(f1z + v0.z());
|
||||||
|
g1z = f2z + v1.z()*(f1z + v1.z());
|
||||||
|
g2z = f2z + v2.z()*(f1z + v2.z());
|
||||||
|
|
||||||
|
// update integrals
|
||||||
|
integrals[0] += n.x()*f1x;
|
||||||
|
integrals[1] += n.x()*f2x;
|
||||||
|
integrals[2] += n.y()*f2y;
|
||||||
|
integrals[3] += n.z()*f2z;
|
||||||
|
integrals[4] += n.x()*f3x;
|
||||||
|
integrals[5] += n.y()*f3y;
|
||||||
|
integrals[6] += n.z()*f3z;
|
||||||
|
integrals[7] += n.x()*(v0.y()*g0x + v1.y()*g1x + v2.y()*g2x);
|
||||||
|
integrals[8] += n.y()*(v0.z()*g0y + v1.z()*g1y + v2.z()*g2y);
|
||||||
|
integrals[9] += n.z()*(v0.x()*g0z + v1.x()*g1z + v2.x()*g2z);
|
||||||
|
}
|
||||||
|
|
||||||
|
integrals[0] *= r6;
|
||||||
|
integrals[1] *= r24;
|
||||||
|
integrals[2] *= r24;
|
||||||
|
integrals[3] *= r24;
|
||||||
|
integrals[4] *= r60;
|
||||||
|
integrals[5] *= r60;
|
||||||
|
integrals[6] *= r60;
|
||||||
|
integrals[7] *= r120;
|
||||||
|
integrals[8] *= r120;
|
||||||
|
integrals[9] *= r120;
|
||||||
|
|
||||||
|
// mass
|
||||||
|
mass = integrals[0];
|
||||||
|
|
||||||
|
// center of mass
|
||||||
|
cM = vector(integrals[1], integrals[2], integrals[3])/mass;
|
||||||
|
|
||||||
|
// inertia relative to origin
|
||||||
|
J.xx() = integrals[5] + integrals[6];
|
||||||
|
J.xy() = -integrals[7];
|
||||||
|
J.xz() = -integrals[9];
|
||||||
|
J.yx() = J.xy();
|
||||||
|
J.yy() = integrals[4] + integrals[6];
|
||||||
|
J.yz() = -integrals[8];
|
||||||
|
J.zx() = J.xz();
|
||||||
|
J.zy() = J.yz();
|
||||||
|
J.zz() = integrals[4] + integrals[5];
|
||||||
|
|
||||||
|
// inertia relative to center of mass
|
||||||
|
J -= mass*((cM & cM)*I - cM*cM);
|
||||||
|
|
||||||
|
// Apply density
|
||||||
|
mass *= density;
|
||||||
|
J *= density;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
scalar T0;
|
void Foam::momentOfInertia::massPropertiesShell
|
||||||
vector T1, T2, TP;
|
|
||||||
|
|
||||||
compVolumeIntegrals
|
|
||||||
(
|
(
|
||||||
points,
|
const pointField& pts,
|
||||||
faces,
|
const triFaceList& triFaces,
|
||||||
cFaces,
|
scalar density,
|
||||||
fNorm,
|
scalar& mass,
|
||||||
fW,
|
vector& cM,
|
||||||
|
tensor& J
|
||||||
|
)
|
||||||
|
{
|
||||||
|
// Reset properties for accumulation
|
||||||
|
|
||||||
T0,
|
mass = 0.0;
|
||||||
T1,
|
cM = vector::zero;
|
||||||
T2,
|
J = tensor::zero;
|
||||||
TP
|
|
||||||
|
// Find centre of mass
|
||||||
|
|
||||||
|
forAll(triFaces, i)
|
||||||
|
{
|
||||||
|
const triFace& tri(triFaces[i]);
|
||||||
|
|
||||||
|
triPointRef t
|
||||||
|
(
|
||||||
|
pts[tri[0]],
|
||||||
|
pts[tri[1]],
|
||||||
|
pts[tri[2]]
|
||||||
);
|
);
|
||||||
|
|
||||||
const scalar density = 1.0; /* assume unit density */
|
scalar triMag = t.mag();
|
||||||
|
|
||||||
scalar mass = density * T0;
|
cM += triMag*t.centre();
|
||||||
|
|
||||||
/* compute center of mass */
|
mass += triMag;
|
||||||
r = T1 / T0;
|
|
||||||
|
|
||||||
/* compute inertia tensor */
|
|
||||||
J.xx() = density * (T2[1] + T2[2]);
|
|
||||||
J.yy() = density * (T2[2] + T2[0]);
|
|
||||||
J.zz() = density * (T2[0] + T2[1]);
|
|
||||||
J.xy() = J.yx() = - density * TP[0];
|
|
||||||
J.yz() = J.zy() = - density * TP[1];
|
|
||||||
J.zx() = J.xz() = - density * TP[2];
|
|
||||||
|
|
||||||
///* translate inertia tensor to center of mass */
|
|
||||||
//J[XX] -= mass * (r[1]*r[1] + r[2]*r[2]);
|
|
||||||
//J[YY] -= mass * (r[2]*r[2] + r[0]*r[0]);
|
|
||||||
//J[ZZ] -= mass * (r[0]*r[0] + r[1]*r[1]);
|
|
||||||
//J[XY] = J[YX] += mass * r[0] * r[1];
|
|
||||||
//J[YZ] = J[ZY] += mass * r[1] * r[2];
|
|
||||||
//J[ZX] = J[XZ] += mass * r[2] * r[0];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cM /= mass;
|
||||||
|
|
||||||
|
mass *= density;
|
||||||
|
|
||||||
|
// Find inertia around centre of mass
|
||||||
|
|
||||||
|
forAll(triFaces, i)
|
||||||
|
{
|
||||||
|
const triFace& tri(triFaces[i]);
|
||||||
|
|
||||||
|
J += triPointRef
|
||||||
|
(
|
||||||
|
pts[tri[0]],
|
||||||
|
pts[tri[1]],
|
||||||
|
pts[tri[2]]
|
||||||
|
).inertia(cM, density);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Foam::momentOfInertia::massPropertiesSolid
|
||||||
|
(
|
||||||
|
const triSurface& surf,
|
||||||
|
scalar density,
|
||||||
|
scalar& mass,
|
||||||
|
vector& cM,
|
||||||
|
tensor& J
|
||||||
|
)
|
||||||
|
{
|
||||||
|
triFaceList faces(surf.size());
|
||||||
|
|
||||||
|
forAll(surf, i)
|
||||||
|
{
|
||||||
|
faces[i] = triFace(surf[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
massPropertiesSolid(surf.points(), faces, density, mass, cM, J);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Foam::momentOfInertia::massPropertiesShell
|
||||||
|
(
|
||||||
|
const triSurface& surf,
|
||||||
|
scalar density,
|
||||||
|
scalar& mass,
|
||||||
|
vector& cM,
|
||||||
|
tensor& J
|
||||||
|
)
|
||||||
|
{
|
||||||
|
triFaceList faces(surf.size());
|
||||||
|
|
||||||
|
forAll(surf, i)
|
||||||
|
{
|
||||||
|
faces[i] = triFace(surf[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
massPropertiesShell(surf.points(), faces, density, mass, cM, J);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Foam::tensor Foam::momentOfInertia::applyParallelAxisTheorem
|
||||||
|
(
|
||||||
|
scalar mass,
|
||||||
|
const vector& cM,
|
||||||
|
const tensor& J,
|
||||||
|
const vector& refPt
|
||||||
|
)
|
||||||
|
{
|
||||||
|
// The displacement vector (refPt = cM) is the displacement of the
|
||||||
|
// new reference point from the centre of mass of the body that
|
||||||
|
// the inertia tensor applies to.
|
||||||
|
|
||||||
|
vector d = (refPt - cM);
|
||||||
|
|
||||||
|
return J + mass*((d & d)*I - d*d);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Foam::tmp<Foam::tensorField> Foam::momentOfInertia::meshInertia
|
||||||
|
(
|
||||||
|
const polyMesh& mesh
|
||||||
|
)
|
||||||
|
{
|
||||||
|
tmp<tensorField> tTf = tmp<tensorField>(new tensorField(mesh.nCells()));
|
||||||
|
|
||||||
|
tensorField& tf = tTf();
|
||||||
|
|
||||||
|
forAll(tf, cI)
|
||||||
|
{
|
||||||
|
tf[cI] = meshInertia(mesh, cI);
|
||||||
|
}
|
||||||
|
|
||||||
|
return tTf;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Foam::tensor Foam::momentOfInertia::meshInertia
|
||||||
|
(
|
||||||
|
const polyMesh& mesh,
|
||||||
|
label cellI
|
||||||
|
)
|
||||||
|
{
|
||||||
|
List<tetIndices> cellTets = polyMeshTetDecomposition::cellTetIndices
|
||||||
|
(
|
||||||
|
mesh,
|
||||||
|
cellI
|
||||||
|
);
|
||||||
|
|
||||||
|
triFaceList faces(cellTets.size());
|
||||||
|
|
||||||
|
forAll(cellTets, cTI)
|
||||||
|
{
|
||||||
|
faces[cTI] = cellTets[cTI].faceTriIs(mesh);
|
||||||
|
}
|
||||||
|
|
||||||
|
scalar m = 0.0;
|
||||||
|
vector cM = vector::zero;
|
||||||
|
tensor J = tensor::zero;
|
||||||
|
|
||||||
|
massPropertiesSolid(mesh.points(), faces, 1.0, m, cM, J);
|
||||||
|
|
||||||
|
return J;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// ************************************************************************* //
|
// ************************************************************************* //
|
||||||
|
|||||||
@ -25,6 +25,9 @@ Class
|
|||||||
momentOfInertia
|
momentOfInertia
|
||||||
|
|
||||||
Description
|
Description
|
||||||
|
Calculates the inertia tensor and principal axes and moments of a
|
||||||
|
polyhedra/cells/triSurfaces. Inertia can either be of the solid body or
|
||||||
|
of a thin shell.
|
||||||
|
|
||||||
SourceFiles
|
SourceFiles
|
||||||
momentOfInertia.H
|
momentOfInertia.H
|
||||||
@ -34,35 +37,87 @@ SourceFiles
|
|||||||
#ifndef momentOfInertia_H
|
#ifndef momentOfInertia_H
|
||||||
#define momentOfInertia_H
|
#define momentOfInertia_H
|
||||||
|
|
||||||
#include "tensor.H"
|
#include "tetPointRef.H"
|
||||||
#include "primitiveMesh.H"
|
#include "triFaceList.H"
|
||||||
|
#include "triSurface.H"
|
||||||
|
#include "polyMesh.H"
|
||||||
|
#include "polyMeshTetDecomposition.H"
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
namespace Foam
|
namespace Foam
|
||||||
{
|
{
|
||||||
|
|
||||||
////- Moment of inertia around cell centre for single cell.
|
/*---------------------------------------------------------------------------*\
|
||||||
//tensor momentOfInertia
|
Class momentOfInertia Declaration
|
||||||
//(
|
\*---------------------------------------------------------------------------*/
|
||||||
// const pointField&,
|
|
||||||
// const faceList&,
|
|
||||||
// const cell&,
|
|
||||||
// const point& cc
|
|
||||||
//);
|
|
||||||
|
|
||||||
// Calculate
|
class momentOfInertia
|
||||||
// - centre of mass
|
{
|
||||||
// - inertia tensor around (0,0,0)
|
|
||||||
void momentOfIntertia
|
public:
|
||||||
|
|
||||||
|
static void massPropertiesSolid
|
||||||
(
|
(
|
||||||
const pointField&,
|
const pointField& pts,
|
||||||
const faceList&,
|
const triFaceList& triFaces,
|
||||||
const cell&,
|
scalar density,
|
||||||
point& r,
|
scalar& mass,
|
||||||
tensor& Jorigin
|
vector& cM,
|
||||||
|
tensor& J
|
||||||
);
|
);
|
||||||
|
|
||||||
|
static void massPropertiesShell
|
||||||
|
(
|
||||||
|
const pointField& pts,
|
||||||
|
const triFaceList& triFaces,
|
||||||
|
scalar density,
|
||||||
|
scalar& mass,
|
||||||
|
vector& cM,
|
||||||
|
tensor& J
|
||||||
|
);
|
||||||
|
|
||||||
|
static void massPropertiesSolid
|
||||||
|
(
|
||||||
|
const triSurface& surf,
|
||||||
|
scalar density,
|
||||||
|
scalar& mass,
|
||||||
|
vector& cM,
|
||||||
|
tensor& J
|
||||||
|
);
|
||||||
|
|
||||||
|
static void massPropertiesShell
|
||||||
|
(
|
||||||
|
const triSurface& surf,
|
||||||
|
scalar density,
|
||||||
|
scalar& mass,
|
||||||
|
vector& cM,
|
||||||
|
tensor& J
|
||||||
|
);
|
||||||
|
|
||||||
|
static tensor applyParallelAxisTheorem
|
||||||
|
(
|
||||||
|
scalar mass,
|
||||||
|
const vector& cM,
|
||||||
|
const tensor& J,
|
||||||
|
const vector& refPt
|
||||||
|
);
|
||||||
|
|
||||||
|
// Calculate the inertia tensor for all cells in the mesh
|
||||||
|
static tmp<tensorField> meshInertia
|
||||||
|
(
|
||||||
|
const polyMesh& mesh
|
||||||
|
);
|
||||||
|
|
||||||
|
// Calculate the inertia tensor the given cell
|
||||||
|
static tensor meshInertia
|
||||||
|
(
|
||||||
|
const polyMesh& mesh,
|
||||||
|
label cellI
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
} // End namespace Foam
|
} // End namespace Foam
|
||||||
|
|||||||
Reference in New Issue
Block a user