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  if (cellOwners_.size() > 0)
159  {
160  // Determine which processor to inject from
161  const label proci = whichProc(fraction01);
162 
163  if (Pstream::myProcNo() == proci)
164  {
165  const scalar areaFraction = fraction01*patchArea_;
166 
167  // Find corresponding decomposed face triangle
168  label trii = 0;
169  scalar offset = sumTriMagSf_[proci];
170  forAllReverse(triCumulativeMagSf_, i)
171  {
172  if (areaFraction > triCumulativeMagSf_[i] + offset)
173  {
174  trii = i;
175  break;
176  }
177  }
178 
179  // Set cellOwner
180  label facei = triToFace_[trii];
181  cellOwner = cellOwners_[facei];
182 
183  // Find random point in triangle
184  const polyPatch& patch = mesh.boundaryMesh()[patchId_];
185  const pointField& points = patch.points();
186  const face& tf = triFace_[trii];
187  const triPointRef tri(points[tf[0]], points[tf[1]], points[tf[2]]);
188  const point pf(tri.randomPoint(rnd));
189 
190  // Position perturbed away from face (into domain)
191  const scalar a = rnd.position(scalar(0.1), scalar(0.5));
192  const vector& pc = mesh.cellCentres()[cellOwner];
193  const vector d =
194  mag((pf - pc) & patchNormal_[facei])*patchNormal_[facei];
195 
196  position = pf - a*d;
197 
198  // Try to find tetFacei and tetPti in the current position
199  mesh.findTetFacePt(cellOwner, position, tetFacei, tetPti);
200 
201  // tetFacei and tetPti not found, check if the cell has changed
202  if (tetFacei == -1 ||tetPti == -1)
203  {
204  mesh.findCellFacePt(position, cellOwner, tetFacei, tetPti);
205  }
206 
207  // Both searches failed, choose a random position within
208  // the original cell
209  if (tetFacei == -1 ||tetPti == -1)
210  {
211  // Reset cellOwner
212  cellOwner = cellOwners_[facei];
213  const scalarField& V = mesh.V();
214 
215  // Construct cell tet indices
216  const List<tetIndices> cellTetIs =
218 
219  // Construct cell tet volume fractions
220  scalarList cTetVFrac(cellTetIs.size(), Zero);
221  for (label teti=1; teti<cellTetIs.size()-1; teti++)
222  {
223  cTetVFrac[teti] =
224  cTetVFrac[teti-1]
225  + cellTetIs[teti].tet(mesh).mag()/V[cellOwner];
226  }
227  cTetVFrac.last() = 1;
228 
229  // Set new particle position
230  const scalar volFrac = rnd.sample01<scalar>();
231  label teti = 0;
232  forAll(cTetVFrac, vfI)
233  {
234  if (cTetVFrac[vfI] > volFrac)
235  {
236  teti = vfI;
237  break;
238  }
239  }
240  position = cellTetIs[teti].tet(mesh).randomPoint(rnd);
241  tetFacei = cellTetIs[teti].face();
242  tetPti = cellTetIs[teti].tetPt();
243  }
244  }
245  else
246  {
247  cellOwner = -1;
248  tetFacei = -1;
249  tetPti = -1;
250 
251  // Dummy position
252  position = pTraits<vector>::max;
253  }
254  }
255  else
256  {
257  cellOwner = -1;
258  tetFacei = -1;
259  tetPti = -1;
260 
261  // Dummy position
262  position = pTraits<vector>::max;
263  }
264 }
265 
266 
268 (
269  const fvMesh& mesh,
270  Random& rnd,
271  vector& position,
272  label& cellOwner,
273  label& tetFacei,
274  label& tetPti
275 )
276 {
277  scalar fraction01 = rnd.globalSample01<scalar>();
278 
279  setPositionAndCell
280  (
281  mesh,
282  fraction01,
283  rnd,
284  position,
285  cellOwner,
286  tetFacei,
287  tetPti
288  );
289 }
290 
291 
292 Foam::label Foam::patchInjectionBase::whichProc(const scalar fraction01) const
293 {
294  const scalar areaFraction = fraction01*patchArea_;
295 
296  // Determine which processor to inject from
297  forAllReverse(sumTriMagSf_, i)
298  {
299  if (areaFraction >= sumTriMagSf_[i])
300  {
301  return i;
302  }
303  }
304 
305  return 0;
306 }
307 
308 
309 // ************************************************************************* //
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:62
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::patchInjectionBase::setPositionAndCell
void 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::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:61
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::DynamicList::clear
void clear()
Clear the addressed list, i.e. set the size to zero.
Definition: DynamicListI.H:348
Foam::patchInjectionBase::updateMesh
virtual void updateMesh(const polyMesh &mesh)
Update patch geometry and derived info for injection locations.
Definition: patchInjectionBase.C:82
Foam::patchInjectionBase::whichProc
label whichProc(const scalar fraction01) const
Return the processor that has the location specified by the fraction.
Definition: patchInjectionBase.C:292
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:83
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:381
Foam::UPstream::myProcNo
static int myProcNo(const label communicator=worldComm)
Number of this process (starting from masterNo() = 0)
Definition: UPstream.H:464
Foam::nl
constexpr char nl
Definition: Ostream.H:385
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
Traits class for primitives.
Definition: pTraits.H:54
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:527
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