60 { outputFormatType::PLAIN,
"plain" },
61 { outputFormatType::DICTIONARY,
"dictionary" },
71 { scalingType::LENGTH,
"length" },
72 { scalingType::FORCE,
"force" },
73 { scalingType::MOMENT,
"moment" },
85 static inline Ostream& putPlain(Ostream&
os,
const vector& v)
87 return os << v.x() <<
' ' << v.y() <<
' ' << v.z();
95 static void writeList(Ostream&
os,
const string& header,
const UList<T>& list)
97 const label len = list.size();
100 os << header.c_str() <<
nl;
106 for (label i=0; i < len; ++i)
133 inputName_(
"positions.in"),
134 outputName_(
"forces.out"),
135 logName_(
"movement.log"),
161 inputName_(
"positions.in"),
162 outputName_(
"forces.out"),
163 logName_(
"movement.log"),
177 return (
timeIndex >= lastTrigger_ + calcFrequency_);
193 auto&
points0 = tpoints0.ref();
198 originalIds_.
clear();
199 controllers_.clear();
200 patchControls_.clear();
211 <<
"Incorrect number of pointLabels. Had " 212 << originalIds_.size() <<
" for " <<
points0.
size() <<
" points" 221 for (
const label
id : originalIds_)
223 if (!pointIdMap.
insert(
id, pointi))
231 if (!duplicates.
empty())
234 <<
"Found duplicate point ids " 248 (*iter)->remapPointLabels(
points0.
size(), pointIdMap);
256 controllers_.clear();
265 coupler_.readDict(commDict);
267 calcFrequency_ = commDict.
getOrDefault<label>(
"calcFrequency", 1);
271 commDict.
readEntry(
"inputName", inputName_);
272 commDict.
readEntry(
"outputName", outputName_);
276 outputFormat_ = formatNames.get(
"outputFormat", commDict);
283 if ((scaleDict = commDict.
findDict(
"scaleInput")) !=
nullptr)
285 for (
int i=0; i < scaleInput_.size(); ++i)
292 && scaleInput_[i] > 0
295 Info<<
"Using input " <<
key <<
" multiplier: " 296 << scaleInput_[i] <<
nl;
301 if ((scaleDict = commDict.
findDict(
"scaleOutput")) !=
nullptr)
303 for (
int i=0; i < scaleOutput_.size(); ++i)
310 && scaleOutput_[i] > 0
313 Info<<
"Using output " <<
key <<
" multiplier: " 314 << scaleOutput_[i] <<
nl;
326 quaternion::eulerOrder::ZXZ
331 state0_.
scalePoints(scaleInput_[scalingType::LENGTH]);
342 return hasPatchControl(
pp.index());
351 return hasInterpolator(fpatch.
index());
360 const auto ctrlIter = patchControls_.cfind(
pp.index());
362 if (!ctrlIter.good())
365 <<
"No controllers for patch " <<
pp.name()
369 const patchControl& ctrl = *ctrlIter;
371 for (
const word& ctrlName : ctrl.names_)
373 const auto iter = controllers_.cfind(ctrlName);
378 <<
"No controller: " << ctrlName <<
nl 379 <<
" For patch " <<
pp.name()
394 const pointField& lumpedCentres0 = state0().points();
396 const label patchIndex =
pp.index();
401 patchControl& ctrl = patchControls_(patchIndex);
402 ctrl.names_ = ctrlNames;
407 checkPatchControl(
pp);
409 const faceList& faces =
pp.boundaryMesh().mesh().faces();
414 for (
const word& ctrlName : ctrl.names_)
416 const auto iter = controllers_.
cfind(ctrlName);
421 <<
"No controller: " << ctrlName <<
nl 430 if (ctrl.names_.size() && subsetPointIds.
empty())
433 <<
"Controllers specified, but without any points" <<
nl 447 subsetPointIds.
size()
454 const auto& treePoints = ppTree.
shapes();
456 const scalar searchDistSqr(
sqr(GREAT));
458 const label patchStart =
pp.start();
461 const point fc(faces[patchStart + patchFacei].centre(
points0));
465 treePoints.objectIndex
467 ppTree.findNearest(fc, searchDistSqr).index()
473 Pout<<
"Added face mapping for patch: " << patchIndex <<
endl;
485 const pointField& lumpedCentres0 = state0().points();
487 const label patchIndex = fpatch.
index();
489 patchControl& ctrl = patchControls_(patchIndex);
500 for (
const word& ctrlName : ctrl.names_)
502 const auto iter = controllers_.
cfind(ctrlName);
507 <<
"No controller: " << ctrlName <<
nl 523 adjacency(prev).
insert(curr);
524 adjacency(curr).
insert(prev);
526 else if (!adjacency.
found(curr))
528 adjacency(curr).
clear();
533 if (ctrl.names_.empty())
536 const label len = state0().size();
538 for (label i=0; i < len; ++i)
540 const label curr = i;
544 const label prev = i-1;
545 adjacency(prev).
insert(curr);
546 adjacency(curr).
insert(prev);
548 else if (!adjacency.
found(curr))
550 adjacency(curr).
clear();
555 if (ctrl.names_.size() && subsetPointIds.
empty())
558 <<
"Controllers specified, but without any points" <<
nl 578 const label nearest = iter.key();
580 labelList neighbours(iter.val().sortedToc());
582 const label len = neighbours.
size();
587 const point& nearPt = lumpedCentres0[nearest];
589 for (label j=1; j < len; ++j)
591 for (label i=0; i < j; ++i)
593 labelPair neiPair(neighbours[i], neighbours[j]);
598 lumpedCentres0[neiPair.
first()],
599 lumpedCentres0[neiPair.
second()]
603 if (tri.pointToBarycentric(tri.a(), bary) > SMALL)
614 acuteAngles.
append(-(ab & ac));
619 if (pairs.
size() > 1)
626 adjacencyPairs.
insert(nearest, pairs);
632 Info<<
"Adjacency table for patch: " << fpatch.
name() <<
nl;
634 for (
const label own : adjacency.
sortedToc())
637 for (
const label nei : adjacency[own].
sortedToc())
642 if (originalIds_.size())
644 Info<<
" # " << originalIds_[own] <<
" =>";
645 for (
const label nei : adjacency[own].
sortedToc())
647 Info<<
' ' << originalIds_[nei];
665 subsetPointIds.
size()
672 const auto& treePoints = ppTree.
shapes();
677 const scalar searchDistSqr(
sqr(GREAT));
686 forAll(meshPoints, pointi)
691 const label nearest =
692 treePoints.objectIndex
694 ppTree.findNearest(ptOnMesh, searchDistSqr).index()
697 interpList[pointi].nearest(nearest);
714 const point& nearPt = lumpedCentres0[nearest];
718 const labelPairList& adjacentPairs = adjacencyPairs[nearest];
720 unsortedNeighbours = adjacency[nearest].
toc();
721 unsortedNeiWeightDist.
resize(unsortedNeighbours.
size());
723 forAll(unsortedNeighbours, nbri)
725 unsortedNeiWeightDist[nbri] =
726 magSqr(ptOnMesh - lumpedCentres0[unsortedNeighbours[nbri]]);
735 for (
const label nbri : distOrder)
737 const label nextPointi = unsortedNeighbours[nbri];
739 const point& nextPt = lumpedCentres0[nextPointi];
743 const scalar weight =
754 unsortedNeiWeightDist[nbri] = weight;
757 distOrder[ngood] = nbri;
764 if (distOrder.size() < 1)
772 bool useFirst =
true;
774 if (neighbours.
size() > 1 && adjacentPairs.
size())
779 neiPointid.
set(neighbours);
781 for (
const labelPair& ends : adjacentPairs)
783 label nei1 = ends.first();
784 label nei2 = ends.second();
786 if (!neiPointid.
test(nei1) || !neiPointid.
test(nei2))
791 else if (neighbours.
find(nei2) < neighbours.
find(nei1))
795 std::swap(nei1, nei2);
799 triFace triF(nearest, nei1, nei2);
809 interpList[pointi].
set(triF, bary);
820 interpList[pointi].next(neighbours.
first(), neiWeight.
first());
831 const label nLumpedPoints = state0().
size();
835 if (patchControls_.empty())
838 <<
"Attempted to calculate areas without setMapping()" 846 if (isA<fvMesh>(pmesh))
848 const auto&
mesh = refCast<const fvMesh>(pmesh);
856 const label patchIndex = iter.key();
857 const patchControl& ctrl = iter.val();
875 zoneAreas[pointIndex] +=
mag(patchSf[patchIndex][patchFacei]);
893 const label nLumpedPoints = state0().size();
895 forces.
resize(nLumpedPoints);
896 moments.
resize(nLumpedPoints);
898 if (patchControls_.empty())
901 <<
"Attempted to calculate forces without setMapping()" 918 const word pName(forcesDict_.getOrDefault<
word>(
"p",
"p"));
919 scalar pRef = forcesDict_.getOrDefault<scalar>(
"pRef", 0);
920 scalar rhoRef = forcesDict_.getOrDefault<scalar>(
"rhoRef", 1);
929 if (isA<fvMesh>(pmesh) && pPtr)
931 const auto&
mesh = refCast<const fvMesh>(pmesh);
951 const label patchIndex = iter.key();
952 const patchControl& ctrl = iter.val();
956 if (!forceOnPatches.found(patchIndex))
966 * patchSf[patchIndex] * (patchPress[patchIndex] - pRef)
971 const vectorField& forceOnPatch = *forceOnPatches[patchIndex];
987 forces[pointIndex] += forceOnPatch[patchFacei];
994 patchCf[patchIndex][patchFacei]
995 - lumpedCentres[pointIndex]
999 moments[pointIndex] += lever ^ forceOnPatch[patchFacei];
1022 return pointsDisplacement(state(), fpatch,
points0);
1034 const label patchIndex = fpatch.
index();
1037 const pointField& lumpedCentres0 = state0().points();
1050 auto& disp = tdisp.ref();
1054 = patchControls_[patchIndex].interp_;
1056 forAll(meshPoints, pointi)
1066 disp[pointi] = (rotTensor & (
p0 - origin0)) + origin -
p0;
1081 const label patchIndex = fpatch.
index();
1084 const pointField& lumpedCentres0 = state0().points();
1097 auto& disp = tdisp.ref();
1101 patchControls_[patchIndex].interp_;
1103 forAll(meshPoints, pointi)
1113 disp[pointi] = (rotTensor & (
p0 - origin0)) + origin;
1131 const bool status = state_.
readData 1134 coupler().resolveFile(inputName_),
1135 state0().rotationOrder(),
1139 scalePoints(state_);
1141 state_.relax(relax_, prev);
1156 const bool writeMoments = (moments.
size() == forces.
size());
1158 if (fmt == outputFormatType::PLAIN)
1160 os <<
"########" <<
nl;
1163 os <<
"# Time value=" << timesWritten->
first() <<
nl 1164 <<
"# Time prev=" << timesWritten->
second() <<
nl;
1166 os <<
"# size=" << this->size() <<
nl 1167 <<
"# columns (points) (forces)";
1176 bool report =
false;
1177 scalar scaleLength = scaleOutput_[scalingType::LENGTH];
1178 scalar scaleForce = scaleOutput_[scalingType::FORCE];
1179 scalar scaleMoment = scaleOutput_[scalingType::MOMENT];
1181 if (scaleLength > 0)
1201 if (scaleMoment > 0)
1213 os <<
"# scaling points=" << scaleLength
1214 <<
" forces=" << scaleForce;
1218 os <<
" moments=" << scaleMoment;
1224 os <<
"########" <<
nl;
1228 const point& pt = state0().points()[i];
1230 putPlain(
os, scaleLength * pt) <<
' ';
1232 if (i < forces.
size())
1234 const vector val(scaleForce * forces[i]);
1239 putPlain(
os, vector::zero);
1245 if (i < moments.
size())
1247 const vector val(scaleMoment * moments[i]);
1252 putPlain(
os, vector::zero);
1265 os <<
"////////" <<
nl;
1302 coupler().resolveFile(outputName_)
1305 writeData(
os, forces, moments, outputFormat_, timesWritten);
1312 coupler().resolveFile(logName_),
1317 writeData(
os, forces, moments, outputFormatType::PLAIN, timesWritten);
EnumType get(const word &enumName) const
The enumeration corresponding to the given name.
Point unitVec() const
Return the unit vector (start-to-end)
const T & first() const noexcept
Access the first element.
bool set(const Key &key)
Same as insert (no value to overwrite)
void size(const label n)
Older name for setAddressableSize.
const surfaceVectorField & Sf() const
Return cell face area vectors.
A triangle primitive used to calculate face normals and swept volumes. Uses referred points...
List< scalar > areas(const polyMesh &pmesh) const
The areas for each pressure-zone.
void set(const bitSet &bitset)
Set specified bits from another bitset.
Inter-processor communication reduction functions.
Holds (reference to) pointField. Encapsulation of data needed for octree searches. Used for searching for nearest point. No bounding boxes around points. Only overlaps and calcNearest are implemented, rest makes little sense.
errorManipArg< error, int > exit(error &err, const int errNo=1)
tmp< pointField > pointsPosition(const lumpedPointState &state, const pointPatch &fpatch, const pointField &points0) const
The points absolute position according to specified state.
dimensioned< typename typeOfMag< Type >::type > mag(const dimensioned< Type > &dt)
barycentric2D pointToBarycentric(const point &pt) const
Calculate the barycentric coordinates from the given point.
labelList pointLabels(nPoints, -1)
static void writeData(Ostream &os, const Type &val)
void resize(const label len)
Adjust allocated size of list.
scalar mag() const
The magnitude (length) of the line.
error FatalError
Error stream (stdout output on all processes), with additional 'FOAM FATAL ERROR' header text and sta...
A list of keyword definitions, which are a keyword followed by a number of values (eg...
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
const surfaceVectorField & Cf() const
Return face centres as surfaceVectorField.
void setInterpolator(const pointPatch &fpatch, const pointField &points0)
Check if patch control exists for specified patch.
triPointRef tri(const UList< point > &points) const
Return the triangle.
bool found(const label &key) const
Same as contains()
const Type & shapes() const noexcept
Reference to shape.
labelList sortedOrder(const UList< T > &input)
Return the (stable) sort order for the list.
bool outside() const
True if any coordinate is negative.
void inflate(const scalar factor)
Expand box by factor*mag(span) in all dimensions.
std::enable_if< std::is_same< bool, TypeT >::value, bool >::type set(const label i, bool val=true)
A bitSet::set() method for a list of bool.
dimensionedSymmTensor sqr(const dimensionedVector &dv)
Output to file stream, using an OSstream.
static const Enum< outputFormatType > formatNames
Names for the output format types.
constexpr char nl
The newline '\n' character (0x0a)
void inplaceReorder(const labelUList &oldToNew, ListType &input, const bool prune=false)
Inplace reorder the elements of a list.
int debugSwitch(const char *name, const int deflt=0)
Lookup debug switch or add default value.
void resize(const label len)
Alter addressable list size, allocating new space if required while recovering old content...
Ostream & endl(Ostream &os)
Add newline and flush stream.
A HashTable of pointers to objects of type <T> with a label key.
T interpolate(const UList< T > &input) const
Linear interpolated value between nearest and next locations.
Begin list [isseparator].
void couplingCompleted(const label timeIndex) const
Register that coupling is completed at this calcFrequency.
void readDict(const dictionary &dict)
Update settings from dictionary.
Ostream & writeEntry(const keyType &key, const T &value)
Write a keyword/value entry.
const Type * findObject(const word &name, const bool recursive=false) const
Return const pointer to the object of the given Type.
T & first()
Access first element of the list, position [0].
A simple container for options an IOstream can normally have.
A HashTable of pointers to objects of type <T>, with deallocation management of the pointers...
quaternion normalised(const quaternion &q)
Return the normalised (unit) quaternion of the given quaternion.
bool writeData(Ostream &os, const UList< vector > &forces, const UList< vector > &moments, const outputFormatType fmt=outputFormatType::PLAIN, const Tuple2< scalar, scalar > *timesWritten=nullptr) const
Write points, forces, moments. Only call from the master process.
bool insert(const Key &key)
Insert a new entry, not overwriting existing entries.
void setPatchControl(const polyPatch &pp, const wordList &ctrlNames, const pointField &points0)
Define pressure-zones mapping for faces in the specified patches.
const dictionary & subDict(const word &keyword, enum keyType::option matchOpt=keyType::REGEX) const
Find and return a sub-dictionary.
static const Enum< eulerOrder > eulerOrderNames
The names for Euler-angle and Tait-Bryan angles, including "rollPitchYaw" and "yawPitchRoll" aliases...
static const Enum< scalingType > scalingNames
Names for the scaling types.
scalingType
Output format types.
#define forAll(list, i)
Loop across all elements in list.
static const word canonicalName
The canonical name ("lumpedPointMovement") for the dictionary.
Templated 2D Barycentric derived from VectorSpace. Has 3 components, one of which is redundant...
static const Enum< inputFormatType > formatNames
Names for the input format types.
bool insert(const Key &key, const T &obj)
Copy insert a new entry, not overwriting existing entries.
bool readEntry(const word &keyword, T &val, enum keyType::option matchOpt=keyType::REGEX, IOobjectOption::readOption readOpt=IOobjectOption::MUST_READ) const
Find entry and assign to T val. FatalIOError if it is found and the number of tokens is incorrect...
label size() const noexcept
The number of elements in table.
A simple linear interpolator between two locations, which are referenced by index.
A 1D vector of objects of type <T> that resizes itself as necessary to accept the new objects...
const_iterator cfind(const Key &key) const
Find and return an const_iterator set at the hashed entry.
void clear()
Clear the list, i.e. set size to zero.
const polyBoundaryMesh & boundaryMesh() const noexcept
Return boundary mesh.
A class for handling words, derived from Foam::string.
A triangular face using a FixedList of labels corresponding to mesh vertices.
bool forcesAndMoments(const polyMesh &pmesh, List< vector > &forces, List< vector > &moments) const
The forces and moments acting on each pressure-zone.
void clear()
Clear all entries from table.
bool hasInterpolator(const pointPatch &fpatch) const
Check if patch control exists for specified patch.
#define forAllIters(container, iter)
Iterate across all elements in the container object.
outputFormatType
Output format types.
static tmp< T > New(Args &&... args)
Construct tmp with forwarding arguments.
virtual const word & name() const =0
Return name.
void append(const T &val)
Copy append an element to the end of this list.
label size() const noexcept
The number of elements in the list.
const dimensionSet dimPressure
label find(const T &val, label pos=0) const
Find index of the first occurrence of the value.
bool test(const label pos) const
Test for True value at specified position, never auto-vivify entries.
A 1D vector of objects of type <T>, where the size of the vector is known and can be used for subscri...
A polyBoundaryMesh is a polyPatch list with additional search methods and registered IO...
An Ostream is an abstract base class for all output systems (streams, files, token lists...
bool empty() const noexcept
True if the hash table is empty.
void writeList(vtk::formatter &fmt, const UList< uint8_t > &values)
Write a list of uint8_t values.
A Vector of values with scalar precision, where scalar is float/double depending on the compilation f...
int debug
Static debugging option.
bool readIfPresent(const word &keyword, T &val, enum keyType::option matchOpt=keyType::REGEX) const
Find an entry if present, and assign to T val. FatalIOError if it is found and the number of tokens i...
tmp< pointField > pointsDisplacement(const pointPatch &fpatch, const pointField &points0) const
Displace points according to the current state.
OBJstream os(runTime.globalPath()/outputName)
bool readState()
Read state from file, applying relaxation as requested.
void clear() noexcept
Clear the addressed list, i.e. set the size to zero.
dictionary subOrEmptyDict(const word &keyword, enum keyType::option matchOpt=keyType::REGEX, const bool mandatory=false) const
Find and return a sub-dictionary as a copy, otherwise return an empty dictionary. ...
void scalePoints(const scalar scaleFactor)
Scale points by given factor.
void writeDict(Ostream &os) const
Write axis, locations, division as a dictionary.
Represents 0/1 range or concept. Used for tagged dispatch or clamping.
Point vec() const
Return start-to-end vector.
void checkPatchControl(const polyPatch &pp) const
Check if patch control exists for specified patch.
pointField points0(pointIOField(IOobject("points", mesh.time().constant(), polyMesh::meshSubDir, mesh, IOobject::MUST_READ, IOobject::NO_WRITE, IOobject::NO_REGISTER)))
bool couplingPending(const label timeIndex) const
Check if coupling is pending (according to the calcFrequency)
Non-pointer based hierarchical recursive searching.
A bitSet stores bits (elements with only two states) in packed internal format and supports a variety...
#define WarningInFunction
Report a warning using Foam::Warning.
Enum is a wrapper around a list of names/values that represent particular enumeration (or int) values...
#define FatalIOErrorInFunction(ios)
Report an error message using Foam::FatalIOError.
Basic pointPatch represents a set of points from the mesh.
virtual label index() const =0
Return the index of this patch in the pointBoundaryMesh.
auto key(const Type &t) -> typename std::enable_if< std::is_enum< Type >::value, typename std::underlying_type< Type >::type >::type
const tensorField & rotations() const
The local-to-global transformation for each point.
List< Key > sortedToc() const
The table of contents (the keys) in sorted order.
A List with indirect addressing. Like IndirectList but does not store addressing. ...
const T2 & second() const noexcept
Access the second element.
static bool master(const label communicator=worldComm)
True if process corresponds to the master rank in the communicator.
const polyBoundaryMesh & patches
const pointField & points() const
The points corresponding to mass centres.
static int debug
Debug switch.
Standard boundBox with extra functionality for use in octree.
List< label > sortedToc(const UList< bool > &bools)
Return the (sorted) values corresponding to 'true' entries.
messageStream Info
Information stream (stdout output on master, null elsewhere)
Mesh consisting of general polyhedral cells.
List< label > toc() const
The table of contents (the keys) in unsorted order.
T getOrDefault(const word &keyword, const T &deflt, enum keyType::option matchOpt=keyType::REGEX) const
Find and return a T, or return the given default value. FatalIOError if it is found and the number of...
A class for managing temporary objects.
A patch is a list of labels that address the faces in the global face list.
const T & second() const noexcept
Access the second element.
const T1 & first() const noexcept
Access the first element.
bool readData(Istream &is, const quaternion::eulerOrder rotOrder=quaternion::eulerOrder::ZXZ, const bool degrees=false)
Read input as dictionary content.
Tensor of scalars, i.e. Tensor<scalar>.
bool hasPatchControl(const label patchIndex) const
Check if patch control exists for specified patch.
const Boundary & boundaryField() const noexcept
Return const-reference to the boundary field.
prefixOSstream Pout
OSstream wrapped stdout (std::cout) with parallel prefix.
lumpedPointMovement()
Default construct.
const volScalarField & p0
dimensioned< typename typeOfMag< Type >::type > magSqr(const dimensioned< Type > &dt)
The state of lumped points corresponds to positions and rotations.
uindirectPrimitivePatch pp(UIndirectList< face >(mesh.faces(), faceLabels), mesh.points())
virtual const labelList & meshPoints() const =0
Return mesh points.
forAllConstIters(mixture.phases(), phase)
dimensionSet clamp(const dimensionSet &a, const dimensionSet &range)
const dimensionSet & dimensions() const noexcept
Return dimensions.
static void listCombineReduce(List< T > &values, const CombineOp &cop, const int tag=UPstream::msgType(), const label comm=UPstream::worldComm)
After completion all processors have the same data.
A topoSetPointSource to select all points based on usage in given faceSet(s).
virtual label size() const =0
Return size.
FlatOutput::OutputAdaptor< Container, Delimiters > flatOutput(const Container &obj, Delimiters delim)
Global flatOutput() function with specified output delimiters.
const dictionary * findDict(const word &keyword, enum keyType::option matchOpt=keyType::REGEX) const
Find and return a sub-dictionary pointer if present (and a sub-dictionary) otherwise return nullptr...
IOerror FatalIOError
Error stream (stdout output on all processes), with additional 'FOAM FATAL IO ERROR' header text and ...
static constexpr const zero Zero
Global zero (0)