/*---------------------------------------------------------------------------*\ ========= | \\ / 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