wallBoundedParticleTemplates.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 | Copyright (C) 2011-2015 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 "wallBoundedParticle.H"
27 
28 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
29 
30 template<class TrackData>
32 (
33  TrackData& td,
34  const scalar trackFraction
35 )
36 {
37 // typedef TrackData::CloudType cloudType;
38  typedef typename TrackData::cloudType::particleType particleType;
39 
40  particleType& p = static_cast<particleType&>(*this);
41  p.hitFace(td);
42 
43  if (!internalFace(faceI_))
44  {
45  label origFaceI = faceI_;
46  label patchI = patch(faceI_);
47 
48  // No action taken for tetPtI_ for tetFaceI_ here, handled by
49  // patch interaction call or later during processor transfer.
50 
51 
52  // Dummy tet indices. What to do here?
53  tetIndices faceHitTetIs;
54 
55  if
56  (
57  !p.hitPatch
58  (
59  mesh_.boundaryMesh()[patchI],
60  td,
61  patchI,
62  trackFraction,
63  faceHitTetIs
64  )
65  )
66  {
67  // Did patch interaction model switch patches?
68  // Note: recalculate meshEdgeStart_, diagEdge_!
69  if (faceI_ != origFaceI)
70  {
71  patchI = patch(faceI_);
72  }
73 
74  const polyPatch& patch = mesh_.boundaryMesh()[patchI];
75 
76  if (isA<wedgePolyPatch>(patch))
77  {
78  p.hitWedgePatch
79  (
80  static_cast<const wedgePolyPatch&>(patch), td
81  );
82  }
83  else if (isA<symmetryPlanePolyPatch>(patch))
84  {
85  p.hitSymmetryPlanePatch
86  (
87  static_cast<const symmetryPlanePolyPatch&>(patch), td
88  );
89  }
90  else if (isA<symmetryPolyPatch>(patch))
91  {
92  p.hitSymmetryPatch
93  (
94  static_cast<const symmetryPolyPatch&>(patch), td
95  );
96  }
97  else if (isA<cyclicPolyPatch>(patch))
98  {
99  p.hitCyclicPatch
100  (
101  static_cast<const cyclicPolyPatch&>(patch), td
102  );
103  }
104  else if (isA<processorPolyPatch>(patch))
105  {
106  p.hitProcessorPatch
107  (
108  static_cast<const processorPolyPatch&>(patch), td
109  );
110  }
111  else if (isA<wallPolyPatch>(patch))
112  {
113  p.hitWallPatch
114  (
115  static_cast<const wallPolyPatch&>(patch), td, faceHitTetIs
116  );
117  }
118  else
119  {
120  p.hitPatch(patch, td);
121  }
122  }
123  }
124 }
125 
126 
127 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
128 
129 //- Track particle to a given position and returns 1.0 if the
130 // trajectory is completed without hitting a face otherwise
131 // stops at the face and returns the fraction of the trajectory
132 // completed.
133 // on entry 'stepFraction()' should be set to the fraction of the
134 // time-step at which the tracking starts.
135 template<class TrackData>
137 (
138  TrackData& td,
139  const vector& endPosition
140 )
141 {
142  // Are we on a track face? If not we do a topological walk.
143 
144  // Particle:
145  // - cell_ always set
146  // - tetFace_, tetPt_ always set (these identify tet particle is in)
147  // - optionally meshEdgeStart_ or diagEdge_ set (edge particle is on)
148 
149  //checkInside();
150  //checkOnTriangle(position());
151  //if (meshEdgeStart_ != -1 || diagEdge_ != -1)
152  //{
153  // checkOnEdge();
154  //}
155 
156  scalar trackFraction = 0.0;
157 
158  if (!td.isWallPatch_[tetFace()])
159  {
160  // Don't track across face. Just walk in cell. Particle is on
161  // mesh edge (as indicated by meshEdgeStart_).
162  const edge meshEdge(currentEdge());
163 
164  // If internal face check whether to go to neighbour cell or just
165  // check to the other internal tet on the edge.
166  if (mesh_.isInternalFace(tetFace()))
167  {
168  label nbrCellI =
169  (
170  cellI_ == mesh_.faceOwner()[faceI_]
171  ? mesh_.faceNeighbour()[faceI_]
172  : mesh_.faceOwner()[faceI_]
173  );
174  // Check angle to nbrCell tet. Is it in the direction of the
175  // endposition? I.e. since volume of nbr tet is positive the
176  // tracking direction should be into the tet.
177  tetIndices nbrTi(nbrCellI, tetFaceI_, tetPtI_, mesh_);
178  if ((nbrTi.faceTri(mesh_).normal() & (endPosition-position())) < 0)
179  {
180  // Change into nbrCell. No need to change tetFace, tetPt.
181  //Pout<< " crossed from cell:" << cellI_
182  // << " into " << nbrCellI << endl;
183  cellI_ = nbrCellI;
184  patchInteraction(td, trackFraction);
185  }
186  else
187  {
188  // Walk to other face on edge. Changes tetFace, tetPt but not
189  // cell.
190  crossEdgeConnectedFace(meshEdge);
191  patchInteraction(td, trackFraction);
192  }
193  }
194  else
195  {
196  // Walk to other face on edge. This might give loop since
197  // particle should have been removed?
198  crossEdgeConnectedFace(meshEdge);
199  patchInteraction(td, trackFraction);
200  }
201  }
202  else
203  {
204  // We're inside a tet on the wall. Check if the current tet is
205  // the one to cross. If not we cross into the neighbouring triangle.
206 
207  if (mesh_.isInternalFace(tetFace()))
208  {
210  << "Can only track on boundary faces."
211  << " Face:" << tetFace()
212  << " at:" << mesh_.faceCentres()[tetFace()]
213  << abort(FatalError);
214  }
215 
216  point projectedEndPosition = endPosition;
217  // Remove normal component
218  {
219  const triFace tri(currentTetIndices().faceTriIs(mesh_));
220  vector n = tri.normal(mesh_.points());
221  n /= mag(n);
222  const point& basePt = mesh_.points()[tri[0]];
223  projectedEndPosition -= ((projectedEndPosition-basePt)&n)*n;
224  }
225 
226 
227  bool doTrack = false;
228  if (meshEdgeStart_ == -1 && diagEdge_ == -1)
229  {
230  // We're starting and not yet on an edge.
231  doTrack = true;
232  }
233  else
234  {
235  // See if the current triangle has got a point on the
236  // correct side of the edge.
237  doTrack = isTriAlongTrack(projectedEndPosition);
238  }
239 
240 
241  if (doTrack)
242  {
243  // Track across triangle. Return triangle edge crossed.
244  label triEdgeI = -1;
245  trackFraction = trackFaceTri(projectedEndPosition, triEdgeI);
246 
247  if (triEdgeI == -1)
248  {
249  // Reached endpoint
250  //checkInside();
251  diagEdge_ = -1;
252  meshEdgeStart_ = -1;
253  return trackFraction;
254  }
255 
256  const tetIndices ti(currentTetIndices());
257 
258  // Triangle (faceTriIs) gets constructed from
259  // f[faceBasePtI_],
260  // f[facePtAI_],
261  // f[facePtBI_]
262  //
263  // So edge indices are:
264  // 0 : edge between faceBasePtI_ and facePtAI_
265  // 1 : edge between facePtAI_ and facePtBI_ (is always a real edge)
266  // 2 : edge between facePtBI_ and faceBasePtI_
267 
268  const Foam::face& f = mesh_.faces()[ti.face()];
269  const label fp0 = ti.faceBasePt();
270 
271  if (triEdgeI == 0)
272  {
273  if (ti.facePtA() == f.fcIndex(fp0))
274  {
275  //Pout<< "Real edge." << endl;
276  diagEdge_ = -1;
277  meshEdgeStart_ = fp0;
278  //checkOnEdge();
279  crossEdgeConnectedFace(currentEdge());
280  patchInteraction(td, trackFraction);
281  }
282  else if (ti.facePtA() == f.rcIndex(fp0))
283  {
284  //Note: should not happen since boundary face so owner
285  //Pout<< "Real edge." << endl;
287  << abort(FatalError);
288 
289  diagEdge_ = -1;
290  meshEdgeStart_ = f.rcIndex(fp0);
291  //checkOnEdge();
292  crossEdgeConnectedFace(currentEdge());
293  patchInteraction(td, trackFraction);
294  }
295  else
296  {
297  // Get index of triangle on other side of edge.
298  diagEdge_ = ti.facePtA()-fp0;
299  if (diagEdge_ < 0)
300  {
301  diagEdge_ += f.size();
302  }
303  meshEdgeStart_ = -1;
304  //checkOnEdge();
305  crossDiagonalEdge();
306  }
307  }
308  else if (triEdgeI == 1)
309  {
310  //Pout<< "Real edge." << endl;
311  diagEdge_ = -1;
312  meshEdgeStart_ = ti.facePtA();
313  //checkOnEdge();
314  crossEdgeConnectedFace(currentEdge());
315  patchInteraction(td, trackFraction);
316  }
317  else // if (triEdgeI == 2)
318  {
319  if (ti.facePtB() == f.rcIndex(fp0))
320  {
321  //Pout<< "Real edge." << endl;
322  diagEdge_ = -1;
323  meshEdgeStart_ = ti.facePtB();
324  //checkOnEdge();
325  crossEdgeConnectedFace(currentEdge());
326  patchInteraction(td, trackFraction);
327  }
328  else if (ti.facePtB() == f.fcIndex(fp0))
329  {
330  //Note: should not happen since boundary face so owner
331  //Pout<< "Real edge." << endl;
333  << abort(FatalError);
334 
335  diagEdge_ = -1;
336  meshEdgeStart_ = fp0;
337  //checkOnEdge();
338  crossEdgeConnectedFace(currentEdge());
339  patchInteraction(td, trackFraction);
340  }
341  else
342  {
343  //Pout<< "Triangle edge." << endl;
344  // Get index of triangle on other side of edge.
345  diagEdge_ = ti.facePtB()-fp0;
346  if (diagEdge_ < 0)
347  {
348  diagEdge_ += f.size();
349  }
350  meshEdgeStart_ = -1;
351  //checkOnEdge();
352  crossDiagonalEdge();
353  }
354  }
355  }
356  else
357  {
358  // Current tet is not the right one. Check the neighbour tet.
359 
360  if (meshEdgeStart_ != -1)
361  {
362  // Particle is on mesh edge so change into other face on cell
363  crossEdgeConnectedFace(currentEdge());
364  //checkOnEdge();
365  patchInteraction(td, trackFraction);
366  }
367  else
368  {
369  // Particle is on diagonal edge so change into the other
370  // triangle.
371  crossDiagonalEdge();
372  //checkOnEdge();
373  }
374  }
375  }
376 
377  //checkInside();
378 
379  return trackFraction;
380 }
381 
382 
383 template<class TrackData>
385 (
386  const polyPatch&,
387  TrackData& td,
388  const label patchI,
389  const scalar trackFraction,
390  const tetIndices& tetIs
391 )
392 {
393  // Disable generic patch interaction
394  return false;
395 }
396 
397 
398 template<class TrackData>
400 (
401  const wedgePolyPatch& pp,
402  TrackData& td
403 )
404 {
405  // Remove particle
406  td.keepParticle = false;
407 }
408 
409 
410 template<class TrackData>
412 (
413  const symmetryPlanePolyPatch& pp,
414  TrackData& td
415 )
416 {
417  // Remove particle
418  td.keepParticle = false;
419 }
420 
421 
422 template<class TrackData>
424 (
425  const symmetryPolyPatch& pp,
426  TrackData& td
427 )
428 {
429  // Remove particle
430  td.keepParticle = false;
431 }
432 
433 
434 template<class TrackData>
436 (
437  const cyclicPolyPatch& pp,
438  TrackData& td
439 )
440 {
441  // Remove particle
442  td.keepParticle = false;
443 }
444 
445 
446 template<class TrackData>
448 (
449  const processorPolyPatch& pp,
450  TrackData& td
451 )
452 {
453  // Switch particle
454  td.switchProcessor = true;
455 
456  // Adapt edgeStart_ for other side.
457  // E.g. if edgeStart_ is 1 then the edge is between vertex 1 and 2 so
458  // on the other side between 2 and 3 so edgeStart_ should be
459  // f.size()-edgeStart_-1.
460 
461  const Foam::face& f = mesh_.faces()[face()];
462 
463  if (meshEdgeStart_ != -1)
464  {
465  meshEdgeStart_ = f.size()-meshEdgeStart_-1;
466  }
467  else
468  {
469  // diagEdge_ is relative to faceBasePt
470  diagEdge_ = f.size()-diagEdge_;
471  }
472 }
473 
474 
475 template<class TrackData>
477 (
478  const wallPolyPatch& wpp,
479  TrackData& td,
480  const tetIndices&
481 )
482 {}
483 
484 
485 template<class TrackData>
487 (
488  const polyPatch& wpp,
489  TrackData& td
490 )
491 {
492  // Remove particle
493  td.keepParticle = false;
494 }
495 
496 
497 template<class CloudType>
499 {
500  if (!c.size())
501  {
502  return;
503  }
504 
506 
508  (
509  c.fieldIOobject("meshEdgeStart", IOobject::MUST_READ)
510  );
511 
513  (
514  c.fieldIOobject("diagEdge_", IOobject::MUST_READ)
515  );
516  c.checkFieldIOobject(c, diagEdge);
517 
518  label i = 0;
519  forAllIter(typename CloudType, c, iter)
520  {
521  iter().meshEdgeStart_ = meshEdgeStart[i];
522  iter().diagEdge_ = diagEdge[i];
523  i++;
524  }
525 }
526 
527 
528 template<class CloudType>
530 {
532 
533  label np = c.size();
534 
535  IOField<label> meshEdgeStart
536  (
537  c.fieldIOobject("meshEdgeStart", IOobject::NO_READ),
538  np
539  );
540  IOField<label> diagEdge
541  (
542  c.fieldIOobject("diagEdge", IOobject::NO_READ),
543  np
544  );
545 
546  label i = 0;
547  forAllConstIter(typename CloudType, c, iter)
548  {
549  meshEdgeStart[i] = iter().meshEdgeStart_;
550  diagEdge[i] = iter().diagEdge_;
551  i++;
552  }
553 
554  meshEdgeStart.write();
555  diagEdge.write();
556 }
557 
558 
559 // ************************************************************************* //
Foam::triFace::normal
vector normal(const pointField &) const
Vector normal; magnitude is equal to area of face.
Definition: triFaceI.H:181
p
p
Definition: pEqn.H:62
forAllIter
#define forAllIter(Container, container, iter)
Iterate across all elements in the container object of type.
Definition: UList.H:431
Foam::IOField
A primitive field of type <T> with automated input and output.
Definition: IOField.H:50
Foam::wedgePolyPatch
Wedge front and back plane patch.
Definition: wedgePolyPatch.H:48
Foam::wallBoundedParticle::writeFields
static void writeFields(const CloudType &)
Write.
Definition: wallBoundedParticleTemplates.C:529
Foam::cyclicPolyPatch
Cyclic plane patch.
Definition: cyclicPolyPatch.H:63
Foam::wallBoundedParticle::patchInteraction
void patchInteraction(TrackData &td, const scalar trackFraction)
Do all patch interaction.
Definition: wallBoundedParticleTemplates.C:32
Foam::wallBoundedParticle::hitProcessorPatch
void hitProcessorPatch(const processorPolyPatch &, TrackData &td)
Definition: wallBoundedParticleTemplates.C:448
Foam::edge
An edge is a list of two point labels. The functionality it provides supports the discretisation on a...
Definition: edge.H:58
Foam::regIOobject::write
virtual bool write() const
Write using setting from DB.
Definition: regIOobjectWrite.C:126
Foam::wallBoundedParticle::trackToEdge
scalar trackToEdge(TrackData &td, const vector &endPosition)
Equivalent of trackToFace.
Foam::IOobject::MUST_READ
@ MUST_READ
Definition: IOobject.H:108
Foam::mag
dimensioned< scalar > mag(const dimensioned< Type > &)
Foam::wallBoundedParticle::hitWallPatch
void hitWallPatch(const wallPolyPatch &, TrackData &td, const tetIndices &)
Overridable function to handle the particle hitting a wallPatch.
Definition: wallBoundedParticleTemplates.C:477
forAllConstIter
forAllConstIter(PtrDictionary< phaseModel >, mixture.phases(), phase)
Definition: pEqn.H:39
n
label n
Definition: TABSMDCalcMethod2.H:31
Foam::tetIndices::facePtB
label facePtB() const
Return face point B.
Definition: tetIndicesI.H:54
wallBoundedParticle.H
Foam::wallBoundedParticle::meshEdgeStart
label meshEdgeStart() const
-1 or label of mesh edge
Definition: wallBoundedParticle.H:272
Foam::label
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
Foam::polyPatch::boundaryMesh
const polyBoundaryMesh & boundaryMesh() const
Return boundaryMesh reference.
Definition: polyPatch.C:302
Foam::triangle::normal
vector normal() const
Return vector normal.
Definition: triangleI.H:116
Foam::tetIndices::faceTri
triPointRef faceTri(const polyMesh &mesh) const
Return the geometry corresponding to the tri on the.
Definition: tetIndicesI.H:109
Foam::IOobject::NO_READ
@ NO_READ
Definition: IOobject.H:111
Foam::polyPatch
A patch is a list of labels that address the faces in the global face list.
Definition: polyPatch.H:66
Foam::symmetryPlanePolyPatch
Symmetry-plane patch.
Definition: symmetryPlanePolyPatch.H:48
Foam::tetIndices::face
label face() const
Return the face.
Definition: tetIndicesI.H:36
Foam::symmetryPolyPatch
Symmetry patch for non-planar or multi-plane patches.
Definition: symmetryPolyPatch.H:51
Foam::wallBoundedParticle::hitSymmetryPatch
void hitSymmetryPatch(const symmetryPolyPatch &, TrackData &td)
Overridable function to handle the particle hitting a.
Definition: wallBoundedParticleTemplates.C:424
Foam::processorPolyPatch
Neighbour processor patch.
Definition: processorPolyPatch.H:55
Foam::DSMCCloud
Templated base class for dsmc cloud.
Definition: DSMCCloud.H:68
Foam::tetIndices::faceBasePt
label faceBasePt() const
Return the face base point.
Definition: tetIndicesI.H:42
Foam::wallBoundedParticle::hitWedgePatch
void hitWedgePatch(const wedgePolyPatch &, TrackData &td)
Overridable function to handle the particle hitting a wedge.
Definition: wallBoundedParticleTemplates.C:400
Foam::FatalError
error FatalError
Foam::wallPolyPatch
Foam::wallPolyPatch.
Definition: wallPolyPatch.H:48
Foam::abort
errorManip< error > abort(error &err)
Definition: errorManip.H:131
Foam::wallBoundedParticle::hitSymmetryPlanePatch
void hitSymmetryPlanePatch(const symmetryPlanePolyPatch &, TrackData &td)
Overridable function to handle the particle hitting a.
Definition: wallBoundedParticleTemplates.C:412
Foam::tetIndices
Storage and named access for the indices of a tet which is part of the decomposition of a cell.
Definition: tetIndices.H:73
Foam::wallBoundedParticle::hitPatch
bool hitPatch(const polyPatch &, TrackData &td, const label patchI, const scalar trackFraction, const tetIndices &tetIs)
Overridable function to handle the particle hitting a patch.
Definition: wallBoundedParticleTemplates.C:385
FatalErrorInFunction
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:318
Foam::triFace
A triangular face using a FixedList of labels corresponding to mesh vertices.
Definition: triFace.H:68
f
labelList f(nPoints)
Foam::Vector< scalar >
Foam::tetIndices::facePtA
label facePtA() const
Return face point A.
Definition: tetIndicesI.H:48
Foam::wallBoundedParticle::readFields
static void readFields(CloudType &)
Read.
Definition: wallBoundedParticleTemplates.C:498
Foam::wallBoundedParticle::hitCyclicPatch
void hitCyclicPatch(const cyclicPolyPatch &, TrackData &td)
Overridable function to handle the particle hitting a cyclic.
Definition: wallBoundedParticleTemplates.C:436
Foam::constant::universal::c
const dimensionedScalar c
Speed of light in a vacuum.
Foam::wallBoundedParticle::diagEdge
label diagEdge() const
-1 or diagonal edge
Definition: wallBoundedParticle.H:278
Foam::particle::readFields
static void readFields(CloudType &c)
Read the fields associated with the owner cloud.
Definition: particleTemplates.C:129
Foam::face
A face is a list of labels corresponding to mesh vertices.
Definition: face.H:75
Foam::particle::writeFields
static void writeFields(const CloudType &c)
Write the fields associated with the owner cloud.
Definition: particleTemplates.C:159