patchInjectionBase.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) 2013-2017 OpenFOAM Foundation
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 "patchInjectionBase.H"
29 #include "polyMesh.H"
30 #include "SubField.H"
31 #include "Random.H"
32 #include "triPointRef.H"
33 #include "volFields.H"
35 
36 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
37 
39 (
40  const polyMesh& mesh,
41  const word& patchName
42 )
43 :
44  patchName_(patchName),
45  patchId_(mesh.boundaryMesh().findPatchID(patchName_)),
46  patchArea_(0.0),
47  patchNormal_(),
48  cellOwners_(),
49  triFace_(),
50  triToFace_(),
51  triCumulativeMagSf_(),
52  sumTriMagSf_(Pstream::nProcs() + 1, Zero)
53 {
54  if (patchId_ < 0)
55  {
57  << "Requested patch " << patchName_ << " not found" << nl
58  << "Available patches are: " << mesh.boundaryMesh().names() << nl
59  << exit(FatalError);
60  }
61 
62  updateMesh(mesh);
63 }
64 
65 
67 :
68  patchName_(pib.patchName_),
69  patchId_(pib.patchId_),
70  patchArea_(pib.patchArea_),
71  patchNormal_(pib.patchNormal_),
72  cellOwners_(pib.cellOwners_),
73  triFace_(pib.triFace_),
74  triToFace_(pib.triToFace_),
75  triCumulativeMagSf_(pib.triCumulativeMagSf_),
76  sumTriMagSf_(pib.sumTriMagSf_)
77 {}
78 
79 
80 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
81 
83 {
84  // Set/cache the injector cells
85  const polyPatch& patch = mesh.boundaryMesh()[patchId_];
86  const pointField& points = patch.points();
87 
88  cellOwners_ = patch.faceCells();
89 
90  // Triangulate the patch faces and create addressing
91  DynamicList<label> triToFace(2*patch.size());
92  DynamicList<scalar> triMagSf(2*patch.size());
94  DynamicList<face> tris(5);
95 
96  // Set zero value at the start of the tri area list
97  triMagSf.append(0.0);
98 
99  forAll(patch, facei)
100  {
101  const face& f = patch[facei];
102 
103  tris.clear();
104  f.triangles(points, tris);
105 
106  forAll(tris, i)
107  {
108  triToFace.append(facei);
109  triFace.append(tris[i]);
110  triMagSf.append(tris[i].mag(points));
111  }
112  }
113 
114  forAll(sumTriMagSf_, i)
115  {
116  sumTriMagSf_[i] = 0.0;
117  }
118 
119  sumTriMagSf_[Pstream::myProcNo() + 1] = sum(triMagSf);
120 
122  Pstream::listCombineScatter(sumTriMagSf_);
123 
124  for (label i = 1; i < triMagSf.size(); i++)
125  {
126  triMagSf[i] += triMagSf[i-1];
127  }
128 
129  // Transfer to persistent storage
130  triFace_.transfer(triFace);
131  triToFace_.transfer(triToFace);
132  triCumulativeMagSf_.transfer(triMagSf);
133 
134  // Convert sumTriMagSf_ into cumulative sum of areas per proc
135  for (label i = 1; i < sumTriMagSf_.size(); i++)
136  {
137  sumTriMagSf_[i] += sumTriMagSf_[i-1];
138  }
139 
140  const scalarField magSf(mag(patch.faceAreas()));
141  patchArea_ = sum(magSf);
142  patchNormal_ = patch.faceAreas()/magSf;
143  reduce(patchArea_, sumOp<scalar>());
144 }
145 
146 
148 (
149  const fvMesh& mesh,
150  const scalar fraction01,
151  Random& rnd,
152  vector& position,
153  label& cellOwner,
154  label& tetFacei,
155  label& tetPti
156 )
157 {
158  label facei = -1;
159 
160  if (cellOwners_.size() > 0)
161  {
162  // Determine which processor to inject from
163  const label proci = whichProc(fraction01);
164 
165  if (Pstream::myProcNo() == proci)
166  {
167  const scalar areaFraction = fraction01*patchArea_;
168 
169  // Find corresponding decomposed face triangle
170  label trii = 0;
171  scalar offset = sumTriMagSf_[proci];
172  forAllReverse(triCumulativeMagSf_, i)
173  {
174  if (areaFraction > triCumulativeMagSf_[i] + offset)
175  {
176  trii = i;
177  break;
178  }
179  }
180 
181  // Set cellOwner
182  facei = triToFace_[trii];
183  cellOwner = cellOwners_[facei];
184 
185  // Find random point in triangle
186  const polyPatch& patch = mesh.boundaryMesh()[patchId_];
187  const pointField& points = patch.points();
188  const face& tf = triFace_[trii];
189  const triPointRef tri(points[tf[0]], points[tf[1]], points[tf[2]]);
190  const point pf(tri.randomPoint(rnd));
191 
192  // Position perturbed away from face (into domain)
193  const scalar a = rnd.position(scalar(0.1), scalar(0.5));
194  const vector& pc = mesh.cellCentres()[cellOwner];
195  const vector d =
196  mag((pf - pc) & patchNormal_[facei])*patchNormal_[facei];
197 
198  position = pf - a*d;
199 
200  // Try to find tetFacei and tetPti in the current position
201  mesh.findTetFacePt(cellOwner, position, tetFacei, tetPti);
202 
203  // tetFacei and tetPti not found, check if the cell has changed
204  if (tetFacei == -1 ||tetPti == -1)
205  {
206  mesh.findCellFacePt(position, cellOwner, tetFacei, tetPti);
207  }
208 
209  // Both searches failed, choose a random position within
210  // the original cell
211  if (tetFacei == -1 ||tetPti == -1)
212  {
213  // Reset cellOwner
214  cellOwner = cellOwners_[facei];
215  const scalarField& V = mesh.V();
216 
217  // Construct cell tet indices
218  const List<tetIndices> cellTetIs =
220 
221  // Construct cell tet volume fractions
222  scalarList cTetVFrac(cellTetIs.size(), Zero);
223  for (label teti=1; teti<cellTetIs.size()-1; teti++)
224  {
225  cTetVFrac[teti] =
226  cTetVFrac[teti-1]
227  + cellTetIs[teti].tet(mesh).mag()/V[cellOwner];
228  }
229  cTetVFrac.last() = 1;
230 
231  // Set new particle position
232  const scalar volFrac = rnd.sample01<scalar>();
233  label teti = 0;
234  forAll(cTetVFrac, vfI)
235  {
236  if (cTetVFrac[vfI] > volFrac)
237  {
238  teti = vfI;
239  break;
240  }
241  }
242  position = cellTetIs[teti].tet(mesh).randomPoint(rnd);
243  tetFacei = cellTetIs[teti].face();
244  tetPti = cellTetIs[teti].tetPt();
245  }
246  }
247  else
248  {
249  cellOwner = -1;
250  tetFacei = -1;
251  tetPti = -1;
252 
253  // Dummy position
254  position = pTraits<vector>::max;
255  }
256  }
257  else
258  {
259  cellOwner = -1;
260  tetFacei = -1;
261  tetPti = -1;
262 
263  // Dummy position
264  position = pTraits<vector>::max;
265  }
266 
267  return facei;
268 }
269 
270 
272 (
273  const fvMesh& mesh,
274  Random& rnd,
275  vector& position,
276  label& cellOwner,
277  label& tetFacei,
278  label& tetPti
279 )
280 {
281  scalar fraction01 = rnd.globalSample01<scalar>();
282 
283  return setPositionAndCell
284  (
285  mesh,
286  fraction01,
287  rnd,
288  position,
289  cellOwner,
290  tetFacei,
291  tetPti
292  );
293 }
294 
295 
296 Foam::label Foam::patchInjectionBase::whichProc(const scalar fraction01) const
297 {
298  const scalar areaFraction = fraction01*patchArea_;
299 
300  // Determine which processor to inject from
301  forAllReverse(sumTriMagSf_, i)
302  {
303  if (areaFraction >= sumTriMagSf_[i])
304  {
305  return i;
306  }
307  }
308 
309  return 0;
310 }
311 
312 
313 // ************************************************************************* //
volFields.H
Foam::Random
Random number generator.
Definition: Random.H:59
Foam::Random::globalSample01
Type globalSample01()
Return a sample whose components lie in the range [0,1].
Definition: RandomTemplates.C:94
Foam::word
A class for handling words, derived from Foam::string.
Definition: word.H:65
SubField.H
Foam::triangle::randomPoint
Point randomPoint(Random &rndGen) const
Return a random point on the triangle from a uniform.
Definition: triangleI.H:254
Foam::Zero
static constexpr const zero Zero
Global zero (0)
Definition: zero.H:131
Foam::DynamicList< label >
Foam::Random::sample01
Type sample01()
Return a sample whose components lie in the range [0,1].
Definition: RandomTemplates.C:36
Foam::polyMesh::boundaryMesh
const polyBoundaryMesh & boundaryMesh() const
Return boundary mesh.
Definition: polyMesh.H:444
triPointRef.H
polyMesh.H
Foam::DynamicList::clear
void clear() noexcept
Clear the addressed list, i.e. set the size to zero.
Definition: DynamicListI.H:391
Foam::polyMesh
Mesh consisting of general polyhedral cells.
Definition: polyMesh.H:77
polyMeshTetDecomposition.H
Foam::sumOp
Definition: ops.H:213
forAll
#define forAll(list, i)
Loop across all elements in list.
Definition: stdFoam.H:296
Foam::triangle
A triangle primitive used to calculate face normals and swept volumes.
Definition: triangle.H:59
Foam::reduce
void reduce(const List< UPstream::commsStruct > &comms, T &Value, const BinaryOp &bop, const int tag, const label comm)
Definition: PstreamReduceOps.H:51
Foam::patchInjectionBase::patchInjectionBase
patchInjectionBase(const polyMesh &mesh, const word &patchName)
Construct from mesh and patch name.
Definition: patchInjectionBase.C:39
Foam::Field< vector >
Foam::polyPatch
A patch is a list of labels that address the faces in the global face list.
Definition: polyPatch.H:68
Foam::patchInjectionBase::updateMesh
virtual void updateMesh(const polyMesh &mesh)
Update patch geometry and derived info for injection locations.
Definition: patchInjectionBase.C:82
Foam::patchInjectionBase::setPositionAndCell
label setPositionAndCell(const fvMesh &mesh, const scalar fraction01, Random &rnd, vector &position, label &cellOwner, label &tetFacei, label &tetPti)
Set the injection position and owner cell, tetFace and tetPt.
Definition: patchInjectionBase.C:148
Foam::patchInjectionBase::whichProc
label whichProc(const scalar fraction01) const
Return the processor that has the location specified by the fraction.
Definition: patchInjectionBase.C:296
Foam::FatalError
error FatalError
Foam::polyMesh::findCellFacePt
void findCellFacePt(const point &p, label &celli, label &tetFacei, label &tetPti) const
Find the cell, tetFacei and tetPti for point p.
Definition: polyMesh.C:1356
mesh
dynamicFvMesh & mesh
Definition: createDynamicFvMesh.H:6
Foam::fvMesh
Mesh data needed to do the Finite Volume discretisation.
Definition: fvMesh.H:85
patchInjectionBase.H
Foam::maxEqOp
Definition: ops.H:80
Random.H
Foam::exit
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:130
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
Foam::primitiveMesh::cellCentres
const vectorField & cellCentres() const
Definition: primitiveMeshCellCentresAndVols.C:84
FatalErrorInFunction
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:453
Foam::UPstream::myProcNo
static int myProcNo(const label communicator=worldComm)
Number of this process (starting from masterNo() = 0)
Definition: UPstream.H:463
Foam::nl
constexpr char nl
Definition: Ostream.H:404
Foam::triFace
A triangular face using a FixedList of labels corresponding to mesh vertices.
Definition: triFace.H:69
f
labelList f(nPoints)
Foam::Random::position
Type position(const Type &start, const Type &end)
Return a sample on the interval [start,end].
Definition: RandomTemplates.C:62
Foam::foamVersion::patch
const std::string patch
OpenFOAM patch number as a std::string.
Foam::Vector< scalar >
Foam::patchInjectionBase
Definition: patchInjectionBase.H:64
Foam::List
A 1D array of objects of type <T>, where the size of the vector is known and used for subscript bound...
Definition: BitOps.H:63
Foam::pTraits
A traits class, which is primarily used for primitives.
Definition: pTraits.H:56
Foam::mag
dimensioned< typename typeOfMag< Type >::type > mag(const dimensioned< Type > &dt)
points
const pointField & points
Definition: gmvOutputHeader.H:1
Foam::sum
dimensioned< Type > sum(const DimensionedField< Type, GeoMesh > &df)
Definition: DimensionedFieldFunctions.C:327
Foam::polyMeshTetDecomposition::cellTetIndices
static List< tetIndices > cellTetIndices(const polyMesh &mesh, label cI)
Return the tet decomposition of the given cell, see.
Definition: polyMeshTetDecomposition.C:566
forAllReverse
#define forAllReverse(list, i)
Reverse loop across all elements in list.
Definition: stdFoam.H:309
Foam::face
A face is a list of labels corresponding to mesh vertices.
Definition: face.H:72
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::polyMesh::findTetFacePt
void findTetFacePt(const label celli, const point &p, label &tetFacei, label &tetPti) const
Find the tetFacei and tetPti for point p in celli.
Definition: polyMesh.C:1381
triFace
face triFace(3)
Foam::fvMesh::V
const DimensionedField< scalar, volMesh > & V() const
Return cell volumes.
Definition: fvMeshGeometry.C:179