particle.C
Go to the documentation of this file.
1 /*---------------------------------------------------------------------------*\
2  ========= |
3  \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
4  \\ / O peration | Website: https://openfoam.org
5  \\ / A nd | Copyright (C) 2011-2026 OpenFOAM Foundation
6  \\/ M anipulation |
7 -------------------------------------------------------------------------------
8 License
9  This file is part of OpenFOAM.
10 
11  OpenFOAM is free software: you can redistribute it and/or modify it
12  under the terms of the GNU General Public License as published by
13  the Free Software Foundation, either version 3 of the License, or
14  (at your option) any later version.
15 
16  OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
17  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
18  FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
19  for more details.
20 
21  You should have received a copy of the GNU General Public License
22  along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
23 
24 \*---------------------------------------------------------------------------*/
25 
26 #include "particle.H"
27 #include "tracking.H"
28 #include "polyTopoChangeMap.H"
29 #include "transform.H"
30 #include "cubicEqn.H"
31 
32 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
33 
35 
36 namespace Foam
37 {
39 }
40 
41 
42 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
43 
44 bool Foam::particle::locate
45 (
46  const polyMesh& mesh,
47  const vector& position,
48  label celli
49 )
50 {
51  celli_ = celli;
52 
53  return
55  (
56  mesh, position,
57  coordinates_, celli_, tetFacei_, tetPti_, 1,
58  debug
59  ? static_cast<const string&>(string("Particle " + name(origId())))
60  : NullObjectRef<string>()
61  );
62 }
63 
64 
65 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
66 
68 (
69  const polyMesh& mesh,
70  const barycentric& coordinates,
71  const label celli,
72  const label tetFacei,
73  const label tetPti,
74  const label facei
75 )
76 :
77  coordinates_(coordinates),
78  celli_(celli),
79  tetFacei_(tetFacei),
80  tetPti_(tetPti),
81  facei_(facei),
82  stepFraction_(1),
83  stepFractionBehind_(0),
84  nTracksBehind_(0),
85  origProc_(Pstream::myProcNo()),
86  origId_(getNewParticleIndex())
87 {}
88 
89 
91 (
92  const meshSearch& searchEngine,
93  const vector& position,
94  const label celli,
95  label& nLocateBoundaryHits
96 )
97 :
98  coordinates_(- vGreat, - vGreat, - vGreat, - vGreat),
99  celli_(celli),
100  tetFacei_(-1),
101  tetPti_(-1),
102  facei_(-1),
103  stepFraction_(1),
104  stepFractionBehind_(0),
105  nTracksBehind_(0),
106  origProc_(Pstream::myProcNo()),
107  origId_(getNewParticleIndex())
108 {
109  if (!locate(searchEngine, position, celli))
110  {
111  nLocateBoundaryHits ++;
112  }
113 }
114 
115 
117 :
118  coordinates_(p.coordinates_),
119  celli_(p.celli_),
120  tetFacei_(p.tetFacei_),
121  tetPti_(p.tetPti_),
122  facei_(p.facei_),
123  stepFraction_(p.stepFraction_),
124  stepFractionBehind_(p.stepFractionBehind_),
125  nTracksBehind_(p.nTracksBehind_),
126  origProc_(p.origProc_),
127  origId_(p.origId_)
128 {}
129 
130 
131 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
132 
133 bool Foam::particle::locate
134 (
135  const meshSearch& searchEngine,
136  const vector& position,
137  label celli
138 )
139 {
140  celli_ = celli;
141 
142  return
144  (
145  searchEngine, position,
146  coordinates_, celli_, tetFacei_, tetPti_, 1,
147  debug
148  ? static_cast<const string&>(string("Particle " + name(origId())))
149  : NullObjectRef<string>()
150  );
151 }
152 
153 
155 (
156  const polyMesh& mesh,
157  const vector& displacement,
158  const scalar fraction
159 )
160 {
161  const Tuple2<bool, scalar> onBoundaryAndF =
163  (
164  mesh, displacement, fraction,
165  coordinates_, celli_, tetFacei_, tetPti_, stepFraction_,
166  stepFractionBehind_, nTracksBehind_,
167  debug
168  ? static_cast<const string&>(string("Particle " + name(origId())))
169  : NullObjectRef<string>()
170  );
171 
172  facei_ = onBoundaryAndF.first() ? tetFacei_ : -1;
173 
174  return onBoundaryAndF.second();
175 }
176 
177 
179 (
180  const polyMesh& mesh,
181  const vector& displacement,
182  const scalar fraction
183 )
184 {
185  const Tuple2<bool, scalar> inNextCellAndF =
187  (
188  mesh, displacement, fraction,
189  coordinates_, celli_, tetFacei_, tetPti_, stepFraction_,
190  stepFractionBehind_, nTracksBehind_,
191  debug
192  ? static_cast<const string&>(string("Particle " + name(origId())))
193  : NullObjectRef<string>()
194  );
195 
196  facei_ = inNextCellAndF.first() ? tetFacei_ : -1;
197 
198  return inNextCellAndF.second();
199 }
200 
201 
203 (
204  const polyMesh& mesh,
205  const vector& displacement,
206  const scalar fraction
207 )
208 {
209  const Tuple2<bool, scalar> onFaceAndF =
211  (
212  mesh, displacement, fraction,
213  coordinates_, celli_, tetFacei_, tetPti_, stepFraction_,
214  stepFractionBehind_, nTracksBehind_,
215  debug
216  ? static_cast<const string&>(string("Particle " + name(origId())))
217  : NullObjectRef<string>()
218  );
219 
220  facei_ = onFaceAndF.first() ? tetFacei_ : -1;
221 
222  return onFaceAndF.second();
223 }
224 
225 
227 (
228  const polyMesh& mesh
229 ) const
230 {
231  if (cmptMin(mesh.geometricD()) == -1)
232  {
233  vector pos = position(mesh), posC = pos;
235  return pos - posC;
236  }
237  else
238  {
239  return vector::zero;
240  }
241 }
242 
243 
245 {}
246 
247 
249 {
250  const processorPolyPatch& ppp =
251  refCast<const processorPolyPatch>
252  (
253  td.mesh.boundary()[td.sendFromPatch]
254  );
255 
256  tracking::inProcessor(ppp, celli_, tetFacei_);
257 }
258 
259 
261 {
262  const processorPolyPatch& ppp =
263  refCast<const processorPolyPatch>
264  (
265  td.mesh.boundary()[td.sendToPatch]
266  );
267 
268  tracking::outProcessor(ppp, coordinates_, celli_, tetFacei_, tetPti_);
269 
270  // Remain on the face
271  facei_ = tetFacei_;
272 
273  // Transform the properties
274  if (ppp.transform().transformsPosition())
275  {
276  transformProperties(ppp.transform());
277  }
278 }
279 
280 
282 (
283  const polyMesh& mesh,
284  const label sendFromPatch,
285  const label sendToPatchFace,
286  const vector& sendToPosition
287 )
288 {
289  const nonConformalCyclicPolyPatch& nccpp =
290  static_cast<const nonConformalCyclicPolyPatch&>
291  (
292  mesh.boundary()[sendFromPatch]
293  );
294 
295  // Store the position in the barycentric data
296  coordinates_ =
298  (
299  1 - cmptSum(sendToPosition),
300  sendToPosition.x(),
301  sendToPosition.y(),
302  sendToPosition.z()
303  );
304 
305  // Break the topology
306  celli_ = -1;
307  tetFacei_ = -1;
308  tetPti_ = -1;
309 
310  // Store the local patch face in the face index
311  facei_ = sendToPatchFace;
312 
313  // Transform the properties
314  if (nccpp.transform().transformsPosition())
315  {
316  transformProperties(nccpp.nbrPatch().transform());
317  }
318 }
319 
320 
322 (
323  const polyMesh& mesh,
324  const label sendToPatch,
325  labelList& patchNLocateBoundaryHits
326 )
327 {
328  const nonConformalCyclicPolyPatch& nccpp =
329  static_cast<const nonConformalCyclicPolyPatch&>
330  (
331  mesh.boundary()[sendToPatch]
332  );
333 
334  // Get the position from the barycentric data
335  const vector receivePos
336  (
337  coordinates_.b(),
338  coordinates_.c(),
339  coordinates_.d()
340  );
341 
342  // Locate the particle on the receiving side
343  const label celli = mesh.faceOwner()[facei_ + nccpp.origPatch().start()];
344  if (!locate(mesh, receivePos, celli))
345  {
346  patchNLocateBoundaryHits[sendToPatch] ++;
347  }
348 
349  // The particle must remain associated with a face for the tracking to
350  // register as incomplete
351  facei_ = tetFacei_;
352 }
353 
354 
356 (
357  const polyMesh& mesh,
358  const transformer& transform
359 )
360 {
361  // Get the transformed position
362  const vector pos = transform.invTransformPosition(position(mesh));
363 
364  // Break the topology
365  celli_ = -1;
366  tetFacei_ = -1;
367  tetPti_ = -1;
368 
369  // Store the position in the barycentric data
370  coordinates_ = barycentric(1 - cmptSum(pos), pos.x(), pos.y(), pos.z());
371 
372  // Transform the properties
373  if (transform.transformsPosition())
374  {
375  transformProperties(inv(transform));
376  }
377 }
378 
379 
381 (
382  const polyMesh& mesh,
383  const label celli
384 )
385 {
386  // Get the position from the barycentric data
387  const vector pos(coordinates_.b(), coordinates_.c(), coordinates_.d());
388 
389  // Create some arbitrary topology for the supplied cell
390  celli_ = celli;
391  tetFacei_ = mesh.cells()[celli_][0];
392  tetPti_ = 1;
393 
394  // Calculate the coordinates for the assumed topology. This isn't likely to
395  // be correct; the particle is probably not in this tet. It will, however,
396  // generate the correct vector when the position method is called. A
397  // referred particle should never be tracked, so this approximate topology
398  // is good enough. By using the nearby cell we minimise the error
399  // associated with the incorrect topology.
400  coordinates_ =
402  (
403  mesh, pos,
404  celli_, tetFacei_, tetPti_, stepFraction_
405  );
406 }
407 
408 
410 (
411  const polyMesh& mesh,
412  const polyMesh& procMesh,
413  const label procCell,
414  const label procTetFace
415 ) const
416 {
417  // The tet point on the procMesh differs from the current tet point if the
418  // mesh and procMesh faces are of differing orientation. The change is the
419  // same as in particle::correctAfterParallelTransfer.
420 
421  if
422  (
423  (mesh.faceOwner()[tetFacei_] == celli_)
424  == (procMesh.faceOwner()[procTetFace] == procCell)
425  )
426  {
427  return tetPti_;
428  }
429  else
430  {
431  return procMesh.faces()[procTetFace].size() - 1 - tetPti_;
432  }
433 }
434 
435 
436 // * * * * * * * * * * * * * * Friend Operators * * * * * * * * * * * * * * //
437 //
438 
439 bool Foam::operator==(const particle& pA, const particle& pB)
440 {
441  return (pA.origProc() == pB.origProc() && pA.origId() == pB.origId());
442 }
443 
444 
445 bool Foam::operator!=(const particle& pA, const particle& pB)
446 {
447  return !(pA == pB);
448 }
449 
450 
451 // ************************************************************************* //
void size(const label)
Override size to be inconsistent with allocated storage.
Definition: ListI.H:164
Inter-processor communications stream.
Definition: Pstream.H:56
A 2-tuple for storing two objects of different types.
Definition: Tuple2.H:66
const Type2 & second() const
Return second.
Definition: Tuple2.H:131
const Type1 & first() const
Return first.
Definition: Tuple2.H:119
static const Form zero
Definition: VectorSpace.H:118
const Cmpt & z() const
Definition: VectorI.H:87
const Cmpt & y() const
Definition: VectorI.H:81
const Cmpt & x() const
Definition: VectorI.H:75
const fvBoundaryMesh & boundary() const
Return reference to boundary mesh.
Definition: fvMesh.C:932
Mesh object that implements searches within the local cells and faces.
Definition: meshSearch.H:59
Non-conformal cyclic poly patch. As nonConformalCoupledPolyPatch, but the neighbouring patch is local...
virtual const transformer & transform() const
Inherit the cyclic transform method.
const nonConformalCyclicPolyPatch & nbrPatch() const
Neighbour patch.
const polyPatch & origPatch() const
Original patch.
label sendFromPatch
Patch from which to send the particle.
Definition: particle.H:114
label sendToPatch
Patch to which to send the particle.
Definition: particle.H:117
const polyMesh & mesh
Reference to the mesh.
Definition: particle.H:104
Base particle class.
Definition: particle.H:85
label origProc() const
Return the originating processor ID.
Definition: particleI.H:96
void prepareForNonConformalCyclicTransfer(const polyMesh &mesh, const label sendToPatch, const label sendToPatchFace, const vector &sendToPosition)
Make changes prior to a transfer across a non conformal cyclic.
Definition: particle.C:282
scalar trackToCell(const polyMesh &mesh, const vector &displacement, const scalar fraction)
As particle::track, but stops when a new cell is reached.
Definition: particle.C:179
void prepareForProcessorTransfer(trackingData &td)
Make changes prior to a transfer across a processor boundary.
Definition: particle.C:248
particle(const polyMesh &mesh, const barycentric &coordinates, const label celli, const label tetFacei, const label tetPti, const label facei)
Construct from components.
Definition: particle.C:68
void correctAfterInteractionListReferral(const polyMesh &mesh, const label celli)
Correct the topology after referral. Locates the particle.
Definition: particle.C:381
void correctAfterNonConformalCyclicTransfer(const polyMesh &mesh, const label sendToPatch, labelList &patchNLocateBoundaryHits)
Make changes following a transfer across a non conformal cyclic.
Definition: particle.C:322
scalar track(const polyMesh &mesh, const vector &displacement, const scalar fraction)
Track along the displacement for a given fraction of the overall.
Definition: particle.C:155
scalar trackToFace(const polyMesh &mesh, const vector &displacement, const scalar fraction)
As particle::track, but stops when a face is hit.
Definition: particle.C:203
void prepareForInteractionListReferral(const polyMesh &mesh, const transformer &transform)
Break the topology and store the cartesian position so that the.
Definition: particle.C:356
vector deviationFromMeshCentre(const polyMesh &mesh) const
Get the displacement from the mesh centre. Used to correct the.
Definition: particle.C:227
void correctAfterProcessorTransfer(trackingData &td)
Make changes following a transfer across a processor boundary.
Definition: particle.C:260
label procTetPt(const polyMesh &mesh, const polyMesh &procMesh, const label procCell, const label procTetFace) const
Return the tet point appropriate for decomposition or.
Definition: particle.C:410
vector position(const polyMesh &mesh) const
Return current particle position.
Definition: particleI.H:159
virtual void transformProperties(const transformer &)
Transform the physical properties of the particle.
Definition: particle.C:244
label origId() const
Return the particle ID on the originating processor.
Definition: particleI.H:108
static label particleCount
Cumulative particle counter - used to provide unique ID.
Definition: particle.H:217
Mesh consisting of general polyhedral cells.
Definition: polyMesh.H:78
const polyBoundaryMesh & boundary() const
Return boundary mesh.
Definition: polyMesh.H:393
virtual const faceList & faces() const
Return raw faces.
Definition: polyMesh.C:1308
virtual const labelList & faceOwner() const
Return face owner.
Definition: polyMesh.C:1321
const Vector< label > & geometricD() const
Return the vector of geometric directions in mesh.
Definition: polyMesh.C:1030
label start() const
Return start label of this patch in the polyMesh face list.
Definition: polyPatch.H:277
const cellList & cells() const
Neighbour processor patch.
virtual const transformer & transform() const
Return null transform between processor patches.
Vector-tensor class used to perform translations, rotations and scaling operations in 3D space.
Definition: transformer.H:84
bool transformsPosition() const
Return true if the transformer transforms a point.
Definition: transformerI.H:146
Foam::fvMesh mesh(Foam::IOobject(regionName, runTime.name(), runTime, Foam::IOobject::MUST_READ), false)
void constrainToMeshCentre(const polyMesh &mesh, point &pt)
Set the constrained components of position to mesh centre.
Definition: meshTools.C:613
barycentric coordinates(const polyMesh &mesh, const point &position, const label celli, const label facei, const label faceTrii, const scalar stepFraction)
Return the coordinates given the position and tet topology.
Definition: tracking.C:1258
Tuple2< bool, scalar > toCell(const polyMesh &mesh, const Displacement &displacement, const scalar fraction, barycentric &coordinates, label &celli, label &facei, label &faceTrii, scalar &stepFraction, scalar &stepFractionBehind, label &nTracksBehind, const string &debugPrefix=NullObjectRef< string >())
As toFace, except that if the track ends on an internal face then this.
Tuple2< bool, scalar > toBoundary(const polyMesh &mesh, const Displacement &displacement, const scalar fraction, barycentric &coordinates, label &celli, label &facei, label &faceTrii, scalar &stepFraction, scalar &stepFractionBehind, label &nTracksBehind, const string &debugPrefix=NullObjectRef< string >())
As toFace, except that the track continues across multiple cells until.
void outProcessor(const processorPolyPatch &outPatch, barycentric &coordinates, label &celli, label &facei, label &faceTrii)
Complete crossing of a processor patch. Restore the topology.
Definition: tracking.C:1805
void inProcessor(const processorPolyPatch &inPatch, label &celli, label &facei)
Initialise crossing of a processor patch. Breaks the topology in order.
Definition: tracking.C:1790
point position(const polyMesh &mesh, const barycentric &coordinates, const label celli, const label facei, const label faceTrii, const scalar stepFraction)
Return the position given the coordinates and tet topology.
Definition: trackingI.H:224
Tuple2< bool, scalar > toFace(const polyMesh &mesh, const Displacement &displacement, const scalar fraction, barycentric &coordinates, label &celli, label &facei, label &faceTrii, scalar &stepFraction, scalar &stepFractionBehind, label &nTracksBehind, const string &debugPrefix=NullObjectRef< string >())
Track along the displacement for a given fraction of the overall.
bool locate(const polyMesh &mesh, const point &position, barycentric &coordinates, label &celli, label &facei, label &faceTrii, const scalar stepFraction, const string &debugPrefix=NullObjectRef< string >())
Initialise the location at the given position. Returns whether or not a.
Definition: tracking.C:1592
const unitSet fraction
Namespace for OpenFOAM.
dimensionedScalar pos(const dimensionedScalar &ds)
bool operator!=(const particle &, const particle &)
Definition: particle.C:445
Barycentric< scalar > barycentric
A scalar version of the templated Barycentric.
Definition: barycentric.H:45
intWM_LABEL_SIZE_t label
A label is an int32_t or int64_t as specified by the pre-processor macro WM_LABEL_SIZE.
Definition: label.H:59
tmp< fvMatrix< Type > > operator==(const fvMatrix< Type > &, const fvMatrix< Type > &)
void transform(GeometricField< Type, GeoMesh > &rtf, const GeometricField< tensor, GeoMesh > &trf, const GeometricField< Type, GeoMesh > &tf)
Vector< scalar > vector
A scalar version of the templated Vector.
Definition: vector.H:49
void inv(pointPatchField< tensor > &, const pointPatchField< tensor > &)
void cmptMin(Field< typename Field< Type >::cmptType > &res, const UList< Type > &f)
word name(const LagrangianState state)
Return a string representation of a Lagrangian state enumeration.
Cmpt cmptSum(const VectorSpace< Form, Cmpt, Ncmpts > &vs)
Definition: VectorSpaceI.H:507
defineTypeNameAndDebug(atmosphericBoundaryLayer, 0)
volScalarField & p
3D tensor transformation operations.