Go to the documentation of this file.
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();
208 if (originalIds_.size() !=
points0.size())
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);
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
441 subsetPointIds.sortedToc(),
442 subsetPointIds.size()
458 const scalar searchDistSqr(
sqr(GREAT));
460 const label patchStart = pp.
start();
463 const point fc(faces[patchStart + patchFacei].centre(
points0));
469 ppTree.findNearest(fc, searchDistSqr).index()
475 Pout<<
"Added face mapping for patch: " << patchIndex <<
endl;
487 const pointField& lumpedCentres0 = state0().points();
489 const label patchIndex = fpatch.
index();
491 patchControl& ctrl = patchControls_(patchIndex);
502 for (
const word& ctrlName : ctrl.names_)
504 const auto iter = controllers_.cfind(ctrlName);
509 <<
"No controller: " << ctrlName <<
nl
525 adjacency(prev).insert(curr);
526 adjacency(curr).insert(prev);
528 else if (!adjacency.found(curr))
530 adjacency(curr).clear();
535 if (ctrl.names_.empty())
538 const label len = state0().size();
540 for (label i=0; i < len; ++i)
542 const label curr = i;
546 const label prev = i-1;
547 adjacency(prev).insert(curr);
548 adjacency(curr).insert(prev);
550 else if (!adjacency.found(curr))
552 adjacency(curr).clear();
557 if (ctrl.names_.size() && subsetPointIds.empty())
560 <<
"Controllers specified, but without any points" <<
nl
580 const label nearest = iter.key();
582 labelList neighbours(iter.val().sortedToc());
584 const label len = neighbours.size();
589 const point& nearPt = lumpedCentres0[nearest];
591 for (label j=1; j < len; ++j)
593 for (label i=0; i < j; ++i)
595 labelPair neiPair(neighbours[i], neighbours[j]);
600 lumpedCentres0[neiPair.first()],
601 lumpedCentres0[neiPair.
second()]
616 acuteAngles.
append(-(ab & ac));
621 if (pairs.size() > 1)
628 adjacencyPairs.insert(nearest, pairs);
634 Info<<
"Adjacency table for patch: " << fpatch.
name() <<
nl;
636 for (
const label own : adjacency.sortedToc())
639 for (
const label nei : adjacency[own].sortedToc())
644 if (originalIds_.size())
646 Info<<
" # " << originalIds_[own] <<
" =>";
647 for (
const label nei : adjacency[own].sortedToc())
649 Info<<
' ' << originalIds_[nei];
661 subsetPointIds.sortedToc(),
662 subsetPointIds.size()
680 const scalar searchDistSqr(
sqr(GREAT));
684 interpList.
resize(meshPoints.size());
689 forAll(meshPoints, pointi)
694 const label nearest =
697 ppTree.findNearest(ptOnMesh, searchDistSqr).index()
700 interpList[pointi].nearest(nearest);
717 const point& nearPt = lumpedCentres0[nearest];
721 const labelPairList& adjacentPairs = adjacencyPairs[nearest];
723 unsortedNeighbours = adjacency[nearest].toc();
724 unsortedNeiWeightDist.
resize(unsortedNeighbours.size());
726 forAll(unsortedNeighbours, nbri)
728 unsortedNeiWeightDist[nbri] =
729 magSqr(ptOnMesh - lumpedCentres0[unsortedNeighbours[nbri]]);
738 for (
const label nbri : distOrder)
740 const label nextPointi = unsortedNeighbours[nbri];
742 const point& nextPt = lumpedCentres0[nextPointi];
746 const scalar weight =
757 unsortedNeiWeightDist[nbri] = weight;
760 distOrder[ngood] = nbri;
767 if (distOrder.size() < 1)
775 bool useFirst =
true;
777 if (neighbours.size() > 1 && adjacentPairs.size())
782 neiPointid.
set(neighbours);
784 for (
const labelPair& ends : adjacentPairs)
786 label nei1 = ends.first();
787 label nei2 = ends.second();
789 if (!neiPointid.
test(nei1) || !neiPointid.
test(nei2))
794 else if (neighbours.find(nei2) < neighbours.find(nei1))
798 std::swap(nei1, nei2);
802 triFace triF(nearest, nei1, nei2);
812 interpList[pointi].
set(triF, bary);
823 interpList[pointi].next(neighbours.first(), neiWeight.first());
834 const label nLumpedPoints = state0().size();
838 if (patchControls_.empty())
841 <<
"Attempted to calculate areas without setMapping()"
849 if (isA<fvMesh>(pmesh))
851 const fvMesh&
mesh = dynamicCast<const fvMesh>(pmesh);
859 const label patchIndex = iter.key();
860 const patchControl& ctrl = iter.val();
878 zoneAreas[pointIndex] +=
mag(patchSf[patchIndex][patchFacei]);
897 const label nLumpedPoints = state0().size();
899 forces.
resize(nLumpedPoints);
900 moments.
resize(nLumpedPoints);
902 if (patchControls_.empty())
905 <<
"Attempted to calculate forces without setMapping()"
922 const word pName(forcesDict_.getOrDefault<
word>(
"p",
"p"));
923 scalar pRef = forcesDict_.getOrDefault<scalar>(
"pRef", 0);
924 scalar rhoRef = forcesDict_.getOrDefault<scalar>(
"rhoRef", 1);
933 if (isA<fvMesh>(pmesh) && pPtr)
935 const fvMesh&
mesh = dynamicCast<const fvMesh>(pmesh);
948 rhoRef = (
p.dimensions() ==
dimPressure ? 1.0 : rhoRef);
955 const label patchIndex = iter.key();
956 const patchControl& ctrl = iter.val();
960 if (!forceOnPatches.found(patchIndex))
970 * patchSf[patchIndex] * (patchPress[patchIndex] - pRef)
975 const vectorField& forceOnPatch = *forceOnPatches[patchIndex];
991 forces[pointIndex] += forceOnPatch[patchFacei];
998 patchCf[patchIndex][patchFacei]
999 - lumpedCentres[pointIndex]
1003 moments[pointIndex] += lever ^ forceOnPatch[patchFacei];
1029 return pointsDisplacement(state(), fpatch,
points0);
1041 const label patchIndex = fpatch.
index();
1044 const pointField& lumpedCentres0 = state0().points();
1057 auto& disp = tdisp.ref();
1061 = patchControls_[patchIndex].interp_;
1063 forAll(meshPoints, pointi)
1073 disp[pointi] = (rotTensor & (
p0 - origin0)) + origin -
p0;
1088 const label patchIndex = fpatch.
index();
1091 const pointField& lumpedCentres0 = state0().points();
1104 auto& disp = tdisp.ref();
1108 patchControls_[patchIndex].interp_;
1110 forAll(meshPoints, pointi)
1120 disp[pointi] = (rotTensor & (
p0 - origin0)) + origin;
1138 const bool status = state_.
readData
1141 coupler().resolveFile(inputName_),
1142 state0().rotationOrder(),
1146 scalePoints(state_);
1148 state_.relax(relax_, prev);
1163 const bool writeMoments = (moments.
size() == forces.
size());
1165 if (fmt == outputFormatType::PLAIN)
1167 os <<
"########" <<
nl;
1170 os <<
"# Time value=" << timesWritten->
first() <<
nl
1171 <<
"# Time prev=" << timesWritten->
second() <<
nl;
1173 os <<
"# size=" << this->size() <<
nl
1174 <<
"# columns (points) (forces)";
1183 bool report =
false;
1184 scalar scaleLength = scaleOutput_[scalingType::LENGTH];
1185 scalar scaleForce = scaleOutput_[scalingType::FORCE];
1186 scalar scaleMoment = scaleOutput_[scalingType::MOMENT];
1188 if (scaleLength > 0)
1208 if (scaleMoment > 0)
1220 os <<
"# scaling points=" << scaleLength
1221 <<
" forces=" << scaleForce;
1225 os <<
" moments=" << scaleMoment;
1231 os <<
"########" <<
nl;
1235 const point& pt = state0().points()[i];
1237 putPlain(
os, scaleLength * pt) <<
' ';
1239 if (i < forces.
size())
1241 const vector val(scaleForce * forces[i]);
1252 if (i < moments.
size())
1254 const vector val(scaleMoment * moments[i]);
1272 os <<
"////////" <<
nl;
1309 coupler().resolveFile(outputName_)
1312 writeData(
os, forces, moments, outputFormat_, timesWritten);
1319 coupler().resolveFile(logName_),
1324 writeData(
os, forces, moments, outputFormatType::PLAIN, timesWritten);
dictionary * findDict(const word &keyword, enum keyType::option matchOpt=keyType::REGEX)
void resize(const label len)
const dimensionSet dimPressure
A templated (3 x 3) tensor of objects of <T> derived from MatrixSpace.
virtual label index() const =0
void writeDict(Ostream &os) const
Enum is a wrapper around a list of names/values that represent particular enumeration (or int) values...
A class for handling words, derived from Foam::string.
A bitSet stores bits (elements with only two states) in packed internal format and supports a variety...
void resize(const label len)
A polyBoundaryMesh is a polyPatch list with additional search methods and registered IO.
bool forcesAndMoments(const polyMesh &pmesh, List< vector > &forces, List< vector > &moments) const
static const Enum< scalingType > scalingNames
T interpolate(const UList< T > &input) const
bool writeData(Ostream &os, const UList< vector > &forces, const UList< vector > &moments, const outputFormatType fmt=outputFormatType::PLAIN, const Tuple2< scalar, scalar > *timesWritten=nullptr) const
void readDict(const dictionary &dict)
A class for managing temporary objects.
static constexpr const zero Zero
A 1D vector of objects of type <T> that resizes itself as necessary to accept the new objects.
int debugSwitch(const char *name, const int deflt=0)
void inflate(const scalar s)
Standard boundBox with extra functionality for use in octree.
List< scalar > areas(const polyMesh &pmesh) const
auto key(const Type &t) -> typename std::enable_if< std::is_enum< Type >::value, typename std::underlying_type< Type >::type >::type
Templated 2D Barycentric derived from VectorSpace. Has 3 components, one of which is redundant.
void set(const bitSet &bitset)
static bool master(const label communicator=worldComm)
const polyBoundaryMesh & boundaryMesh() const
const pointField & points() const
Ostream & endl(Ostream &os)
Basic pointPatch represents a set of points from the mesh.
EnumType get(const word &enumName) const
bool test(const label pos) const
A HashTable with keys but without contents that is similar to std::unordered_set.
triPointRef tri(const UList< point > &points) const
Mesh consisting of general polyhedral cells.
Holds (reference to) pointField. Encapsulation of data needed for octree searches....
bool hasInterpolator(const pointPatch &fpatch) const
dimensioned< typename typeOfMag< Type >::type > magSqr(const dimensioned< Type > &dt)
bool readData(Istream &is, const quaternion::eulerOrder rotOrder=quaternion::eulerOrder::ZXZ, const bool degrees=false)
bool couplingPending(const label timeIndex) const
A triangle primitive used to calculate face normals and swept volumes.
The state of lumped points corresponds to positions and rotations.
const polyMesh & mesh() const noexcept
Generic templated field type.
const polyBoundaryMesh & boundaryMesh() const
static const Enum< inputFormatType > formatNames
A patch is a list of labels that address the faces in the global face list.
DynamicList< T, SizeMin > & append(const T &val)
static MinMax< T > zero_one()
const dictionary & subDict(const word &keyword, enum keyType::option matchOpt=keyType::REGEX) const
The IOstreamOption is a simple container for options an IOstream can normally have.
Non-pointer based hierarchical recursive searching.
bool readEntry(const word &keyword, T &val, enum keyType::option matchOpt=keyType::REGEX, bool mandatory=true) const
void writeList(vtk::formatter &fmt, const UList< uint8_t > &values)
@ END_STATEMENT
End entry [isseparator].
#define forAllIters(container, iter)
static void writeData(Ostream &os, const Type &val)
A list of keyword definitions, which are a keyword followed by a number of values (eg,...
static const word canonicalName
static const Enum< outputFormatType > formatNames
OBJstream os(runTime.globalPath()/outputName)
Mesh data needed to do the Finite Volume discretisation.
FlatOutput::OutputAdaptor< Container, Delimiters > flatOutput(const Container &obj, Delimiters delim)
label index() const noexcept
virtual const word & name() const =0
Vector< scalar > vector
A scalar version of the templated Vector.
Inter-processor communication reduction functions.
dictionary subOrEmptyDict(const word &keyword, enum keyType::option matchOpt=keyType::REGEX, const bool mandatory=false) const
errorManipArg< error, int > exit(error &err, const int errNo=1)
Output to file stream, using an OSstream.
virtual label size() const =0
tmp< pointField > pointsPosition(const lumpedPointState &state, const pointPatch &fpatch, const pointField &points0) const
VectorSpace< Form, Cmpt, Ncmpts > normalised(const VectorSpace< Form, Cmpt, Ncmpts > &vs)
static void listCombineGather(const List< commsStruct > &comms, List< T > &Value, const CombineOp &cop, const int tag, const label comm)
label pointLabel(const label index) const
pointField points0(pointIOField(IOobject("points", mesh.time().constant(), polyMesh::meshSubDir, mesh, IOobject::MUST_READ, IOobject::NO_WRITE, false)))
static const Enum< eulerOrder > eulerOrderNames
virtual const faceList & faces() const
#define FatalErrorInFunction
dimensionedSymmTensor sqr(const dimensionedVector &dv)
const Type * findObject(const word &name, const bool recursive=false) const
An ordered pair of two objects of type <T> with first() and second() elements.
forAllConstIters(mixture.phases(), phase)
A triangular face using a FixedList of labels corresponding to mesh vertices.
A HashTable of pointers to objects of type <T>, with deallocation management of the pointers.
bool hasPatchControl(const label patchIndex) const
virtual const labelList & meshPoints() const =0
void setPatchControl(const polyPatch &pp, const wordList &ctrlNames, const pointField &points0)
const T & second() const noexcept
A 1D array of objects of type <T>, where the size of the vector is known and used for subscript bound...
tmp< pointField > pointsDisplacement(const pointPatch &fpatch, const pointField &points0) const
dimensioned< typename typeOfMag< Type >::type > mag(const dimensioned< Type > &dt)
A 1D vector of objects of type <T>, where the size of the vector is known and can be used for subscri...
const tensorField & rotations() const
static tmp< T > New(Args &&... args)
bool insert(const Key &key)
const polyBoundaryMesh & patches
Ostream & writeEntry(const keyType &key, const T &value)
std::enable_if< std::is_same< bool, TypeT >::value, bool >::type set(const label i, bool val=true)
const T2 & second() const noexcept
@ END_LIST
End list [isseparator].
A List with indirect addressing.
A simple linear interpolator between two locations, which are referenced by index.
void inplaceReorder(const labelUList &oldToNew, ListType &input, const bool prune=false)
#define FatalIOErrorInFunction(ios)
const word & name() const noexcept
labelList sortedOrder(const UList< T > &input)
barycentric2D pointToBarycentric(const point &pt) const
An Ostream is an abstract base class for all output systems (streams, files, token lists,...
void checkPatchControl(const polyPatch &pp) const
const volScalarField & p0
void couplingCompleted(const label timeIndex) const
static void listCombineScatter(const List< commsStruct > &comms, List< T > &Value, const int tag, const label comm)
T getOrDefault(const word &keyword, const T &deflt, enum keyType::option matchOpt=keyType::REGEX) const
Generic GeometricField class.
@ BEGIN_LIST
Begin list [isseparator].
A topoSetPointSource to select all points based on usage in given faceSet(s).
const surfaceVectorField & Cf() const
void setInterpolator(const pointPatch &fpatch, const pointField &points0)
const T1 & first() const noexcept
#define WarningInFunction
labelList pointLabels(nPoints, -1)
bool readIfPresent(const word &keyword, T &val, enum keyType::option matchOpt=keyType::REGEX) const
const Boundary & boundaryField() const
A HashTable of pointers to objects of type <T> with a label key.
const surfaceVectorField & Sf() const