/*---------------------------------------------------------------------------*\ ========= | \\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / O peration | \\ / A nd | www.openfoam.com \\/ M anipulation | ------------------------------------------------------------------------------- Copyright (C) 2020-2021 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 polynomial-motion Description Polynomial representations of position/angle for fluid-structure interface check. Generates position and rotation angle of each node. Note The values may or may not correspond to experimental values. \*---------------------------------------------------------------------------*/ #include "argList.H" #include "Time.H" #include "Fstream.H" #include "polynomialFunction.H" #include "unitConversion.H" #include "foamVtkSeriesWriter.H" #include "lumpedPointTools.H" #include "lumpedPointState.H" #include "lumpedPointIOMovement.H" #include using namespace Foam; //- Position/angle generator based on polynomials class position_generator { // Private Data typedef FixedList xyzPoly; List points_; List angles_; // Private Member Functions //- Calculate position/rotation at given time lumpedPointState calc(scalar currTime) const { // Limit the time currTime = min(currTime, maxTime); const auto polyToValue = [=](const xyzPoly& p) -> vector { return vector ( p[0].value(currTime), p[1].value(currTime), p[2].value(currTime) ); }; pointField pts(points_.size()); std::transform ( points_.cbegin(), points_.cend(), pts.begin(), polyToValue ); vectorField ang(angles_.size()); std::transform ( angles_.cbegin(), angles_.cend(), ang.begin(), polyToValue ); return lumpedPointState{pts, ang}; } public: // Control Parameters // Upper time limit on polynomials scalar maxTime = GREAT; // Constructors //- Default construct position_generator() = default; //- Read construct from dictionary position_generator(const dictionary& dict) { dict.readIfPresent("maxTime", maxTime); dict.readEntry("points", points_); dict.readEntry("angles", angles_); if (angles_.size() != points_.size()) { Info<< "Resized angles to match number of points" << nl; angles_.resize(points_.size(), xyzPoly(polynomialFunction())); } } // Member Functions //- Calculate position/rotation at given time lumpedPointState state(const scalar currTime) const { return calc(currTime); } }; // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // int main(int argc, char *argv[]) { argList::addNote ( "Polynomial representations of position/angle for fluid-structure" " interface check." " Generates position and rotation angle of each node." ); argList::noBanner(); argList::noParallel(); // Time control argList::addOption ( "time", "value", "The time to use" ); argList::addOption ( "deltaT", "value", "The time increment for multiple time loops" ); argList::addOption ( "nTimes", "value", "The number of time loops" ); // Query, output argList::addBoolOption ( "query", "Report values only and exit" ); argList::addOption ( "output", "file", "write to file, with header" ); argList::addOption ( "scale", "factor", "Scaling factor for movement (default: 1)" ); argList::addOption ( "visual-length", "len", "Visualization length for planes (visualized as triangles)" ); // Run controls argList::addBoolOption ( "dry-run", "Test movement without a mesh" ); argList::addBoolOption ( "removeLock", "Remove lock-file on termination of slave" ); argList::addBoolOption ( "slave", "Invoke as a slave responder for testing" ); argList::addArgument ( "file", "Points/angles as triples of polynomials.\n" "Dictionary format" ); #include "setRootCase.H" // The position/angle generator position_generator gen; { // Input polynomials file IFstream is(args[1]); dictionary dict(is); gen = position_generator(dict); } // Control parameters const bool dryrun = args.found("dry-run"); const bool slave = args.found("slave"); const bool removeLock = args.found("removeLock"); const bool optQuery = args.found("query"); const fileName outputFile(args.getOrDefault("output", "")); const scalar relax = args.getOrDefault("scale", 1); args.readIfPresent("visual-length", lumpedPointState::visLength); // Time parameters scalar currTime = args.getOrDefault("time", 0); const scalar deltaT = args.getOrDefault("deltaT", 0.001); const label nTimes = args.getOrDefault