/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2011-2016 OpenFOAM Foundation
Copyright (C) 2015-2024 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
OpenFOAM is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with OpenFOAM. If not, see .
Application
surfaceInertia
Group
grpSurfaceUtilities
Description
Calculates the inertia tensor, principal axes and moments of a
command line specified triSurface.
Inertia can either be of the solid body or of a thin shell.
\*---------------------------------------------------------------------------*/
#include "argList.H"
#include "ListOps.H"
#include "triSurface.H"
#include "OFstream.H"
#include "meshTools.H"
#include "Random.H"
#include "transform.H"
#include "IOmanip.H"
#include "Pair.H"
#include "momentOfInertia.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
using namespace Foam;
int main(int argc, char *argv[])
{
argList::addNote
(
"Calculates the inertia tensor and principal axes and moments"
" of the specified surface.\n"
"Inertia can either be of the solid body or of a thin shell."
);
argList::noParallel();
argList::addArgument("input", "The input surface file");
argList::addBoolOption
(
"shellProperties",
"Inertia of a thin shell"
);
argList::addOption
(
"density",
"scalar",
"Specify density, "
"kg/m3 for solid properties, kg/m2 for shell properties"
);
argList::addOption
(
"referencePoint",
"vector",
"Inertia relative to this point, not the centre of mass"
);
argList args(argc, argv);
const auto surfFileName = args.get(1);
const scalar density = args.getOrDefault("density", 1);
vector refPt = Zero;
bool calcAroundRefPt = args.readIfPresent("referencePoint", refPt);
const triSurface surf(surfFileName);
scalar m = 0.0;
vector cM = Zero;
tensor J = Zero;
if (args.found("shellProperties"))
{
momentOfInertia::massPropertiesShell(surf, density, m, cM, J);
}
else
{
momentOfInertia::massPropertiesSolid(surf, density, m, cM, J);
}
if (m < 0)
{
WarningInFunction
<< "Negative mass detected, the surface may be inside-out." << endl;
}
vector eVal = eigenValues(symm(J));
tensor eVec = eigenVectors(symm(J));
label pertI = 0;
Random rand(57373);
while ((magSqr(eVal) < VSMALL) && pertI < 10)
{
WarningInFunction
<< "No eigenValues found, shape may have symmetry, "
<< "perturbing inertia tensor diagonal" << endl;
J.xx() *= 1.0 + SMALL*rand.sample01();
J.yy() *= 1.0 + SMALL*rand.sample01();
J.zz() *= 1.0 + SMALL*rand.sample01();
eVal = eigenValues(symm(J));
eVec = eigenVectors(symm(J));
pertI++;
}
bool showTransform = true;
if
(
(mag(eVec.x() ^ eVec.y()) > (1.0 - SMALL))
&& (mag(eVec.y() ^ eVec.z()) > (1.0 - SMALL))
&& (mag(eVec.z() ^ eVec.x()) > (1.0 - SMALL))
)
{
// Make the eigenvectors a right handed orthogonal triplet
eVec = tensor
(
eVec.x(),
eVec.y(),
eVec.z() * sign((eVec.x() ^ eVec.y()) & eVec.z())
);
// Finding the most natural transformation. Using Lists
// rather than tensors to allow indexed permutation.
// Cartesian basis vectors - right handed orthogonal triplet
FixedList cartesian;
cartesian[0] = vector(1, 0, 0);
cartesian[1] = vector(0, 1, 0);
cartesian[2] = vector(0, 0, 1);
// Principal axis basis vectors - right handed orthogonal triplet
FixedList principal;
principal[0] = eVec.x();
principal[1] = eVec.y();
principal[2] = eVec.z();
// Matching axis indices, first: cartesian, second:principal
Pair