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)
134 inputName_(
"positions.in"),
135 outputName_(
"forces.out"),
136 logName_(
"movement.log"),
162 inputName_(
"positions.in"),
163 outputName_(
"forces.out"),
164 logName_(
"movement.log"),
178 return (
timeIndex >= lastTrigger_ + calcFrequency_);
194 auto&
points0 = tpoints0.ref();
199 originalIds_.
clear();
200 controllers_.clear();
201 patchControls_.clear();
212 <<
"Incorrect number of pointLabels. Had " 213 << originalIds_.size() <<
" for " <<
points0.
size() <<
" points" 222 for (
const label
id : originalIds_)
224 if (!pointIdMap.
insert(
id, pointi))
232 if (!duplicates.
empty())
235 <<
"Found duplicate point ids " 249 (*iter)->remapPointLabels(
points0.
size(), pointIdMap);
257 controllers_.clear();
266 coupler_.readDict(commDict);
268 calcFrequency_ = commDict.
getOrDefault<label>(
"calcFrequency", 1);
272 commDict.
readEntry(
"inputName", inputName_);
273 commDict.
readEntry(
"outputName", outputName_);
277 outputFormat_ = formatNames.get(
"outputFormat", commDict);
284 if ((scaleDict = commDict.
findDict(
"scaleInput")) !=
nullptr)
286 for (
int i=0; i < scaleInput_.size(); ++i)
293 && scaleInput_[i] > 0
296 Info<<
"Using input " <<
key <<
" multiplier: " 297 << scaleInput_[i] <<
nl;
302 if ((scaleDict = commDict.
findDict(
"scaleOutput")) !=
nullptr)
304 for (
int i=0; i < scaleOutput_.size(); ++i)
311 && scaleOutput_[i] > 0
314 Info<<
"Using output " <<
key <<
" multiplier: " 315 << scaleOutput_[i] <<
nl;
327 quaternion::eulerOrder::ZXZ
332 state0_.
scalePoints(scaleInput_[scalingType::LENGTH]);
343 return hasPatchControl(
pp.index());
352 return hasInterpolator(fpatch.
index());
361 const auto ctrlIter = patchControls_.cfind(
pp.index());
363 if (!ctrlIter.good())
366 <<
"No controllers for patch " <<
pp.name()
370 const patchControl& ctrl = *ctrlIter;
372 for (
const word& ctrlName : ctrl.names_)
374 const auto iter = controllers_.cfind(ctrlName);
379 <<
"No controller: " << ctrlName <<
nl 380 <<
" For patch " <<
pp.name()
395 const pointField& lumpedCentres0 = state0().points();
397 const label patchIndex =
pp.index();
402 patchControl& ctrl = patchControls_(patchIndex);
403 ctrl.names_ = ctrlNames;
408 checkPatchControl(
pp);
410 const faceList& faces =
pp.boundaryMesh().mesh().faces();
415 for (
const word& ctrlName : ctrl.names_)
417 const auto iter = controllers_.
cfind(ctrlName);
422 <<
"No controller: " << ctrlName <<
nl 431 if (ctrl.names_.size() && subsetPointIds.
empty())
434 <<
"Controllers specified, but without any points" <<
nl 448 subsetPointIds.
size()
455 const auto& treePoints = ppTree.
shapes();
457 const scalar searchDistSqr(
sqr(GREAT));
459 const label patchStart =
pp.start();
462 const point fc(faces[patchStart + patchFacei].centre(
points0));
466 treePoints.objectIndex
468 ppTree.findNearest(fc, searchDistSqr).index()
474 Pout<<
"Added face mapping for patch: " << patchIndex <<
endl;
486 const pointField& lumpedCentres0 = state0().points();
488 const label patchIndex = fpatch.
index();
490 patchControl& ctrl = patchControls_(patchIndex);
501 for (
const word& ctrlName : ctrl.names_)
503 const auto iter = controllers_.
cfind(ctrlName);
508 <<
"No controller: " << ctrlName <<
nl 524 adjacency(prev).
insert(curr);
525 adjacency(curr).
insert(prev);
527 else if (!adjacency.
found(curr))
529 adjacency(curr).
clear();
534 if (ctrl.names_.empty())
537 const label len = state0().size();
539 for (label i=0; i < len; ++i)
541 const label curr = i;
545 const label prev = i-1;
546 adjacency(prev).
insert(curr);
547 adjacency(curr).
insert(prev);
549 else if (!adjacency.
found(curr))
551 adjacency(curr).
clear();
556 if (ctrl.names_.size() && subsetPointIds.
empty())
559 <<
"Controllers specified, but without any points" <<
nl 579 const label nearest = iter.key();
581 labelList neighbours(iter.val().sortedToc());
583 const label len = neighbours.
size();
588 const point& nearPt = lumpedCentres0[nearest];
590 for (label j=1; j < len; ++j)
592 for (label i=0; i < j; ++i)
594 labelPair neiPair(neighbours[i], neighbours[j]);
599 lumpedCentres0[neiPair.
first()],
600 lumpedCentres0[neiPair.
second()]
604 if (tri.pointToBarycentric(tri.a(), bary) > SMALL)
615 acuteAngles.
append(-(ab & ac));
620 if (pairs.
size() > 1)
627 adjacencyPairs.
insert(nearest, pairs);
633 Info<<
"Adjacency table for patch: " << fpatch.
name() <<
nl;
635 for (
const label own : adjacency.
sortedToc())
638 for (
const label nei : adjacency[own].
sortedToc())
643 if (originalIds_.size())
645 Info<<
" # " << originalIds_[own] <<
" =>";
646 for (
const label nei : adjacency[own].
sortedToc())
648 Info<<
' ' << originalIds_[nei];
666 subsetPointIds.
size()
673 const auto& treePoints = ppTree.
shapes();
678 const scalar searchDistSqr(
sqr(GREAT));
687 forAll(meshPoints, pointi)
692 const label nearest =
693 treePoints.objectIndex
695 ppTree.findNearest(ptOnMesh, searchDistSqr).index()
698 interpList[pointi].nearest(nearest);
715 const point& nearPt = lumpedCentres0[nearest];
719 const labelPairList& adjacentPairs = adjacencyPairs[nearest];
721 unsortedNeighbours = adjacency[nearest].
toc();
722 unsortedNeiWeightDist.
resize(unsortedNeighbours.
size());
724 forAll(unsortedNeighbours, nbri)
726 unsortedNeiWeightDist[nbri] =
727 magSqr(ptOnMesh - lumpedCentres0[unsortedNeighbours[nbri]]);
736 for (
const label nbri : distOrder)
738 const label nextPointi = unsortedNeighbours[nbri];
740 const point& nextPt = lumpedCentres0[nextPointi];
744 const scalar weight =
755 unsortedNeiWeightDist[nbri] = weight;
758 distOrder[ngood] = nbri;
765 if (distOrder.size() < 1)
773 bool useFirst =
true;
775 if (neighbours.
size() > 1 && adjacentPairs.
size())
780 neiPointid.
set(neighbours);
782 for (
const labelPair& ends : adjacentPairs)
784 label nei1 = ends.first();
785 label nei2 = ends.second();
787 if (!neiPointid.
test(nei1) || !neiPointid.
test(nei2))
792 else if (neighbours.
find(nei2) < neighbours.
find(nei1))
796 std::swap(nei1, nei2);
800 triFace triF(nearest, nei1, nei2);
810 interpList[pointi].
set(triF, bary);
821 interpList[pointi].next(neighbours.
first(), neiWeight.
first());
832 const label nLumpedPoints = state0().
size();
836 if (patchControls_.empty())
839 <<
"Attempted to calculate areas without setMapping()" 847 if (isA<fvMesh>(pmesh))
849 const auto&
mesh = refCast<const fvMesh>(pmesh);
857 const label patchIndex = iter.key();
858 const patchControl& ctrl = iter.val();
876 zoneAreas[pointIndex] +=
mag(patchSf[patchIndex][patchFacei]);
894 const label nLumpedPoints = state0().size();
896 forces.
resize(nLumpedPoints);
897 moments.
resize(nLumpedPoints);
899 if (patchControls_.empty())
902 <<
"Attempted to calculate forces without setMapping()" 919 const word pName(forcesDict_.getOrDefault<
word>(
"p",
"p"));
920 scalar pRef = forcesDict_.getOrDefault<scalar>(
"pRef", 0);
921 scalar rhoRef = forcesDict_.getOrDefault<scalar>(
"rhoRef", 1);
930 if (isA<fvMesh>(pmesh) && pPtr)
932 const auto&
mesh = refCast<const fvMesh>(pmesh);
952 const label patchIndex = iter.key();
953 const patchControl& ctrl = iter.val();
957 if (!forceOnPatches.found(patchIndex))
967 * patchSf[patchIndex] * (patchPress[patchIndex] - pRef)
972 const vectorField& forceOnPatch = *forceOnPatches[patchIndex];
988 forces[pointIndex] += forceOnPatch[patchFacei];
995 patchCf[patchIndex][patchFacei]
996 - lumpedCentres[pointIndex]
1000 moments[pointIndex] += lever ^ forceOnPatch[patchFacei];
1023 return pointsDisplacement(state(), fpatch,
points0);
1035 const label patchIndex = fpatch.
index();
1038 const pointField& lumpedCentres0 = state0().points();
1051 auto& disp = tdisp.ref();
1055 = patchControls_[patchIndex].interp_;
1057 forAll(meshPoints, pointi)
1067 disp[pointi] = (rotTensor & (
p0 - origin0)) + origin -
p0;
1082 const label patchIndex = fpatch.
index();
1085 const pointField& lumpedCentres0 = state0().points();
1098 auto& disp = tdisp.ref();
1102 patchControls_[patchIndex].interp_;
1104 forAll(meshPoints, pointi)
1114 disp[pointi] = (rotTensor & (
p0 - origin0)) + origin;
1132 const bool status = state_.
readData 1135 coupler().resolveFile(inputName_),
1136 state0().rotationOrder(),
1140 scalePoints(state_);
1142 state_.relax(relax_, prev);
1157 const bool writeMoments = (moments.
size() == forces.
size());
1159 if (fmt == outputFormatType::PLAIN)
1161 os <<
"########" <<
nl;
1164 os <<
"# Time value=" << timesWritten->
first() <<
nl 1165 <<
"# Time prev=" << timesWritten->
second() <<
nl;
1167 os <<
"# size=" << this->size() <<
nl 1168 <<
"# columns (points) (forces)";
1177 bool report =
false;
1178 scalar scaleLength = scaleOutput_[scalingType::LENGTH];
1179 scalar scaleForce = scaleOutput_[scalingType::FORCE];
1180 scalar scaleMoment = scaleOutput_[scalingType::MOMENT];
1182 if (scaleLength > 0)
1202 if (scaleMoment > 0)
1214 os <<
"# scaling points=" << scaleLength
1215 <<
" forces=" << scaleForce;
1219 os <<
" moments=" << scaleMoment;
1225 os <<
"########" <<
nl;
1229 const point& pt = state0().points()[i];
1231 putPlain(
os, scaleLength * pt) <<
' ';
1233 if (i < forces.
size())
1235 const vector val(scaleForce * forces[i]);
1240 putPlain(
os, vector::zero);
1246 if (i < moments.
size())
1248 const vector val(scaleMoment * moments[i]);
1253 putPlain(
os, vector::zero);
1266 os <<
"////////" <<
nl;
1303 coupler().resolveFile(outputName_)
1306 writeData(
os, forces, moments, outputFormat_, timesWritten);
1313 coupler().resolveFile(logName_),
1318 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()
label find(const T &val, label pos=0, label len=-1) const
Find index of the first occurrence of the value.
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 as an OSstream, normally using std::ofstream for the actual output...
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()
Remove 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
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...
append (seek end after open)
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.
virtual Ostream & endEntry()
Write end entry (';') followed by newline.
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)
Combines List elements. 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 it is a 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)