diff --git a/src/lumpedPointMotion/lumpedPointDisplacementPointPatchVectorField.C b/src/lumpedPointMotion/lumpedPointDisplacementPointPatchVectorField.C index 3368d6f59f58e35cd69833be51921811d313e343..1ac55bd8b86a539de5eead5c201ec3e06e56a50f 100644 --- a/src/lumpedPointMotion/lumpedPointDisplacementPointPatchVectorField.C +++ b/src/lumpedPointMotion/lumpedPointDisplacementPointPatchVectorField.C @@ -250,7 +250,7 @@ void Foam::lumpedPointDisplacementPointPatchVectorField::updateCoeffs() if (Pstream::master()) { - movement().writeData(forces, moments); + movement().writeData(forces, moments, &(db().time())); // Signal external source to execute movement().coupler().useSlave(); diff --git a/src/lumpedPointMotion/lumpedPointMovement.C b/src/lumpedPointMotion/lumpedPointMovement.C index 4e74f34a2f733893753895fefa18e1347aaf0160..00c34c7209875ecb7b6c13c032389af6539f644a 100644 --- a/src/lumpedPointMotion/lumpedPointMovement.C +++ b/src/lumpedPointMotion/lumpedPointMovement.C @@ -2,7 +2,7 @@ ========= | \\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / O peration | - \\ / A nd | Copyright (C) 2016-2017 OpenCFD Ltd. + \\ / A nd | Copyright (C) 2016-2018 OpenCFD Ltd. \\/ M anipulation | ------------------------------------------------------------------------------- License @@ -48,29 +48,65 @@ Foam::lumpedPointMovement::formatNames }; +const Foam::Enum +< + Foam::lumpedPointMovement::scalingType +> +Foam::lumpedPointMovement::scalingNames +{ + { scalingType::LENGTH, "plain" }, + { scalingType::FORCE, "force" }, + { scalingType::MOMENT, "moment" } +}; + + const Foam::word Foam::lumpedPointMovement::dictionaryName("lumpedPointMovement"); +// * * * * * * * * * * * * * * * Local Functions * * * * * * * * * * * * * * // + namespace Foam { + +//! \cond fileScope +//- Space-separated vector value (ASCII) +static inline Ostream& putPlain(Ostream& os, const vector& val) +{ + os << val.x() << ' ' << val.y() << ' ' << val.z(); + return os; +} + + +//! \cond fileScope +//- Space-separated vector value (ASCII) +static inline Ostream& putTime(Ostream& os, const Time& t) +{ + os <<"Time index=" << t.timeIndex() + << " value=" << t.timeOutputValue(); + + return os; +} + + //! \cond fileScope //- Write list content with size, bracket, content, bracket one-per-line. // This makes for consistent for parsing, regardless of the list length. template <class T> -static void writeList(Ostream& os, const string& header, const UList<T>& lst) +static void writeList(Ostream& os, const string& header, const UList<T>& list) { + const label len = list.size(); + // Header string os << header.c_str() << nl; // Write size and start delimiter - os << lst.size() << nl - << token::BEGIN_LIST << nl; + os << len << nl << token::BEGIN_LIST << nl; // Write contents - forAll(lst, i) + for (label i=0; i < len; ++i) { - os << lst[i] << nl; + os << list[i] << nl; } // Write end delimiter @@ -165,8 +201,11 @@ Foam::lumpedPointMovement::lumpedPointMovement() coupler_(), inputName_("positions.in"), outputName_("forces.out"), + logName_("movement.log"), inputFormat_(lumpedPointState::inputFormatType::DICTIONARY), outputFormat_(outputFormatType::DICTIONARY), + scaleInput_(-1.0), + scaleOutput_(-1.0), state0_(), state_(), thresholdPtr_(0), @@ -198,6 +237,11 @@ Foam::lumpedPointMovement::lumpedPointMovement autoCentre_(true), forcesDict_(), coupler_(), + inputName_("positions.in"), + outputName_("forces.out"), + logName_("movement.log"), + scaleInput_(-1.0), + scaleOutput_(-1.0), state0_(), state_(), thresholdPtr_(0), @@ -262,6 +306,7 @@ void Foam::lumpedPointMovement::readDict(const dictionary& dict) commDict.lookup("inputName") >> inputName_; commDict.lookup("outputName") >> outputName_; + commDict.readIfPresent("logName", logName_); inputFormat_ = lumpedPointState::formatNames.lookup ( @@ -274,6 +319,47 @@ void Foam::lumpedPointMovement::readDict(const dictionary& dict) "outputFormat", commDict ); + + scaleInput_ = -1; + scaleOutput_ = -1; + + const dictionary* scaleDict = nullptr; + + if ((scaleDict = commDict.subDictPtr("scaleInput"))) + { + for (int i=0; i < scaleInput_.size(); ++i) + { + const word& key = scalingNames[scalingType(i)]; + + if + ( + scaleDict->readIfPresent(key, scaleInput_[i]) + && scaleInput_[i] > 0 + ) + { + Info<<"Using input " << key << " multiplier: " + << scaleInput_[i] << nl; + } + } + } + + if ((scaleDict = commDict.subDictPtr("scaleOutput"))) + { + for (int i=0; i < scaleOutput_.size(); ++i) + { + const word& key = scalingNames[scalingType(i)]; + + if + ( + scaleDict->readIfPresent(key, scaleOutput_[i]) + && scaleOutput_[i] > 0 + ) + { + Info<<"Using output " << key << " multiplier: " + << scaleOutput_[i] << nl; + } + } + } } @@ -638,6 +724,8 @@ bool Foam::lumpedPointMovement::readState() coupler().resolveFile(inputName_) ); + state_.scalePoints(scaleInput_[scalingType::LENGTH]); + state_.relax(relax_, prev); return status; @@ -646,45 +734,114 @@ bool Foam::lumpedPointMovement::readState() bool Foam::lumpedPointMovement::writeData ( - const UList<vector>& forces + Ostream& os, + const UList<vector>& forces, + const UList<vector>& moments, + const outputFormatType fmt, + const Time* timeinfo ) const { - if (!Pstream::master()) + const bool writeMoments = (moments.size() == forces.size()); + + if (fmt == outputFormatType::PLAIN) { - return false; - } + os <<"########" << nl; + if (timeinfo) + { + os <<"# "; + putTime(os, *timeinfo) << nl; + } + os <<"# size=" << this->size() << nl + <<"# columns (points) (forces)"; - const fileName output(coupler().resolveFile(outputName_)); - OFstream os(output); // ASCII + if (writeMoments) + { + os << " (moments)"; + } - if (outputFormat_ == outputFormatType::PLAIN) - { - os <<"# output from OpenFOAM" << nl - <<"# N, points, forces" << nl - << this->size() << nl; + os << nl; + + bool report = false; + scalar scaleLength = scaleOutput_[scalingType::LENGTH]; + scalar scaleForce = scaleOutput_[scalingType::FORCE]; + scalar scaleMoment = scaleOutput_[scalingType::MOMENT]; + + if (scaleLength > 0) + { + report = true; + } + else + { + scaleLength = 1.0; + } + + if (scaleForce > 0) + { + report = true; + } + else + { + scaleForce = 1.0; + } + + if (writeMoments) + { + if (scaleMoment > 0) + { + report = true; + } + else + { + scaleMoment = 1.0; + } + } + + if (report) + { + os <<"# scaling points=" << scaleLength + <<" forces=" << scaleForce; + + if (writeMoments) + { + os <<" moments=" << scaleMoment; + } + + os << nl; + } - const char* zeroVector = "0 0 0"; + os <<"########" << nl; forAll(locations_, i) { - const vector pos = locations_[i] * axis_; + const vector pos = scaleLength * (locations_[i] * axis_); - os << pos.x() << ' ' - << pos.y() << ' ' - << pos.z() << ' '; + putPlain(os, pos) << ' '; if (i < forces.size()) { - os << forces[i].x() << ' ' - << forces[i].y() << ' ' - << forces[i].z(); + const vector val(scaleForce * forces[i]); + putPlain(os, val); } else { - os << zeroVector; + putPlain(os, vector::zero); } - os << nl; + if (writeMoments) + { + os << ' '; + if (i < moments.size()) + { + const vector val(scaleMoment * moments[i]); + putPlain(os, val); + } + else + { + putPlain(os, vector::zero); + } + } + + os << nl; } } else @@ -693,10 +850,21 @@ bool Foam::lumpedPointMovement::writeData // - exclude the usual OpenFOAM 'FoamFile' header // - ensure lists have consistent format - os <<"// output from OpenFOAM" << nl << nl; + os <<"////////" << nl; + if (timeinfo) + { + os <<"// "; + putTime(os, *timeinfo) << nl; + } + os << nl; writeList(os, "points", (locations_*axis_)()); writeList(os, "forces", forces); + + if (writeMoments) + { + writeList(os, "moments", moments); + } } return true; @@ -706,7 +874,8 @@ bool Foam::lumpedPointMovement::writeData bool Foam::lumpedPointMovement::writeData ( const UList<vector>& forces, - const UList<vector>& moments + const UList<vector>& moments, + const Time* timeinfo ) const { if (!Pstream::master()) @@ -714,60 +883,28 @@ bool Foam::lumpedPointMovement::writeData return false; } - const fileName output(coupler().resolveFile(outputName_)); - OFstream os(output); // ASCII - - if (outputFormat_ == outputFormatType::PLAIN) + // Regular output { - os <<"# output from OpenFOAM" << nl - <<"# N, points, forces, moments" << nl - << this->size() << nl; - - const char* zeroVector = "0 0 0"; - - forAll(locations_, i) - { - const vector pos = locations_[i] * axis_; + const fileName output(coupler().resolveFile(outputName_)); + OFstream os(output, IOstream::ASCII); - os << pos.x() << ' ' - << pos.y() << ' ' - << pos.z() << ' '; - - if (i < forces.size()) - { - os << forces[i].x() << ' ' - << forces[i].y() << ' ' - << forces[i].z() << ' '; - } - else - { - os << zeroVector << ' '; - } - - if (i < moments.size()) - { - os << moments[i].x() << ' ' - << moments[i].y() << ' ' - << moments[i].z(); - } - else - { - os << zeroVector; - } - os << nl; - } + writeData(os, forces, moments, outputFormat_, timeinfo); } - else + + // Log output { - // Make it easier for external programs to parse - // - exclude the usual OpenFOAM 'FoamFile' header - // - ensure lists have consistent format + const fileName output(coupler().resolveFile(logName_)); - os <<"// output from OpenFOAM" << nl << nl; + OFstream os + ( + output, + IOstream::ASCII, + IOstream::currentVersion, + IOstream::UNCOMPRESSED, + true // append mode + ); - writeList(os, "points", (locations_*axis_)()); - writeList(os, "forces", forces); - writeList(os, "moments", moments); + writeData(os, forces, moments, outputFormatType::PLAIN, timeinfo); } return true; diff --git a/src/lumpedPointMotion/lumpedPointMovement.H b/src/lumpedPointMotion/lumpedPointMovement.H index dc0f1fb189676a10bb4a46925c13634b0776e35d..7587ec8378cf8d2e743b25e4d6c4f3a98bc0b070 100644 --- a/src/lumpedPointMotion/lumpedPointMovement.H +++ b/src/lumpedPointMotion/lumpedPointMovement.H @@ -2,7 +2,7 @@ ========= | \\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / O peration | - \\ / A nd | Copyright (C) 2016-2017 OpenCFD Ltd. + \\ / A nd | Copyright (C) 2016-2018 OpenCFD Ltd. \\/ M anipulation | ------------------------------------------------------------------------------- License @@ -60,8 +60,10 @@ SourceFiles namespace Foam { + // Forward declarations class polyMesh; +class Time; /*---------------------------------------------------------------------------*\ Class lumpedPointMovement Declaration @@ -78,11 +80,22 @@ public: DICTIONARY }; + //- Output format types + enum scalingType + { + LENGTH = 0, + FORCE, + MOMENT + }; + // Static data //- Names for the output format types static const Enum<outputFormatType> formatNames; + //- Names for the scaling types + static const Enum<scalingType> scalingNames; + private: @@ -125,9 +138,15 @@ private: //- File io word inputName_; word outputName_; + word logName_; + lumpedPointState::inputFormatType inputFormat_; outputFormatType outputFormat_; + //- Optional scale factors for input/output files + FixedList<scalar, 1> scaleInput_; + FixedList<scalar, 3> scaleOutput_; + // Demand-driven private data @@ -246,6 +265,9 @@ public: //- The output (forces) file name inline const word& outputName() const; + //- The log file name + inline const word& logName() const; + //- The input (state) file format inline lumpedPointState::inputFormatType inputFormat() const; @@ -324,21 +346,24 @@ public: //- Write axis, locations, division as a dictionary void writeDict(Ostream& os) const; - - //- Write points, forces + //- Write points, forces, moments. Only call from the master process bool writeData ( - const UList<vector>& forces + Ostream& os, + const UList<vector>& forces, + const UList<vector>& moments, + const outputFormatType fmt = outputFormatType::PLAIN, + const Time* timeinfo = nullptr ) const; //- Write points, forces, moments bool writeData ( const UList<vector>& forces, - const UList<vector>& moments + const UList<vector>& moments = List<vector>(), + const Time* timeinfo = nullptr ) const; - //- Read state from file, applying relaxation as requested bool readState(); diff --git a/src/lumpedPointMotion/lumpedPointMovement.dict b/src/lumpedPointMotion/lumpedPointMovement.dict new file mode 100644 index 0000000000000000000000000000000000000000..5223b7d253a14e5ed2dc7ec3460cee9fb27d1a61 --- /dev/null +++ b/src/lumpedPointMotion/lumpedPointMovement.dict @@ -0,0 +1,100 @@ +/*--------------------------------*- C++ -*----------------------------------*\ +| ========= | | +| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox | +| \\ / O peration | Version: plus | +| \\ / A nd | Web: www.OpenFOAM.com | +| \\/ M anipulation | | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + version 2.0; + format ascii; + class dictionary; + location "system"; + object lumpedPointMovement; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +// Reference axis for the locations +axis (0 0 1); + +// Locations of the lumped points +locations 11(0 0.05 0.1 0.15 0.2 0.25 0.3 0.35 0.4 0.45 0.5); + +// Division for pressure forces (0-1) +division 0.5; + +//- If present, the offset of patch points compared to the locations +// Otherwise determined from the bounding box +// centre (0 0 0); + +//- The interpolation scheme +interpolationScheme linear; + +//- Relaxation/scaling factor when updating positions +relax 1.0; + + +forces +{ + //- The pressure name (default: p) + p p; + + //- Reference pressure [Pa] (default: 0) + pRef 0; + + //- Reference density for incompressible calculations (default: 1) + rhoRef 1; +} + + +communication +{ + commsDir "comms"; + + log on; + + waitInterval 1; + + timeOut 100; + + initByExternal false; + + // Input file of positions/rotation, written by external application + inputName positions.in; + + // Output file of forces, written by OpenFOAM + outputName forces.out; + + // Log of points/forces/moments during the simulation + logName movement.log; + + inputFormat dictionary; + outputFormat dictionary; + + debugTable "$FOAM_CASE/output.txt"; + + + // Scaling applied to values read from 'inputName' + scaleInput + { + //- Length multiplier (to metres). Eg 0.001 for [mm] -> [m] + length 1; + } + + // Scaling applied to values written to 'outputName' + scaleOutput + { + //- Length multiplier (from metres). Eg 1000 for [m] -> [mm] + length 1; + + //- Force units multiplier (from Pa) + force 1; + + //- Moment units multiplier (from N.m) + moment 1; + } +} + + +// ************************************************************************* // diff --git a/src/lumpedPointMotion/lumpedPointMovementI.H b/src/lumpedPointMotion/lumpedPointMovementI.H index 43bcdb30947a63cbcb501d6110debecb811ff056..ef73c4ddea837b7522710dee5671faba906103a5 100644 --- a/src/lumpedPointMotion/lumpedPointMovementI.H +++ b/src/lumpedPointMotion/lumpedPointMovementI.H @@ -2,7 +2,7 @@ ========= | \\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / O peration | - \\ / A nd | Copyright (C) 2017 OpenCFD Ltd. + \\ / A nd | Copyright (C) 2017-2018 OpenCFD Ltd. \\/ M anipulation | ------------------------------------------------------------------------------- License @@ -133,6 +133,12 @@ inline const Foam::word& Foam::lumpedPointMovement::outputName() const } +inline const Foam::word& Foam::lumpedPointMovement::logName() const +{ + return logName_; +} + + inline Foam::lumpedPointState::inputFormatType Foam::lumpedPointMovement::inputFormat() const { diff --git a/src/lumpedPointMotion/lumpedPointState.C b/src/lumpedPointMotion/lumpedPointState.C index a84e963fb66ae959cdd619595ee2b011fe2b19be..8bddc73d8e71cac798340691028cb6c0d6e4df4d 100644 --- a/src/lumpedPointMotion/lumpedPointState.C +++ b/src/lumpedPointMotion/lumpedPointState.C @@ -2,7 +2,7 @@ ========= | \\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / O peration | - \\ / A nd | Copyright (C) 2016-2017 OpenCFD Ltd. + \\ / A nd | Copyright (C) 2016-2018 OpenCFD Ltd. \\/ M anipulation | ------------------------------------------------------------------------------- License @@ -94,8 +94,8 @@ void Foam::lumpedPointState::readDict(const dictionary& dict) Foam::lumpedPointState::lumpedPointState() : - points_(0), - angles_(0), + points_(), + angles_(), degrees_(false), rotationPtr_(nullptr) {} @@ -110,10 +110,7 @@ Foam::lumpedPointState::lumpedPointState(const lumpedPointState& rhs) {} -Foam::lumpedPointState::lumpedPointState -( - const pointField& pts -) +Foam::lumpedPointState::lumpedPointState(const pointField& pts) : points_(pts), angles_(points_.size(), Zero), @@ -122,10 +119,7 @@ Foam::lumpedPointState::lumpedPointState {} -Foam::lumpedPointState::lumpedPointState -( - tmp<pointField>& pts -) +Foam::lumpedPointState::lumpedPointState(tmp<pointField>& pts) : points_(pts), angles_(points_.size(), Zero), @@ -134,13 +128,10 @@ Foam::lumpedPointState::lumpedPointState {} -Foam::lumpedPointState::lumpedPointState -( - const dictionary& dict -) +Foam::lumpedPointState::lumpedPointState(const dictionary& dict) : - points_(0), - angles_(0), + points_(), + angles_(), degrees_(false), rotationPtr_(nullptr) { @@ -168,6 +159,15 @@ void Foam::lumpedPointState::operator=(const lumpedPointState& rhs) } +void Foam::lumpedPointState::scalePoints(const scalar scaleFactor) +{ + if (scaleFactor > 0) + { + points_ *= scaleFactor; + } +} + + void Foam::lumpedPointState::relax ( const scalar alpha, @@ -273,19 +273,17 @@ void Foam::lumpedPointState::writePlain(Ostream& os) const { const vector& pt = points_[i]; - os << pt.x() << ' ' - << pt.y() << ' ' - << pt.z() << ' '; + os << pt.x() << ' ' << pt.y() << ' ' << pt.z(); if (i < angles_.size()) { - os << angles_[i].x() << ' ' - << angles_[i].y() << ' ' - << angles_[i].z() << '\n'; + os << ' ' << angles_[i].x() + << ' ' << angles_[i].y() + << ' ' << angles_[i].z() << '\n'; } else { - os << "0 0 0\n"; + os << " 0 0 0\n"; } } } diff --git a/src/lumpedPointMotion/lumpedPointState.H b/src/lumpedPointMotion/lumpedPointState.H index 0d32fa892770ab638f3105c0f0906ebdcd52f818..2d69c8c1b2772df07d900c150d05954f6ae86210 100644 --- a/src/lumpedPointMotion/lumpedPointState.H +++ b/src/lumpedPointMotion/lumpedPointState.H @@ -2,7 +2,7 @@ ========= | \\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / O peration | - \\ / A nd | Copyright (C) 2016-2017 OpenCFD Ltd. + \\ / A nd | Copyright (C) 2016-2018 OpenCFD Ltd. \\/ M anipulation | ------------------------------------------------------------------------------- License @@ -143,13 +143,16 @@ public: //- The local-to-global transformation for each point inline const tensorField& rotations() const; + //- Scale points by given factor. + // Zero and negative values are ignored. + void scalePoints(const scalar scaleFactor); + //- Relax the state // alpha = 1 : no relaxation // alpha < 1 : relaxation // alpha = 0 : do nothing void relax(const scalar alpha, const lumpedPointState& prev); - //- Read input as dictionary content bool readData(Istream& is); diff --git a/tutorials/incompressible/lumpedPointMotion/building/steady/system/lumpedPointMovement b/tutorials/incompressible/lumpedPointMotion/building/steady/system/lumpedPointMovement index f1b33cbbfdfd3ccde4ae5f719bed07ec7e08b20b..5c65da66dabc095f09159cc0039ecb57c20e4bce 100644 --- a/tutorials/incompressible/lumpedPointMotion/building/steady/system/lumpedPointMovement +++ b/tutorials/incompressible/lumpedPointMotion/building/steady/system/lumpedPointMovement @@ -66,10 +66,33 @@ communication // Output file of forces, written by OpenFOAM outputName forces.out; + // Log of points/forces/moments during the simulation + logName movement.log; + inputFormat dictionary; outputFormat dictionary; debugTable "<case>/output.txt"; + + // Scaling applied to values read from 'inputName' + scaleInput + { + //- Length multiplier (to metres). Eg 0.001 for [mm] -> [m] + length 1; + } + + // Scaling applied to values written to 'outputName' + scaleOutput + { + //- Length multiplier (from metres). Eg 1000 for [m] -> [mm] + length 1; + + //- Force units multiplier (from Pa) + force 1; + + //- Moment units multiplier (from N.m) + moment 1; + } } // ************************************************************************* //