ENH: additional input/output parameters for lumped point motion (closes #804)

- input or output scaling of values to manage dissimilar unit systems
  in the structures model

- logging of communicated force, moments and updated positions.
  This allows tracking of the information exchange throughout the
  duration of the simulation and may assist in post-simulation diagnosis.
This commit is contained in:
Mark Olesen
2018-03-22 23:57:46 +01:00
parent 51d6008bbb
commit 73a525b7f5
8 changed files with 409 additions and 117 deletions

View File

@ -250,7 +250,7 @@ void Foam::lumpedPointDisplacementPointPatchVectorField::updateCoeffs()
if (Pstream::master()) if (Pstream::master())
{ {
movement().writeData(forces, moments); movement().writeData(forces, moments, &(db().time()));
// Signal external source to execute // Signal external source to execute
movement().coupler().useSlave(); movement().coupler().useSlave();

View File

@ -2,7 +2,7 @@
========= | ========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration | \\ / O peration |
\\ / A nd | Copyright (C) 2016-2017 OpenCFD Ltd. \\ / A nd | Copyright (C) 2016-2018 OpenCFD Ltd.
\\/ M anipulation | \\/ M anipulation |
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
License 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 const Foam::word
Foam::lumpedPointMovement::dictionaryName("lumpedPointMovement"); Foam::lumpedPointMovement::dictionaryName("lumpedPointMovement");
// * * * * * * * * * * * * * * * Local Functions * * * * * * * * * * * * * * //
namespace Foam 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 //! \cond fileScope
//- Write list content with size, bracket, content, bracket one-per-line. //- Write list content with size, bracket, content, bracket one-per-line.
// This makes for consistent for parsing, regardless of the list length. // This makes for consistent for parsing, regardless of the list length.
template <class T> 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 // Header string
os << header.c_str() << nl; os << header.c_str() << nl;
// Write size and start delimiter // Write size and start delimiter
os << lst.size() << nl os << len << nl << token::BEGIN_LIST << nl;
<< token::BEGIN_LIST << nl;
// Write contents // Write contents
forAll(lst, i) for (label i=0; i < len; ++i)
{ {
os << lst[i] << nl; os << list[i] << nl;
} }
// Write end delimiter // Write end delimiter
@ -165,8 +201,11 @@ Foam::lumpedPointMovement::lumpedPointMovement()
coupler_(), coupler_(),
inputName_("positions.in"), inputName_("positions.in"),
outputName_("forces.out"), outputName_("forces.out"),
logName_("movement.log"),
inputFormat_(lumpedPointState::inputFormatType::DICTIONARY), inputFormat_(lumpedPointState::inputFormatType::DICTIONARY),
outputFormat_(outputFormatType::DICTIONARY), outputFormat_(outputFormatType::DICTIONARY),
scaleInput_(-1.0),
scaleOutput_(-1.0),
state0_(), state0_(),
state_(), state_(),
thresholdPtr_(0), thresholdPtr_(0),
@ -198,6 +237,11 @@ Foam::lumpedPointMovement::lumpedPointMovement
autoCentre_(true), autoCentre_(true),
forcesDict_(), forcesDict_(),
coupler_(), coupler_(),
inputName_("positions.in"),
outputName_("forces.out"),
logName_("movement.log"),
scaleInput_(-1.0),
scaleOutput_(-1.0),
state0_(), state0_(),
state_(), state_(),
thresholdPtr_(0), thresholdPtr_(0),
@ -262,6 +306,7 @@ void Foam::lumpedPointMovement::readDict(const dictionary& dict)
commDict.lookup("inputName") >> inputName_; commDict.lookup("inputName") >> inputName_;
commDict.lookup("outputName") >> outputName_; commDict.lookup("outputName") >> outputName_;
commDict.readIfPresent("logName", logName_);
inputFormat_ = lumpedPointState::formatNames.lookup inputFormat_ = lumpedPointState::formatNames.lookup
( (
@ -274,6 +319,47 @@ void Foam::lumpedPointMovement::readDict(const dictionary& dict)
"outputFormat", "outputFormat",
commDict 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_) coupler().resolveFile(inputName_)
); );
state_.scalePoints(scaleInput_[scalingType::LENGTH]);
state_.relax(relax_, prev); state_.relax(relax_, prev);
return status; return status;
@ -646,45 +734,114 @@ bool Foam::lumpedPointMovement::readState()
bool Foam::lumpedPointMovement::writeData 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 ) const
{ {
if (!Pstream::master()) const bool writeMoments = (moments.size() == forces.size());
if (fmt == outputFormatType::PLAIN)
{ {
return false; os <<"########" << nl;
} if (timeinfo)
const fileName output(coupler().resolveFile(outputName_));
OFstream os(output); // ASCII
if (outputFormat_ == outputFormatType::PLAIN)
{
os <<"# output from OpenFOAM" << nl
<<"# N, points, forces" << nl
<< this->size() << nl;
const char* zeroVector = "0 0 0";
forAll(locations_, i)
{ {
const vector pos = locations_[i] * axis_; os <<"# ";
putTime(os, *timeinfo) << nl;
}
os <<"# size=" << this->size() << nl
<<"# columns (points) (forces)";
os << pos.x() << ' ' if (writeMoments)
<< pos.y() << ' ' {
<< pos.z() << ' '; os << " (moments)";
}
if (i < forces.size()) 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)
{ {
os << forces[i].x() << ' ' report = true;
<< forces[i].y() << ' '
<< forces[i].z();
} }
else else
{ {
os << zeroVector; scaleMoment = 1.0;
}
}
if (report)
{
os <<"# scaling points=" << scaleLength
<<" forces=" << scaleForce;
if (writeMoments)
{
os <<" moments=" << scaleMoment;
} }
os << nl; os << nl;
}
os <<"########" << nl;
forAll(locations_, i)
{
const vector pos = scaleLength * (locations_[i] * axis_);
putPlain(os, pos) << ' ';
if (i < forces.size())
{
const vector val(scaleForce * forces[i]);
putPlain(os, val);
}
else
{
putPlain(os, vector::zero);
}
if (writeMoments)
{
os << ' ';
if (i < moments.size())
{
const vector val(scaleMoment * moments[i]);
putPlain(os, val);
}
else
{
putPlain(os, vector::zero);
}
}
os << nl;
} }
} }
else else
@ -693,10 +850,21 @@ bool Foam::lumpedPointMovement::writeData
// - exclude the usual OpenFOAM 'FoamFile' header // - exclude the usual OpenFOAM 'FoamFile' header
// - ensure lists have consistent format // - 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, "points", (locations_*axis_)());
writeList(os, "forces", forces); writeList(os, "forces", forces);
if (writeMoments)
{
writeList(os, "moments", moments);
}
} }
return true; return true;
@ -706,7 +874,8 @@ bool Foam::lumpedPointMovement::writeData
bool Foam::lumpedPointMovement::writeData bool Foam::lumpedPointMovement::writeData
( (
const UList<vector>& forces, const UList<vector>& forces,
const UList<vector>& moments const UList<vector>& moments,
const Time* timeinfo
) const ) const
{ {
if (!Pstream::master()) if (!Pstream::master())
@ -714,60 +883,28 @@ bool Foam::lumpedPointMovement::writeData
return false; return false;
} }
const fileName output(coupler().resolveFile(outputName_)); // Regular output
OFstream os(output); // ASCII
if (outputFormat_ == outputFormatType::PLAIN)
{ {
os <<"# output from OpenFOAM" << nl const fileName output(coupler().resolveFile(outputName_));
<<"# N, points, forces, moments" << nl OFstream os(output, IOstream::ASCII);
<< this->size() << nl;
const char* zeroVector = "0 0 0"; writeData(os, forces, moments, outputFormat_, timeinfo);
forAll(locations_, i)
{
const vector pos = locations_[i] * axis_;
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;
}
} }
else
// Log output
{ {
// Make it easier for external programs to parse const fileName output(coupler().resolveFile(logName_));
// - exclude the usual OpenFOAM 'FoamFile' header
// - ensure lists have consistent format
os <<"// output from OpenFOAM" << nl << nl; OFstream os
(
output,
IOstream::ASCII,
IOstream::currentVersion,
IOstream::UNCOMPRESSED,
true // append mode
);
writeList(os, "points", (locations_*axis_)()); writeData(os, forces, moments, outputFormatType::PLAIN, timeinfo);
writeList(os, "forces", forces);
writeList(os, "moments", moments);
} }
return true; return true;

View File

@ -2,7 +2,7 @@
========= | ========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration | \\ / O peration |
\\ / A nd | Copyright (C) 2016-2017 OpenCFD Ltd. \\ / A nd | Copyright (C) 2016-2018 OpenCFD Ltd.
\\/ M anipulation | \\/ M anipulation |
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
License License
@ -60,8 +60,10 @@ SourceFiles
namespace Foam namespace Foam
{ {
// Forward declarations // Forward declarations
class polyMesh; class polyMesh;
class Time;
/*---------------------------------------------------------------------------*\ /*---------------------------------------------------------------------------*\
Class lumpedPointMovement Declaration Class lumpedPointMovement Declaration
@ -78,11 +80,22 @@ public:
DICTIONARY DICTIONARY
}; };
//- Output format types
enum scalingType
{
LENGTH = 0,
FORCE,
MOMENT
};
// Static data // Static data
//- Names for the output format types //- Names for the output format types
static const Enum<outputFormatType> formatNames; static const Enum<outputFormatType> formatNames;
//- Names for the scaling types
static const Enum<scalingType> scalingNames;
private: private:
@ -125,9 +138,15 @@ private:
//- File io //- File io
word inputName_; word inputName_;
word outputName_; word outputName_;
word logName_;
lumpedPointState::inputFormatType inputFormat_; lumpedPointState::inputFormatType inputFormat_;
outputFormatType outputFormat_; outputFormatType outputFormat_;
//- Optional scale factors for input/output files
FixedList<scalar, 1> scaleInput_;
FixedList<scalar, 3> scaleOutput_;
// Demand-driven private data // Demand-driven private data
@ -246,6 +265,9 @@ public:
//- The output (forces) file name //- The output (forces) file name
inline const word& outputName() const; inline const word& outputName() const;
//- The log file name
inline const word& logName() const;
//- The input (state) file format //- The input (state) file format
inline lumpedPointState::inputFormatType inputFormat() const; inline lumpedPointState::inputFormatType inputFormat() const;
@ -324,21 +346,24 @@ public:
//- Write axis, locations, division as a dictionary //- Write axis, locations, division as a dictionary
void writeDict(Ostream& os) const; void writeDict(Ostream& os) const;
//- Write points, forces, moments. Only call from the master process
//- Write points, forces
bool writeData 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; ) const;
//- Write points, forces, moments //- Write points, forces, moments
bool writeData bool writeData
( (
const UList<vector>& forces, const UList<vector>& forces,
const UList<vector>& moments const UList<vector>& moments = List<vector>(),
const Time* timeinfo = nullptr
) const; ) const;
//- Read state from file, applying relaxation as requested //- Read state from file, applying relaxation as requested
bool readState(); bool readState();

View File

@ -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;
}
}
// ************************************************************************* //

View File

@ -2,7 +2,7 @@
========= | ========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration | \\ / O peration |
\\ / A nd | Copyright (C) 2017 OpenCFD Ltd. \\ / A nd | Copyright (C) 2017-2018 OpenCFD Ltd.
\\/ M anipulation | \\/ M anipulation |
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
License 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 inline Foam::lumpedPointState::inputFormatType
Foam::lumpedPointMovement::inputFormat() const Foam::lumpedPointMovement::inputFormat() const
{ {

View File

@ -2,7 +2,7 @@
========= | ========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration | \\ / O peration |
\\ / A nd | Copyright (C) 2016-2017 OpenCFD Ltd. \\ / A nd | Copyright (C) 2016-2018 OpenCFD Ltd.
\\/ M anipulation | \\/ M anipulation |
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
License License
@ -94,8 +94,8 @@ void Foam::lumpedPointState::readDict(const dictionary& dict)
Foam::lumpedPointState::lumpedPointState() Foam::lumpedPointState::lumpedPointState()
: :
points_(0), points_(),
angles_(0), angles_(),
degrees_(false), degrees_(false),
rotationPtr_(nullptr) rotationPtr_(nullptr)
{} {}
@ -110,10 +110,7 @@ Foam::lumpedPointState::lumpedPointState(const lumpedPointState& rhs)
{} {}
Foam::lumpedPointState::lumpedPointState Foam::lumpedPointState::lumpedPointState(const pointField& pts)
(
const pointField& pts
)
: :
points_(pts), points_(pts),
angles_(points_.size(), Zero), angles_(points_.size(), Zero),
@ -122,10 +119,7 @@ Foam::lumpedPointState::lumpedPointState
{} {}
Foam::lumpedPointState::lumpedPointState Foam::lumpedPointState::lumpedPointState(tmp<pointField>& pts)
(
tmp<pointField>& pts
)
: :
points_(pts), points_(pts),
angles_(points_.size(), Zero), angles_(points_.size(), Zero),
@ -134,13 +128,10 @@ Foam::lumpedPointState::lumpedPointState
{} {}
Foam::lumpedPointState::lumpedPointState Foam::lumpedPointState::lumpedPointState(const dictionary& dict)
(
const dictionary& dict
)
: :
points_(0), points_(),
angles_(0), angles_(),
degrees_(false), degrees_(false),
rotationPtr_(nullptr) 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 void Foam::lumpedPointState::relax
( (
const scalar alpha, const scalar alpha,
@ -273,19 +273,17 @@ void Foam::lumpedPointState::writePlain(Ostream& os) const
{ {
const vector& pt = points_[i]; const vector& pt = points_[i];
os << pt.x() << ' ' os << pt.x() << ' ' << pt.y() << ' ' << pt.z();
<< pt.y() << ' '
<< pt.z() << ' ';
if (i < angles_.size()) if (i < angles_.size())
{ {
os << angles_[i].x() << ' ' os << ' ' << angles_[i].x()
<< angles_[i].y() << ' ' << ' ' << angles_[i].y()
<< angles_[i].z() << '\n'; << ' ' << angles_[i].z() << '\n';
} }
else else
{ {
os << "0 0 0\n"; os << " 0 0 0\n";
} }
} }
} }

View File

@ -2,7 +2,7 @@
========= | ========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration | \\ / O peration |
\\ / A nd | Copyright (C) 2016-2017 OpenCFD Ltd. \\ / A nd | Copyright (C) 2016-2018 OpenCFD Ltd.
\\/ M anipulation | \\/ M anipulation |
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
License License
@ -143,13 +143,16 @@ public:
//- The local-to-global transformation for each point //- The local-to-global transformation for each point
inline const tensorField& rotations() const; inline const tensorField& rotations() const;
//- Scale points by given factor.
// Zero and negative values are ignored.
void scalePoints(const scalar scaleFactor);
//- Relax the state //- Relax the state
// alpha = 1 : no relaxation // alpha = 1 : no relaxation
// alpha < 1 : relaxation // alpha < 1 : relaxation
// alpha = 0 : do nothing // alpha = 0 : do nothing
void relax(const scalar alpha, const lumpedPointState& prev); void relax(const scalar alpha, const lumpedPointState& prev);
//- Read input as dictionary content //- Read input as dictionary content
bool readData(Istream& is); bool readData(Istream& is);

View File

@ -66,10 +66,33 @@ communication
// Output file of forces, written by OpenFOAM // Output file of forces, written by OpenFOAM
outputName forces.out; outputName forces.out;
// Log of points/forces/moments during the simulation
logName movement.log;
inputFormat dictionary; inputFormat dictionary;
outputFormat dictionary; outputFormat dictionary;
debugTable "<case>/output.txt"; 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;
}
} }
// ************************************************************************* // // ************************************************************************* //