lumpedPointMovement.C
Go to the documentation of this file.
1 /*---------------------------------------------------------------------------*\
2  ========= |
3  \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
4  \\ / O peration |
5  \\ / A nd | www.openfoam.com
6  \\/ M anipulation |
7 -------------------------------------------------------------------------------
8  Copyright (C) 2016-2021 OpenCFD Ltd.
9 -------------------------------------------------------------------------------
10 License
11  This file is part of OpenFOAM.
12 
13  OpenFOAM is free software: you can redistribute it and/or modify it
14  under the terms of the GNU General Public License as published by
15  the Free Software Foundation, either version 3 of the License, or
16  (at your option) any later version.
17 
18  OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
19  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
20  FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
21  for more details.
22 
23  You should have received a copy of the GNU General Public License
24  along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
25 
26 \*---------------------------------------------------------------------------*/
27 
28 #include "lumpedPointMovement.H"
29 #include "lumpedPointIOMovement.H"
30 #include "Fstream.H"
31 #include "volFields.H"
32 #include "surfaceFields.H"
33 #include "PtrMap.H"
34 #include "triFace.H"
35 #include "labelPair.H"
36 #include "indexedOctree.H"
37 #include "treeDataPoint.H"
38 #include "pointIndexHit.H"
39 #include "pointPatch.H"
40 #include "PstreamReduceOps.H"
41 
42 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
43 
45 (
46  ::Foam::debug::debugSwitch("lumpedPointMovement", 0)
47 );
48 
49 
50 const Foam::word
51 Foam::lumpedPointMovement::canonicalName("lumpedPointMovement");
52 
53 
54 const Foam::Enum
55 <
57 >
59 ({
60  { outputFormatType::PLAIN, "plain" },
61  { outputFormatType::DICTIONARY, "dictionary" },
62 });
63 
64 
65 const Foam::Enum
66 <
68 >
70 ({
71  { scalingType::LENGTH, "length" },
72  { scalingType::FORCE, "force" },
73  { scalingType::MOMENT, "moment" },
74 });
75 
76 
77 
78 // * * * * * * * * * * * * * * * Local Functions * * * * * * * * * * * * * * //
79 
80 namespace Foam
81 {
82 
84 //- Space-separated vector value (ASCII)
85 static inline Ostream& putPlain(Ostream& os, const vector& v)
86 {
87  return os << v.x() << ' ' << v.y() << ' ' << v.z();
88 }
89 
90 
92 //- Write list content with size, bracket, content, bracket one-per-line.
93 // This makes for consistent for parsing, regardless of the list length.
94 template <class T>
95 static void writeList(Ostream& os, const string& header, const UList<T>& list)
96 {
97  const label len = list.size();
98 
99  // Header string
100  os << header.c_str() << nl;
101 
102  // Write size and start delimiter
103  os << len << nl << token::BEGIN_LIST << nl;
104 
105  // Write contents
106  for (label i=0; i < len; ++i)
107  {
108  os << list[i] << nl;
109  }
110 
111  // Write end delimiter
113 }
115 
116 } // End namespace Foam
117 
118 
119 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
120 
122 :
123  origin_(Zero),
124  state0_(),
125  state_(),
126  originalIds_(),
127  controllers_(),
128  patchControls_(),
129  relax_(1),
130  ownerId_(-1),
131  forcesDict_(),
132  coupler_(),
133  inputName_("positions.in"),
134  outputName_("forces.out"),
135  logName_("movement.log"),
136  inputFormat_(lumpedPointState::inputFormatType::DICTIONARY),
137  outputFormat_(outputFormatType::DICTIONARY),
138  scaleInput_(-1),
139  scaleOutput_(-1),
140  calcFrequency_(1),
141  lastTrigger_(-1)
142 {}
143 
144 
146 (
147  const dictionary& dict,
148  label ownerId
149 )
150 :
151  origin_(Zero),
152  state0_(),
153  state_(),
154  originalIds_(),
155  controllers_(),
156  patchControls_(),
157  relax_(1),
158  ownerId_(ownerId),
159  forcesDict_(),
160  coupler_(),
161  inputName_("positions.in"),
162  outputName_("forces.out"),
163  logName_("movement.log"),
164  scaleInput_(-1),
165  scaleOutput_(-1),
166  calcFrequency_(1),
167  lastTrigger_(-1)
168 {
169  readDict(dict);
170 }
171 
172 
173 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
174 
176 {
177  return (timeIndex >= lastTrigger_ + calcFrequency_);
178 }
179 
180 
182 {
183  lastTrigger_ = timeIndex;
184 }
185 
186 
188 {
189  origin_ = dict.getOrDefault<point>("origin", Zero);
190 
191  // Initial point locations (zero rotation)
192  auto tpoints0 = tmp<pointField>::New();
193  auto& points0 = tpoints0.ref();
194 
195  dict.readEntry("points", points0);
196  points0 += origin_;
197 
198  originalIds_.clear();
199  controllers_.clear();
200  patchControls_.clear();
201 
202 
203  // The FEA ids for the points (optional)
204  Map<label> pointIdMap;
205 
206  if (dict.readIfPresent("pointLabels", originalIds_) && originalIds_.size())
207  {
208  if (originalIds_.size() != points0.size())
209  {
211  << "Incorrect number of pointLabels. Had "
212  << originalIds_.size() << " for " << points0.size() << " points"
213  << nl << endl
214  << exit(FatalIOError);
215  }
216 
217  labelHashSet duplicates;
218 
219  label pointi = 0;
220 
221  for (const label id : originalIds_)
222  {
223  if (!pointIdMap.insert(id, pointi))
224  {
225  duplicates.set(id);
226  }
227 
228  ++pointi;
229  }
230 
231  if (!duplicates.empty())
232  {
234  << "Found duplicate point ids "
235  << flatOutput(duplicates.sortedToc()) << nl << endl
236  << exit(FatalIOError);
237  }
238  }
239 
240  const dictionary* dictptr = dict.findDict("controllers");
241  if (dictptr)
242  {
243  controllers_ = HashPtrTable<lumpedPointController>(*dictptr);
244 
245  // Verify the input
246  forAllIters(controllers_, iter)
247  {
248  (*iter)->remapPointLabels(points0.size(), pointIdMap);
249  }
250  }
251  else
252  {
253  // Add single global controller
254  // Warning?
255 
256  controllers_.clear();
257  }
258 
259  relax_ = dict.getOrDefault<scalar>("relax", 1);
260  scalarMinMax::zero_one().inplaceClip(relax_);
261 
262  forcesDict_.merge(dict.subOrEmptyDict("forces"));
263 
264  const dictionary& commDict = dict.subDict("communication");
265  coupler_.readDict(commDict);
266 
267  calcFrequency_ = commDict.getOrDefault<label>("calcFrequency", 1);
268 
269  // Leave trigger intact
270 
271  commDict.readEntry("inputName", inputName_);
272  commDict.readEntry("outputName", outputName_);
273  commDict.readIfPresent("logName", logName_);
274 
275  inputFormat_ = lumpedPointState::formatNames.get("inputFormat", commDict);
276  outputFormat_ = formatNames.get("outputFormat", commDict);
277 
278  scaleInput_ = -1;
279  scaleOutput_ = -1;
280 
281  const dictionary* scaleDict = nullptr;
282 
283  if ((scaleDict = commDict.findDict("scaleInput")) != nullptr)
284  {
285  for (int i=0; i < scaleInput_.size(); ++i)
286  {
287  const word& key = scalingNames[scalingType(i)];
288 
289  if
290  (
291  scaleDict->readIfPresent(key, scaleInput_[i])
292  && scaleInput_[i] > 0
293  )
294  {
295  Info<<"Using input " << key << " multiplier: "
296  << scaleInput_[i] << nl;
297  }
298  }
299  }
300 
301  if ((scaleDict = commDict.findDict("scaleOutput")) != nullptr)
302  {
303  for (int i=0; i < scaleOutput_.size(); ++i)
304  {
305  const word& key = scalingNames[scalingType(i)];
306 
307  if
308  (
309  scaleDict->readIfPresent(key, scaleOutput_[i])
310  && scaleOutput_[i] > 0
311  )
312  {
313  Info<<"Using output " << key << " multiplier: "
314  << scaleOutput_[i] << nl;
315  }
316  }
317  }
318 
319  state0_ = lumpedPointState
320  (
321  tpoints0,
322  quaternion::eulerOrderNames.getOrDefault
323  (
324  "rotationOrder",
325  dict,
326  quaternion::eulerOrder::ZXZ
327  ),
328  dict.getOrDefault("degrees", false)
329  );
330 
331  state0_.scalePoints(scaleInput_[scalingType::LENGTH]);
332 
333  state_ = state0_;
334 }
335 
336 
338 (
339  const polyPatch& pp
340 ) const
341 {
342  return hasPatchControl(pp.index());
343 }
344 
345 
347 (
348  const pointPatch& fpatch
349 ) const
350 {
351  return hasInterpolator(fpatch.index());
352 }
353 
354 
356 (
357  const polyPatch& pp
358 ) const
359 {
360  const auto ctrlIter = patchControls_.cfind(pp.index());
361 
362  if (!ctrlIter.good())
363  {
365  << "No controllers for patch " << pp.name()
366  << exit(FatalError);
367  }
368 
369  const patchControl& ctrl = *ctrlIter;
370 
371  for (const word& ctrlName : ctrl.names_)
372  {
373  const auto iter = controllers_.cfind(ctrlName);
374 
375  if (!iter.good())
376  {
378  << "No controller: " << ctrlName << nl
379  << " For patch " << pp.name()
380  << exit(FatalError);
381  }
382  }
383 }
384 
385 
387 (
388  const polyPatch& pp,
389  const wordList& ctrlNames,
390  const pointField& points0
391 )
392 {
393  // Reference mass centres
394  const pointField& lumpedCentres0 = state0().points();
395 
396  const label patchIndex = pp.index();
397 
398  // Info<<"Add patch control for patch " << patchIndex << " "
399  // << pp.name() << nl;
400 
401  patchControl& ctrl = patchControls_(patchIndex);
402  ctrl.names_ = ctrlNames;
403 
404  labelList& faceToPoint = ctrl.faceToPoint_;
405  faceToPoint.resize(pp.size(), -1);
406 
407  checkPatchControl(pp);
408 
409  const faceList& faces = pp.boundaryMesh().mesh().faces();
410 
411  // Subset of points to search (if specified)
412  labelHashSet subsetPointIds;
413 
414  for (const word& ctrlName : ctrl.names_)
415  {
416  const auto iter = controllers_.cfind(ctrlName);
417 
418  if (!iter.good())
419  {
421  << "No controller: " << ctrlName << nl
422  << exit(FatalError);
423  }
424 
425  const labelList& pointLabels = (*iter)->pointLabels();
426 
427  subsetPointIds.insert(pointLabels);
428  }
429 
430  if (ctrl.names_.size() && subsetPointIds.empty())
431  {
433  << "Controllers specified, but without any points" << nl
434  << exit(FatalError);
435  }
436 
437 
438  treeDataPoint treePoints
439  (
440  lumpedCentres0,
441  subsetPointIds.sortedToc(),
442  subsetPointIds.size()
443  );
444 
445 
446  treeBoundBox bb(lumpedCentres0);
447  bb.inflate(0.01);
448 
450  (
451  treePoints,
452  bb, // overall search domain
453  8, // maxLevel
454  10, // leafsize
455  3.0 // duplicity
456  );
457 
458  const scalar searchDistSqr(sqr(GREAT));
459 
460  const label patchStart = pp.start();
461  forAll(pp, patchFacei)
462  {
463  const point fc(faces[patchStart + patchFacei].centre(points0));
464 
465  // Store the original pointId, not subset id
466  faceToPoint[patchFacei] =
467  treePoints.pointLabel
468  (
469  ppTree.findNearest(fc, searchDistSqr).index()
470  );
471  }
472 
473  if (debug)
474  {
475  Pout<<"Added face mapping for patch: " << patchIndex << endl;
476  }
477 }
478 
479 
481 (
482  const pointPatch& fpatch,
483  const pointField& points0
484 )
485 {
486  // Reference mass centres
487  const pointField& lumpedCentres0 = state0().points();
488 
489  const label patchIndex = fpatch.index();
490 
491  patchControl& ctrl = patchControls_(patchIndex);
492 
493  List<lumpedPointInterpolator>& interpList = ctrl.interp_;
494  interpList.clear();
495 
496  // The connectivity, adjacency list
497  Map<labelHashSet> adjacency;
498 
499  // Subset of points to search (if specified)
500  labelHashSet subsetPointIds;
501 
502  for (const word& ctrlName : ctrl.names_)
503  {
504  const auto iter = controllers_.cfind(ctrlName);
505 
506  if (!iter.good())
507  {
509  << "No controller: " << ctrlName << nl
510  << exit(FatalError);
511  }
512 
513  const labelList& pointLabels = (*iter)->pointLabels();
514 
515  subsetPointIds.insert(pointLabels);
516 
517  // Adjacency lists
518  forAll(pointLabels, i)
519  {
520  const label curr = pointLabels[i];
521 
522  if (i)
523  {
524  const label prev = pointLabels[i-1];
525  adjacency(prev).insert(curr);
526  adjacency(curr).insert(prev);
527  }
528  else if (!adjacency.found(curr))
529  {
530  adjacency(curr).clear();
531  }
532  }
533  }
534 
535  if (ctrl.names_.empty())
536  {
537  // Adjacency lists
538  const label len = state0().size();
539 
540  for (label i=0; i < len; ++i)
541  {
542  const label curr = i;
543 
544  if (i)
545  {
546  const label prev = i-1;
547  adjacency(prev).insert(curr);
548  adjacency(curr).insert(prev);
549  }
550  else if (!adjacency.found(curr))
551  {
552  adjacency(curr).clear();
553  }
554  }
555  }
556 
557  if (ctrl.names_.size() && subsetPointIds.empty())
558  {
560  << "Controllers specified, but without any points" << nl
561  << exit(FatalError);
562  }
563 
564 
565  // Pairs defining connecting points as triangles
566  Map<labelPairList> adjacencyPairs;
567 
568  barycentric2D bary;
569 
570  {
571  // Pairs for the ends
573 
574  // Mag sin(angle) around the triangle point 0,
575  // used to sort the generated triangles according to the acute angle
576  DynamicList<scalar> acuteAngles;
577 
578  forAllConstIters(adjacency, iter)
579  {
580  const label nearest = iter.key();
581 
582  labelList neighbours(iter.val().sortedToc());
583 
584  const label len = neighbours.size();
585 
586  pairs.clear();
587  acuteAngles.clear();
588 
589  const point& nearPt = lumpedCentres0[nearest];
590 
591  for (label j=1; j < len; ++j)
592  {
593  for (label i=0; i < j; ++i)
594  {
595  labelPair neiPair(neighbours[i], neighbours[j]);
596 
597  triPointRef tri
598  (
599  nearPt,
600  lumpedCentres0[neiPair.first()],
601  lumpedCentres0[neiPair.second()]
602  );
603 
604  // Require non-degenerate triangles
605  if (tri.pointToBarycentric(tri.a(), bary) > SMALL)
606  {
607  // Triangle OK
608  pairs.append(neiPair);
609 
610  vector ab(normalised(tri.b() - tri.a()));
611  vector ac(normalised(tri.c() - tri.a()));
612 
613  // Angle between neighbouring edges
614  // Use negative cosine to map [0-180] -> [-1 .. +1]
615 
616  acuteAngles.append(-(ab & ac));
617  }
618  }
619  }
620 
621  if (pairs.size() > 1)
622  {
623  // Sort by acute angle
624  labelList order(sortedOrder(acuteAngles));
625  inplaceReorder(order, pairs);
626  }
627 
628  adjacencyPairs.insert(nearest, pairs);
629  }
630  }
631 
632  if (debug & 2)
633  {
634  Info<< "Adjacency table for patch: " << fpatch.name() << nl;
635 
636  for (const label own : adjacency.sortedToc())
637  {
638  Info<< own << " =>";
639  for (const label nei : adjacency[own].sortedToc())
640  {
641  Info<< ' ' << nei;
642  }
643 
644  if (originalIds_.size())
645  {
646  Info<< " # " << originalIds_[own] << " =>";
647  for (const label nei : adjacency[own].sortedToc())
648  {
649  Info<< ' ' << originalIds_[nei];
650  }
651  }
652 
653  Info<< " # tri " << flatOutput(adjacencyPairs[own]);
654  Info<< nl;
655  }
656  }
657 
658  treeDataPoint treePoints
659  (
660  lumpedCentres0,
661  subsetPointIds.sortedToc(),
662  subsetPointIds.size()
663  );
664 
665  treeBoundBox bb(lumpedCentres0);
666  bb.inflate(0.01);
667 
669  (
670  treePoints,
671  bb, // overall search domain
672  8, // maxLevel
673  10, // leafsize
674  3.0 // duplicity
675  );
676 
677 
678  // Searching
679 
680  const scalar searchDistSqr(sqr(GREAT));
681 
682  const labelList& meshPoints = fpatch.meshPoints();
683 
684  interpList.resize(meshPoints.size());
685 
686  DynamicList<scalar> unsortedNeiWeightDist;
687  DynamicList<label> unsortedNeighbours;
688 
689  forAll(meshPoints, pointi)
690  {
691  const point& ptOnMesh = points0[meshPoints[pointi]];
692 
693  // Nearest (original) point id
694  const label nearest =
695  treePoints.pointLabel
696  (
697  ppTree.findNearest(ptOnMesh, searchDistSqr).index()
698  );
699 
700  interpList[pointi].nearest(nearest);
701 
702  if (nearest == -1)
703  {
704  // Should not really happen
705  continue;
706  }
707 
708  // Have the nearest lumped point, now find the next nearest
709  // but check that the direction is also correct.
710 
711  // OK: within the 0-1 bounds
712  // 1+----+0
713  // .
714  // .
715  // +pt
716 
717  const point& nearPt = lumpedCentres0[nearest];
718 
719  const linePointRef toMeshPt(nearPt, ptOnMesh);
720 
721  const labelPairList& adjacentPairs = adjacencyPairs[nearest];
722 
723  unsortedNeighbours = adjacency[nearest].toc();
724  unsortedNeiWeightDist.resize(unsortedNeighbours.size());
725 
726  forAll(unsortedNeighbours, nbri)
727  {
728  unsortedNeiWeightDist[nbri] =
729  magSqr(ptOnMesh - lumpedCentres0[unsortedNeighbours[nbri]]);
730  }
731 
732  // Sort by distance
733  labelList distOrder(sortedOrder(unsortedNeiWeightDist));
734 
735  label ngood = 0;
736 
737  // Recalculate distance as weighting
738  for (const label nbri : distOrder)
739  {
740  const label nextPointi = unsortedNeighbours[nbri];
741 
742  const point& nextPt = lumpedCentres0[nextPointi];
743 
744  const linePointRef toNextPt(nearPt, nextPt);
745 
746  const scalar weight =
747  (toMeshPt.vec() & toNextPt.unitVec()) / toNextPt.mag();
748 
749  if (weight < 0)
750  {
751  // Reject: wrong direction or other bad value
752  continue;
753  }
754  else
755  {
756  // Store weight
757  unsortedNeiWeightDist[nbri] = weight;
758 
759  // Retain good weight
760  distOrder[ngood] = nbri;
761  ++ngood;
762  }
763  }
764 
765  distOrder.resize(ngood);
766 
767  if (distOrder.size() < 1)
768  {
769  continue;
770  }
771 
772  UIndirectList<label> neighbours(unsortedNeighbours, distOrder);
773  UIndirectList<scalar> neiWeight(unsortedNeiWeightDist, distOrder);
774 
775  bool useFirst = true;
776 
777  if (neighbours.size() > 1 && adjacentPairs.size())
778  {
779  // Check for best two neighbours
780 
781  bitSet neiPointid;
782  neiPointid.set(neighbours);
783 
784  for (const labelPair& ends : adjacentPairs)
785  {
786  label nei1 = ends.first();
787  label nei2 = ends.second();
788 
789  if (!neiPointid.test(nei1) || !neiPointid.test(nei2))
790  {
791  // Reject, invalid combination for this point location
792  continue;
793  }
794  else if (neighbours.find(nei2) < neighbours.find(nei1))
795  {
796  // Order by distance, which is not really needed,
797  // but helps with diagnostics
798  std::swap(nei1, nei2);
799  }
800 
801 
802  triFace triF(nearest, nei1, nei2);
803 
804  if
805  (
806  triF.tri(lumpedCentres0).pointToBarycentric(ptOnMesh, bary)
807  > SMALL
808  && !bary.outside()
809  )
810  {
811  // Use barycentric weights
812  interpList[pointi].set(triF, bary);
813 
814  useFirst = false;
815  break;
816  }
817  }
818  }
819 
820  if (useFirst)
821  {
822  // Use geometrically closest neighbour
823  interpList[pointi].next(neighbours.first(), neiWeight.first());
824  }
825  }
826 }
827 
828 
830 (
831  const polyMesh& pmesh
832 ) const
833 {
834  const label nLumpedPoints = state0().size();
835 
836  List<scalar> zoneAreas(nLumpedPoints, Zero);
837 
838  if (patchControls_.empty())
839  {
841  << "Attempted to calculate areas without setMapping()"
842  << nl << endl;
843  return zoneAreas;
844  }
845 
846  const polyBoundaryMesh& patches = pmesh.boundaryMesh();
847 
848  // fvMesh and has pressure field
849  if (isA<fvMesh>(pmesh))
850  {
851  const fvMesh& mesh = dynamicCast<const fvMesh>(pmesh);
852 
853  // Face areas (on patches)
854  const surfaceVectorField::Boundary& patchSf =
855  mesh.Sf().boundaryField();
856 
857  forAllConstIters(patchControls_, iter)
858  {
859  const label patchIndex = iter.key();
860  const patchControl& ctrl = iter.val();
861 
862  const labelList& faceToPoint = ctrl.faceToPoint_;
863 
864  const polyPatch& pp = patches[patchIndex];
865 
866  forAll(pp, patchFacei)
867  {
868  // Force from the patch-face into sum
869  const label pointIndex = faceToPoint[patchFacei];
870 
871  if (pointIndex < 0)
872  {
873  // Unmapped, for whatever reason?
874  continue;
875  }
876 
877  // Force from the patch-face into sum
878  zoneAreas[pointIndex] += mag(patchSf[patchIndex][patchFacei]);
879  }
880  }
881  }
882 
884  Pstream::listCombineScatter(zoneAreas);
885 
886  return zoneAreas;
887 }
888 
889 
891 (
892  const polyMesh& pmesh,
893  List<vector>& forces,
894  List<vector>& moments
895 ) const
896 {
897  const label nLumpedPoints = state0().size();
898 
899  forces.resize(nLumpedPoints);
900  moments.resize(nLumpedPoints);
901 
902  if (patchControls_.empty())
903  {
905  << "Attempted to calculate forces without setMapping()"
906  << nl << endl;
907 
908  forces.resize(nLumpedPoints, Zero);
909  moments.resize(nLumpedPoints, Zero);
910  return false;
911  }
912 
913  // Initialize with zero
914  forces = Zero;
915  moments = Zero;
916 
917  // Current mass centres
918  const pointField& lumpedCentres = state().points();
919 
920  const polyBoundaryMesh& patches = pmesh.boundaryMesh();
921 
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);
925 
926 
927  // Calculated force per patch - cache
928  PtrMap<vectorField> forceOnPatches;
929 
930  const volScalarField* pPtr = pmesh.findObject<volScalarField>(pName);
931 
932  // fvMesh and has pressure field
933  if (isA<fvMesh>(pmesh) && pPtr)
934  {
935  const fvMesh& mesh = dynamicCast<const fvMesh>(pmesh);
936  const volScalarField& p = *pPtr;
937 
938  // Face centres (on patches)
939  const surfaceVectorField::Boundary& patchCf = mesh.Cf().boundaryField();
940 
941  // Face areas (on patches)
942  const surfaceVectorField::Boundary& patchSf = mesh.Sf().boundaryField();
943 
944  // Pressure (on patches)
945  const volScalarField::Boundary& patchPress = p.boundaryField();
946 
947  // rhoRef if the pressure field is dynamic, i.e. p/rho otherwise 1
948  rhoRef = (p.dimensions() == dimPressure ? 1.0 : rhoRef);
949 
950  // Scale pRef by density for incompressible simulations
951  pRef /= rhoRef;
952 
953  forAllConstIters(patchControls_, iter)
954  {
955  const label patchIndex = iter.key();
956  const patchControl& ctrl = iter.val();
957 
958  const labelList& faceToPoint = ctrl.faceToPoint_;
959 
960  if (!forceOnPatches.found(patchIndex))
961  {
962  // Patch faces are +ve outwards,
963  // so the forces (exerted by fluid on solid)
964  // already have the correct sign
965  forceOnPatches.set
966  (
967  patchIndex,
968  (
969  rhoRef
970  * patchSf[patchIndex] * (patchPress[patchIndex] - pRef)
971  ).ptr()
972  );
973  }
974 
975  const vectorField& forceOnPatch = *forceOnPatches[patchIndex];
976 
977  const polyPatch& pp = patches[patchIndex];
978 
979  forAll(pp, patchFacei)
980  {
981  // Force from the patch-face into sum
982  const label pointIndex = faceToPoint[patchFacei];
983 
984  if (pointIndex < 0)
985  {
986  // Unmapped, for whatever reason?
987  continue;
988  }
989 
990  // Force from the patch-face into sum
991  forces[pointIndex] += forceOnPatch[patchFacei];
992 
993  // Effective torque arm:
994  // - translated into the lumped-points coordinate system
995  // prior to determining the distance
996  const vector lever
997  (
998  patchCf[patchIndex][patchFacei]
999  - lumpedCentres[pointIndex]
1000  );
1001 
1002  // Moment from the patch-face into sum
1003  moments[pointIndex] += lever ^ forceOnPatch[patchFacei];
1004  }
1005  }
1006  }
1007  else
1008  {
1009  Info<<"No pressure field" << endl;
1010  }
1011 
1014 
1016  Pstream::listCombineScatter(moments);
1017 
1018  return true;
1019 }
1020 
1021 
1025  const pointPatch& fpatch,
1026  const pointField& points0
1027 ) const
1028 {
1029  return pointsDisplacement(state(), fpatch, points0);
1030 }
1031 
1032 
1036  const lumpedPointState& state,
1037  const pointPatch& fpatch,
1038  const pointField& points0
1039 ) const
1040 {
1041  const label patchIndex = fpatch.index();
1042 
1043  // Reference mass centres
1044  const pointField& lumpedCentres0 = state0().points();
1045 
1046  // Current mass centres
1047  const pointField& lumpedCentres = state.points();
1048 
1049  // The local-to-global transformation tensor
1050  const tensorField& localToGlobal = state.rotations();
1051 
1052  const labelList& meshPoints = fpatch.meshPoints();
1053 
1054  // Could also verify the sizes (state vs original)
1055 
1056  auto tdisp = tmp<pointField>::New(fpatch.size());
1057  auto& disp = tdisp.ref();
1058 
1059  // The interpolator
1060  const List<lumpedPointInterpolator>& interpList
1061  = patchControls_[patchIndex].interp_;
1062 
1063  forAll(meshPoints, pointi)
1064  {
1065  const lumpedPointInterpolator& interp = interpList[pointi];
1066 
1067  const point& p0 = points0[meshPoints[pointi]];
1068 
1069  const vector origin0 = interp.interpolate(lumpedCentres0);
1070  const vector origin = interp.interpolate(lumpedCentres);
1071  const tensor rotTensor = interp.interpolate(localToGlobal);
1072 
1073  disp[pointi] = (rotTensor & (p0 - origin0)) + origin - p0;
1074  }
1075 
1076  return tdisp;
1077 }
1078 
1079 
1083  const lumpedPointState& state,
1084  const pointPatch& fpatch,
1085  const pointField& points0
1086 ) const
1087 {
1088  const label patchIndex = fpatch.index();
1089 
1090  // Reference mass centres
1091  const pointField& lumpedCentres0 = state0().points();
1092 
1093  // Current mass centres
1094  const pointField& lumpedCentres = state.points();
1095 
1096  // The local-to-global transformation tensor
1097  const tensorField& localToGlobal = state.rotations();
1098 
1099  const labelList& meshPoints = fpatch.meshPoints();
1100 
1101  // Could also verify the sizes (state vs original)
1102 
1103  auto tdisp = tmp<pointField>::New(fpatch.size());
1104  auto& disp = tdisp.ref();
1105 
1106  // The interpolator
1107  const List<lumpedPointInterpolator>& interpList =
1108  patchControls_[patchIndex].interp_;
1109 
1110  forAll(meshPoints, pointi)
1111  {
1112  const lumpedPointInterpolator& interp = interpList[pointi];
1113 
1114  const point& p0 = points0[meshPoints[pointi]];
1115 
1116  const vector origin0 = interp.interpolate(lumpedCentres0);
1117  const vector origin = interp.interpolate(lumpedCentres);
1118  const tensor rotTensor = interp.interpolate(localToGlobal);
1119 
1120  disp[pointi] = (rotTensor & (p0 - origin0)) + origin;
1121  }
1122 
1123  return tdisp;
1124 }
1125 
1126 
1128 {
1129  // os.writeEntry("axis", axis_);
1130  // os.writeEntry("locations", locations_);
1131 }
1132 
1133 
1135 {
1136  lumpedPointState prev = state_;
1137 
1138  const bool status = state_.readData
1139  (
1140  inputFormat_,
1141  coupler().resolveFile(inputName_),
1142  state0().rotationOrder(),
1143  state0().degrees()
1144  );
1145 
1146  scalePoints(state_);
1147 
1148  state_.relax(relax_, prev);
1149 
1150  return status;
1151 }
1152 
1153 
1156  Ostream& os,
1157  const UList<vector>& forces,
1158  const UList<vector>& moments,
1159  const outputFormatType fmt,
1160  const Tuple2<scalar, scalar>* timesWritten
1161 ) const
1162 {
1163  const bool writeMoments = (moments.size() == forces.size());
1164 
1165  if (fmt == outputFormatType::PLAIN)
1166  {
1167  os <<"########" << nl;
1168  if (timesWritten)
1169  {
1170  os << "# Time value=" << timesWritten->first() << nl
1171  << "# Time prev=" << timesWritten->second() << nl;
1172  }
1173  os << "# size=" << this->size() << nl
1174  << "# columns (points) (forces)";
1175 
1176  if (writeMoments)
1177  {
1178  os << " (moments)";
1179  }
1180 
1181  os << nl;
1182 
1183  bool report = false;
1184  scalar scaleLength = scaleOutput_[scalingType::LENGTH];
1185  scalar scaleForce = scaleOutput_[scalingType::FORCE];
1186  scalar scaleMoment = scaleOutput_[scalingType::MOMENT];
1187 
1188  if (scaleLength > 0)
1189  {
1190  report = true;
1191  }
1192  else
1193  {
1194  scaleLength = 1.0;
1195  }
1196 
1197  if (scaleForce > 0)
1198  {
1199  report = true;
1200  }
1201  else
1202  {
1203  scaleForce = 1.0;
1204  }
1205 
1206  if (writeMoments)
1207  {
1208  if (scaleMoment > 0)
1209  {
1210  report = true;
1211  }
1212  else
1213  {
1214  scaleMoment = 1.0;
1215  }
1216  }
1217 
1218  if (report)
1219  {
1220  os <<"# scaling points=" << scaleLength
1221  <<" forces=" << scaleForce;
1222 
1223  if (writeMoments)
1224  {
1225  os <<" moments=" << scaleMoment;
1226  }
1227 
1228  os << nl;
1229  }
1230 
1231  os <<"########" << nl;
1232 
1233  forAll(state0().points(), i)
1234  {
1235  const point& pt = state0().points()[i];
1236 
1237  putPlain(os, scaleLength * pt) << ' ';
1238 
1239  if (i < forces.size())
1240  {
1241  const vector val(scaleForce * forces[i]);
1242  putPlain(os, val);
1243  }
1244  else
1245  {
1246  putPlain(os, vector::zero);
1247  }
1248 
1249  if (writeMoments)
1250  {
1251  os << ' ';
1252  if (i < moments.size())
1253  {
1254  const vector val(scaleMoment * moments[i]);
1255  putPlain(os, val);
1256  }
1257  else
1258  {
1259  putPlain(os, vector::zero);
1260  }
1261  }
1262 
1263  os << nl;
1264  }
1265  }
1266  else
1267  {
1268  // Make it easier for external programs to parse
1269  // - exclude the usual OpenFOAM 'FoamFile' header
1270  // - ensure lists have consistent format
1271 
1272  os <<"////////" << nl;
1273  if (timesWritten)
1274  {
1275  os.writeEntry("time", timesWritten->first());
1276  os.writeEntry("prevTime", timesWritten->second());
1277  }
1278  os << nl;
1279 
1280  writeList(os, "points", state0().points());
1281  writeList(os, "forces", forces);
1282 
1283  if (writeMoments)
1284  {
1285  writeList(os, "moments", moments);
1286  }
1287  }
1288 
1289  return true;
1290 }
1291 
1292 
1295  const UList<vector>& forces,
1296  const UList<vector>& moments,
1297  const Tuple2<scalar, scalar>* timesWritten
1298 ) const
1299 {
1300  if (!Pstream::master())
1301  {
1302  return false;
1303  }
1304 
1305  // Regular output
1306  {
1307  OFstream os
1308  (
1309  coupler().resolveFile(outputName_)
1310  );
1311 
1312  writeData(os, forces, moments, outputFormat_, timesWritten);
1313  }
1314 
1315  // Log output
1316  {
1317  OFstream os
1318  (
1319  coupler().resolveFile(logName_),
1320  IOstreamOption(),
1321  true // append
1322  );
1323 
1324  writeData(os, forces, moments, outputFormatType::PLAIN, timesWritten);
1325  }
1326 
1327  return true;
1328 }
1329 
1330 
1331 // ************************************************************************* //
Foam::expressions::patchExpr::debug
int debug
Static debugging option.
Foam::Pair::second
const T & second() const noexcept
Return second element, which is also the last element.
Definition: PairI.H:122
Foam::dictionary::findDict
dictionary * findDict(const word &keyword, enum keyType::option matchOpt=keyType::REGEX)
Find and return a sub-dictionary pointer if present.
Definition: dictionaryI.H:127
volFields.H
Foam::DynamicList::resize
void resize(const label len)
Definition: DynamicListI.H:353
Foam::dimPressure
const dimensionSet dimPressure
Foam::Tensor< scalar >
Foam::pointPatch::index
virtual label index() const =0
Return the index of this patch in the pointBoundaryMesh.
p
volScalarField & p
Definition: createFieldRefs.H:8
Foam::lumpedPointMovement::writeDict
void writeDict(Ostream &os) const
Write axis, locations, division as a dictionary.
Definition: lumpedPointMovement.C:1127
Foam::Enum
Enum is a wrapper around a list of names/values that represent particular enumeration (or int) values...
Definition: IOstreamOption.H:57
pointIndexHit.H
Foam::word
A class for handling words, derived from Foam::string.
Definition: word.H:65
Foam::bitSet
A bitSet stores bits (elements with only two states) in packed internal format and supports a variety...
Definition: bitSet.H:63
Foam::List::resize
void resize(const label len)
Adjust allocated size of list.
Definition: ListI.H:139
Foam::polyBoundaryMesh
A polyBoundaryMesh is a polyPatch list with additional search methods and registered IO.
Definition: polyBoundaryMesh.H:63
Foam::lumpedPointMovement::forcesAndMoments
bool forcesAndMoments(const polyMesh &pmesh, List< vector > &forces, List< vector > &moments) const
The forces and moments acting on each pressure-zone.
Definition: lumpedPointMovement.C:891
Foam::lumpedPointMovement::scalingNames
static const Enum< scalingType > scalingNames
Names for the scaling types.
Definition: lumpedPointMovement.H:297
Foam::lumpedPointInterpolator::interpolate
T interpolate(const UList< T > &input) const
Linear interpolated value between nearest and next locations.
Definition: lumpedPointInterpolatorI.H:170
Foam::lumpedPointMovement::writeData
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.
Definition: lumpedPointMovement.C:1155
Foam::lumpedPointMovement::readDict
void readDict(const dictionary &dict)
Update settings from dictionary.
Definition: lumpedPointMovement.C:187
Foam::tmp
A class for managing temporary objects.
Definition: PtrList.H:61
Foam::Zero
static constexpr const zero Zero
Global zero (0)
Definition: zero.H:131
Foam::DynamicList
A 1D vector of objects of type <T> that resizes itself as necessary to accept the new objects.
Definition: DynamicList.H:55
Foam::debug::debugSwitch
int debugSwitch(const char *name, const int deflt=0)
Lookup debug switch or add default value.
Definition: debug.C:225
Foam::treeBoundBox
Standard boundBox with extra functionality for use in octree.
Definition: treeBoundBox.H:86
indexedOctree.H
Foam::lumpedPointMovement::areas
List< scalar > areas(const polyMesh &pmesh) const
The areas for each pressure-zone.
Definition: lumpedPointMovement.C:830
Foam::glTF::key
auto key(const Type &t) -> typename std::enable_if< std::is_enum< Type >::value, typename std::underlying_type< Type >::type >::type
Definition: foamGltfBase.H:108
Foam::Barycentric2D
Templated 2D Barycentric derived from VectorSpace. Has 3 components, one of which is redundant.
Definition: Barycentric2D.H:54
Foam::bitSet::set
void set(const bitSet &bitset)
Set specified bits from another bitset.
Definition: bitSetI.H:574
Foam::Map< label >
Foam::UPstream::master
static bool master(const label communicator=worldComm)
Am I the master process.
Definition: UPstream.H:457
Foam::FatalIOError
IOerror FatalIOError
Foam::polyMesh::boundaryMesh
const polyBoundaryMesh & boundaryMesh() const
Return boundary mesh.
Definition: polyMesh.H:444
Foam::lumpedPointState::points
const pointField & points() const
The points corresponding to mass centres.
Definition: lumpedPointStateI.H:46
Foam::endl
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:369
surfaceFields.H
Foam::surfaceFields.
Foam::lumpedPointMovement::scalingType
scalingType
Output format types.
Definition: lumpedPointMovement.H:283
Foam::pointPatch
Basic pointPatch represents a set of points from the mesh.
Definition: pointPatch.H:58
Foam::Pout
prefixOSstream Pout
OSstream wrapped stdout (std::cout) with parallel prefix.
triFace.H
Foam::Enum::get
EnumType get(const word &enumName) const
The enumeration corresponding to the given name.
Definition: Enum.C:75
Foam::bitSet::test
bool test(const label pos) const
Test value at specified position, never auto-vivify entries.
Definition: bitSetI.H:520
Foam::HashSet< label, Hash< label > >
Foam::DynamicList::clear
void clear() noexcept
Clear the addressed list, i.e. set the size to zero.
Definition: DynamicListI.H:391
Foam::triFace::tri
triPointRef tri(const UList< point > &points) const
Return the triangle.
Definition: triFaceI.H:165
Foam::polyMesh
Mesh consisting of general polyhedral cells.
Definition: polyMesh.H:77
Foam::treeDataPoint
Holds (reference to) pointField. Encapsulation of data needed for octree searches....
Definition: treeDataPoint.H:62
forAll
#define forAll(list, i)
Loop across all elements in list.
Definition: stdFoam.H:296
Foam::lumpedPointMovement::hasInterpolator
bool hasInterpolator(const pointPatch &fpatch) const
Check if patch control exists for specified patch.
Definition: lumpedPointMovement.C:347
Foam::magSqr
dimensioned< typename typeOfMag< Type >::type > magSqr(const dimensioned< Type > &dt)
Foam::lumpedPointState::readData
bool readData(Istream &is, const quaternion::eulerOrder rotOrder=quaternion::eulerOrder::ZXZ, const bool degrees=false)
Read input as dictionary content.
Definition: lumpedPointState.C:320
Foam::Barycentric2D::outside
bool outside() const
True if any coordinates are negative.
Definition: Barycentric2DI.H:97
Foam::lumpedPointMovement::couplingPending
bool couplingPending(const label timeIndex) const
Check if coupling is pending (according to the calcFrequency)
Definition: lumpedPointMovement.C:175
Foam::triangle
A triangle primitive used to calculate face normals and swept volumes.
Definition: triangle.H:59
Foam::lumpedPointState
The state of lumped points corresponds to positions and rotations.
Definition: lumpedPointState.H:112
Foam::lumpedPointState::scalePoints
void scalePoints(const scalar scaleFactor)
Scale points by given factor.
Definition: lumpedPointState.C:236
Foam::polyBoundaryMesh::mesh
const polyMesh & mesh() const noexcept
Return the mesh reference.
Definition: polyBoundaryMesh.H:152
Foam::Field< vector >
treeDataPoint.H
Foam::polyPatch::boundaryMesh
const polyBoundaryMesh & boundaryMesh() const
Return boundaryMesh reference.
Definition: polyPatch.C:315
Foam::lumpedPointState::formatNames
static const Enum< inputFormatType > formatNames
Names for the input format types.
Definition: lumpedPointState.H:129
Foam::Info
messageStream Info
Information stream (stdout output on master, null elsewhere)
Foam::lumpedPointMovement::debug
static int debug
Debug switch.
Definition: lumpedPointMovement.H:382
Foam::polyPatch
A patch is a list of labels that address the faces in the global face list.
Definition: polyPatch.H:68
Foam::DynamicList::append
DynamicList< T, SizeMin > & append(const T &val)
Append an element to the end of this list.
Definition: DynamicListI.H:511
Foam::MinMax::zero_one
static MinMax< T > zero_one()
A 0-1 range corresponding to the pTraits zero, one.
Definition: MinMaxI.H:45
Foam::dictionary::subDict
const dictionary & subDict(const word &keyword, enum keyType::option matchOpt=keyType::REGEX) const
Find and return a sub-dictionary.
Definition: dictionary.C:460
Foam::IOstreamOption
The IOstreamOption is a simple container for options an IOstream can normally have.
Definition: IOstreamOption.H:63
Foam::indexedOctree
Non-pointer based hierarchical recursive searching.
Definition: treeDataEdge.H:50
Foam::dictionary::readEntry
bool readEntry(const word &keyword, T &val, enum keyType::option matchOpt=keyType::REGEX, bool mandatory=true) const
Definition: dictionaryTemplates.C:302
Foam::vtk::writeList
void writeList(vtk::formatter &fmt, const UList< uint8_t > &values)
Write a list of uint8_t values.
Definition: foamVtkOutput.C:112
Foam::token::END_STATEMENT
End entry [isseparator].
Definition: token.H:154
Foam::line::mag
scalar mag() const
Return scalar magnitude.
Definition: lineI.H:105
Foam::line::unitVec
Point unitVec() const
Return the unit vector (start-to-end)
Definition: lineI.H:119
forAllIters
#define forAllIters(container, iter)
Iterate across all elements in the container object.
Definition: stdFoam.H:223
PtrMap.H
dict
dictionary dict
Definition: searchingEngine.H:14
Foam::writeData
static void writeData(Ostream &os, const Type &val)
Definition: rawSurfaceWriterImpl.C:45
Foam::FatalError
error FatalError
Foam::dictionary
A list of keyword definitions, which are a keyword followed by a number of values (eg,...
Definition: dictionary.H:123
Foam::lumpedPointMovement::canonicalName
static const word canonicalName
The canonical name ("lumpedPointMovement") for the dictionary.
Definition: lumpedPointMovement.H:385
Foam::lumpedPointMovement::formatNames
static const Enum< outputFormatType > formatNames
Names for the output format types.
Definition: lumpedPointMovement.H:294
os
OBJstream os(runTime.globalPath()/outputName)
Foam::lumpedPointMovement::readState
bool readState()
Read state from file, applying relaxation as requested.
Definition: lumpedPointMovement.C:1134
mesh
dynamicFvMesh & mesh
Definition: createDynamicFvMesh.H:6
Foam::fvMesh
Mesh data needed to do the Finite Volume discretisation.
Definition: fvMesh.H:85
Foam
Namespace for OpenFOAM.
Definition: atmBoundaryLayer.C:33
Foam::flatOutput
FlatOutput::OutputAdaptor< Container, Delimiters > flatOutput(const Container &obj, Delimiters delim)
Global flatOutput() function with specified output delimiters.
Definition: FlatOutput.H:216
Foam::patchIdentifier::index
label index() const noexcept
The index of this patch in the boundaryMesh.
Definition: patchIdentifier.H:147
Foam::pointPatch::name
virtual const word & name() const =0
Return name.
Foam::vector
Vector< scalar > vector
A scalar version of the templated Vector.
Definition: vector.H:51
Foam::polyPatch::start
label start() const
Return start label of this patch in the polyMesh face list.
Definition: polyPatch.H:361
PstreamReduceOps.H
Inter-processor communication reduction functions.
lumpedPointIOMovement.H
Foam::dictionary::subOrEmptyDict
dictionary subOrEmptyDict(const word &keyword, enum keyType::option matchOpt=keyType::REGEX, const bool mandatory=false) const
Definition: dictionary.C:540
Foam::exit
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:130
Foam::OFstream
Output to file stream, using an OSstream.
Definition: OFstream.H:53
Foam::pointPatch::size
virtual label size() const =0
Return size.
Foam::lumpedPointMovement::pointsPosition
tmp< pointField > pointsPosition(const lumpedPointState &state, const pointPatch &fpatch, const pointField &points0) const
The points absolute position according to specified state.
Definition: lumpedPointMovement.C:1082
Foam::normalised
VectorSpace< Form, Cmpt, Ncmpts > normalised(const VectorSpace< Form, Cmpt, Ncmpts > &vs)
Definition: VectorSpaceI.H:487
Foam::Pstream::listCombineGather
static void listCombineGather(const List< commsStruct > &comms, List< T > &Value, const CombineOp &cop, const int tag, const label comm)
Definition: combineGatherScatter.C:290
points0
pointField points0(pointIOField(IOobject("points", mesh.time().constant(), polyMesh::meshSubDir, mesh, IOobject::MUST_READ, IOobject::NO_WRITE, false)))
Foam::quaternion::eulerOrderNames
static const Enum< eulerOrder > eulerOrderNames
The names for Euler-angle rotation order.
Definition: quaternion.H:112
Foam::polyMesh::faces
virtual const faceList & faces() const
Return raw faces.
Definition: polyMesh.C:1094
FatalErrorInFunction
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:453
Foam::sqr
dimensionedSymmTensor sqr(const dimensionedVector &dv)
Definition: dimensionedSymmTensor.C:51
Foam::objectRegistry::findObject
const Type * findObject(const word &name, const bool recursive=false) const
Return const pointer to the object of the given Type.
Definition: objectRegistryTemplates.C:401
Foam::nl
constexpr char nl
Definition: Ostream.H:404
Foam::Pair< label >
forAllConstIters
forAllConstIters(mixture.phases(), phase)
Definition: pEqn.H:28
Foam::triFace
A triangular face using a FixedList of labels corresponding to mesh vertices.
Definition: triFace.H:69
Fstream.H
Foam::HashPtrTable
A HashTable of pointers to objects of type <T>, with deallocation management of the pointers.
Definition: HashPtrTable.H:54
Foam::lumpedPointMovement::outputFormatType
outputFormatType
Output format types.
Definition: lumpedPointMovement.H:276
Foam::lumpedPointMovement::hasPatchControl
bool hasPatchControl(const label patchIndex) const
Check if patch control exists for specified patch.
Definition: lumpedPointMovementI.H:53
Foam::Vector< scalar >
Foam::pointPatch::meshPoints
virtual const labelList & meshPoints() const =0
Return mesh points.
Foam::lumpedPointMovement::setPatchControl
void setPatchControl(const polyPatch &pp, const wordList &ctrlNames, const pointField &points0)
Define pressure-zones mapping for faces in the specified patches.
Definition: lumpedPointMovement.C:387
Foam::List< word >
Foam::lumpedPointMovement::pointsDisplacement
tmp< pointField > pointsDisplacement(const pointPatch &fpatch, const pointField &points0) const
Displace points according to the current state.
Definition: lumpedPointMovement.C:1024
Foam::mag
dimensioned< typename typeOfMag< Type >::type > mag(const dimensioned< Type > &dt)
Foam::lumpedPointMovement::lumpedPointMovement
lumpedPointMovement()
Default construct.
Definition: lumpedPointMovement.C:121
Foam::UList
A 1D vector of objects of type <T>, where the size of the vector is known and can be used for subscri...
Definition: HashTable.H:103
points
const pointField & points
Definition: gmvOutputHeader.H:1
Foam::List::clear
void clear()
Clear the list, i.e. set size to zero.
Definition: ListI.H:116
Foam::lumpedPointState::rotations
const tensorField & rotations() const
The local-to-global transformation for each point.
Definition: lumpedPointStateI.H:58
Foam::tmp::New
static tmp< T > New(Args &&... args)
Construct tmp of T with forwarding arguments.
Foam::HashSet::insert
bool insert(const Key &key)
Insert a new entry, not overwriting existing entries.
Definition: HashSet.H:191
patches
const polyBoundaryMesh & patches
Definition: convertProcessorPatches.H:65
Foam::line
A line primitive.
Definition: line.H:53
Foam::Ostream::writeEntry
Ostream & writeEntry(const keyType &key, const T &value)
Write a keyword/value entry.
Definition: Ostream.H:236
Foam::List::set
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.
Definition: List.H:341
Foam::Tuple2::second
const T2 & second() const noexcept
Return second.
Definition: Tuple2.H:130
Foam::token::END_LIST
End list [isseparator].
Definition: token.H:156
Foam::VectorSpace< Vector< scalar >, scalar, 3 >::zero
static const Vector< scalar > zero
Definition: VectorSpace.H:115
Foam::UIndirectList
A List with indirect addressing.
Definition: faMatrix.H:60
Foam::lumpedPointInterpolator
A simple linear interpolator between two locations, which are referenced by index.
Definition: lumpedPointInterpolator.H:59
Foam::inplaceReorder
void inplaceReorder(const labelUList &oldToNew, ListType &input, const bool prune=false)
Inplace reorder the elements of a list.
Definition: ListOpsTemplates.C:124
FatalIOErrorInFunction
#define FatalIOErrorInFunction(ios)
Report an error message using Foam::FatalIOError.
Definition: error.H:473
Foam::patchIdentifier::name
const word & name() const noexcept
The patch name.
Definition: patchIdentifier.H:135
timeIndex
label timeIndex
Definition: getTimeIndex.H:30
Foam::plusEqOp
Definition: ops.H:72
Foam::sortedOrder
labelList sortedOrder(const UList< T > &input)
Return the (stable) sort order for the list.
Foam::UList::size
void size(const label n)
Older name for setAddressableSize.
Definition: UList.H:114
Foam::triangle::pointToBarycentric
barycentric2D pointToBarycentric(const point &pt) const
Calculate the barycentric coordinates from the given point.
Definition: triangleI.H:272
Foam::Ostream
An Ostream is an abstract base class for all output systems (streams, files, token lists,...
Definition: Ostream.H:56
Foam::lumpedPointMovement::checkPatchControl
void checkPatchControl(const polyPatch &pp) const
Check if patch control exists for specified patch.
Definition: lumpedPointMovement.C:356
p0
const volScalarField & p0
Definition: EEqn.H:36
Foam::lumpedPointMovement::couplingCompleted
void couplingCompleted(const label timeIndex) const
Register that coupling is completed at this calcFrequency.
Definition: lumpedPointMovement.C:181
Foam::Tuple2< scalar, scalar >
Foam::Pstream::listCombineScatter
static void listCombineScatter(const List< commsStruct > &comms, List< T > &Value, const int tag, const label comm)
Scatter data. Reverse of combineGather.
Definition: combineGatherScatter.C:432
Foam::dictionary::getOrDefault
T getOrDefault(const word &keyword, const T &deflt, enum keyType::option matchOpt=keyType::REGEX) const
Definition: dictionaryTemplates.C:148
Foam::GeometricField< scalar, fvPatchField, volMesh >
Foam::token::BEGIN_LIST
Begin list [isseparator].
Definition: token.H:155
Foam::faceToPoint
A topoSetPointSource to select all points based on usage in given faceSet(s).
Definition: faceToPoint.H:174
Foam::fvMesh::Cf
const surfaceVectorField & Cf() const
Return face centres as surfaceVectorField.
Definition: fvMeshGeometry.C:352
lumpedPointMovement.H
Foam::lumpedPointMovement::setInterpolator
void setInterpolator(const pointPatch &fpatch, const pointField &points0)
Check if patch control exists for specified patch.
Definition: lumpedPointMovement.C:481
Foam::Tuple2::first
const T1 & first() const noexcept
Return first.
Definition: Tuple2.H:118
Foam::line::vec
Point vec() const
Return start-to-end vector.
Definition: lineI.H:112
WarningInFunction
#define WarningInFunction
Report a warning using Foam::Warning.
Definition: messageStream.H:328
pointLabels
labelList pointLabels(nPoints, -1)
Foam::dictionary::readIfPresent
bool readIfPresent(const word &keyword, T &val, enum keyType::option matchOpt=keyType::REGEX) const
Definition: dictionaryTemplates.C:405
Foam::HashSet::set
bool set(const Key &key)
Same as insert (no value to overwrite)
Definition: HashSet.H:197
Foam::GeometricField::boundaryField
const Boundary & boundaryField() const
Return const-reference to the boundary field.
Definition: GeometricFieldI.H:62
pointPatch.H
labelPair.H
Foam::PtrMap
A HashTable of pointers to objects of type <T> with a label key.
Definition: HashTableFwd.H:48
Foam::fvMesh::Sf
const surfaceVectorField & Sf() const
Return cell face area vectors.
Definition: fvMeshGeometry.C:319