triangulatedPatch.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) 2023-2024 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 "triangulatedPatch.H"
29 
30 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
31 
32 bool Foam::triangulatedPatch::randomPoint
33 (
34  Random& rnd,
35  const scalar c,
36  point& result,
37  label& facei,
38  label& celli
39 ) const
40 {
41  result = point::min;
42  facei = -1;
43  celli = -1;
44 
45  if (triWght_.empty() || c < triWght_.front() || c > triWght_.back())
46  {
47  return false;
48  }
49 
50  // Find corresponding decomposed face triangle
51  // Note: triWght_ is sized nTri+1 (zero added at start)
52  //
53  // TBD: binary search with findLower(triWght_, c) ??
54  label trii = 0;
55  for (label i = 0; i < triWght_.size() - 1; ++i)
56  {
57  if (c > triWght_[i] && c <= triWght_[i+1])
58  {
59  trii = i;
60  break;
61  }
62  }
63 
64  // Find random point in triangle
65  const pointField& points = patch_.points();
66 
67  result = triFace_[trii].tri(points).randomPoint(rnd);
68  facei = triFace_[trii].index();
69  celli = patch_.faceCells()[facei];
70 
71  if (perturbTol_ > 0)
72  {
73  const polyMesh& mesh = patch_.boundaryMesh().mesh();
74  const point& cc = mesh.cellCentres()[celli];
75 
76  // Normal points out of domain => subtract correction
77  const vector& n = patch_.faceNormals()[facei];
78  result -= perturbTol_*n*mag(n & (cc - result));
79 
80  // Reset facei - point no longer resides on the face
81  facei = -1;
82  }
83 
84  return true;
85 }
86 
87 
88 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
89 
91 (
92  const polyPatch& patch,
93  const scalar perturbTol
94 )
95 :
96  patch_(patch),
97  perturbTol_(perturbTol),
98  triFace_(),
99  triWght_()
100 {
101  update();
102 }
103 
104 
106 (
107  const polyMesh& mesh,
108  const word& patchName,
109  const scalar perturbTol
110 )
111 :
112  triangulatedPatch(mesh.boundaryMesh()[patchName], perturbTol)
113 {}
114 
115 
116 // * * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * //
117 
118 void Foam::triangulatedPatch::triangulate
119 (
120  const polyPatch& pp,
121  List<labelledTri>& tris
122 )
123 {
124  const pointField& points = pp.points();
125 
126  // Triangulate the patch faces and create addressing
127  label nTris = 0;
128  for (const face& f : pp)
129  {
130  nTris += f.nTriangles();
131  }
132 
133  DynamicList<labelledTri> dynTris(nTris);
134  DynamicList<face> tfaces(8); // work array
135 
136  label facei = 0;
137  for (const face& f : pp)
138  {
139  tfaces.clear();
140  f.triangles(points, tfaces);
141 
142  for (const auto& t : tfaces)
143  {
144  dynTris.emplace_back(t[0], t[1], t[2], facei);
145  }
146  ++facei;
147  }
148 
149  tris.transfer(dynTris);
150 }
151 
152 
153 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
154 
155 void Foam::triangulatedPatch::update()
156 {
157  triFace_.clear();
158  triWght_.clear();
159 
160  triangulate(patch_, triFace_);
161 
162  const pointField& points = patch_.points();
163 
164  const label myProci = UPstream::myProcNo();
165  const label numProc = UPstream::nProcs();
166 
167  // Calculate the cumulative triangle weights
168  triWght_.resize_nocopy(triFace_.size()+1);
169 
170  auto iter = triWght_.begin();
171 
172  // Set zero value at the start of the tri area/weight list
173  scalar patchArea = 0;
174  *iter++ = patchArea;
175 
176  // Calculate cumulative and total area (processor-local at this point)
177  for (const auto& t : triFace_)
178  {
179  patchArea += t.mag(points);
180  *iter++ = patchArea;
181  }
182 
183  scalarList procSumArea(numProc+1);
184  procSumArea[0] = 0;
185 
186  {
187  scalarList::subList slice(procSumArea, numProc, 1);
188  slice[myProci] = patchArea;
189  Pstream::allGatherList(slice);
190  }
191 
192  // Convert to cumulative
193  for (label i = 1; i < procSumArea.size(); ++i)
194  {
195  procSumArea[i] += procSumArea[i-1];
196  }
197 
198  const scalar offset = procSumArea[myProci];
199  const scalar totalArea = procSumArea.back();
200 
201  // Apply processor offset and normalise - for a global 0-1 interval
202  for (scalar& w : triWght_)
203  {
204  w = (w + offset) / totalArea;
205  }
206 }
207 
208 
210 (
211  Random& rnd,
212  point& result,
213  label& facei,
214  label& celli
215 ) const
216 {
217  if (triWght_.empty())
218  {
219  result = point::min;
220  facei = -1;
221  celli = -1;
222  return false;
223  }
224 
225  const scalar c = rnd.position<scalar>(triWght_.front(), triWght_.back());
226 
227  return randomPoint(rnd, c, result, facei, celli);
228 }
229 
230 
232 (
233  Random& rnd,
234  point& result,
235  label& facei,
236  label& celli
237 ) const
238 {
239  if (UPstream::parRun())
240  {
241  const scalar c = rnd.sample01<scalar>();
242  const bool ok = randomPoint(rnd, c, result, facei, celli);
243 
245 
246  // Select the first valid processor
247  label proci = valid.find(true);
248  Pstream::broadcast(proci);
249 
250  return (proci == UPstream::myProcNo());
251  }
252  else
253  {
254  return randomLocalPoint(rnd, result, facei, celli);
255  }
256 }
257 
258 
259 // ************************************************************************* //
triangulatedPatch(const polyPatch &patch, const scalar perturbTol)
Constructors.
List< scalar > scalarList
List of scalar.
Definition: scalarList.H:32
void size(const label n)
Older name for setAddressableSize.
Definition: UList.H:116
dimensioned< typename typeOfMag< Type >::type > mag(const dimensioned< Type > &dt)
bool empty() const noexcept
True if List is empty (ie, size() is zero)
Definition: UList.H:675
T & front()
Access first element of the list, position [0].
Definition: UListI.H:230
Addressing for all faces on surface of mesh. Can either be read from polyMesh or from triSurface...
Definition: boundaryMesh.H:58
static List< T > listGatherValues(const T &localValue, const label communicator=worldComm)
Gather individual values into list locations.
static bool & parRun() noexcept
Test if this a parallel run.
Definition: UPstream.H:1061
SubList< scalar > subList
Declare type of subList.
Definition: List.H:144
static int myProcNo(const label communicator=worldComm)
Rank of this process in the communicator (starting from masterNo()). Can be negative if the process i...
Definition: UPstream.H:1086
static void broadcast(Type &value, const label comm=UPstream::worldComm)
Broadcast content (contiguous or non-contiguous) to all communicator ranks. Does nothing in non-paral...
const Field< point_type > & faceNormals() const
Return face unit normals for patch.
static label nProcs(const label communicator=worldComm)
Number of ranks in parallel run (for given communicator). It is 1 for serial run. ...
Definition: UPstream.H:1077
vectorField pointField
pointField is a vectorField.
Definition: pointFieldFwd.H:38
Type sample01()
Return a sample whose components lie in the range [0,1].
dynamicFvMesh & mesh
const pointField & points
const polyBoundaryMesh & boundaryMesh() const noexcept
Return boundaryMesh reference.
Definition: polyPatch.C:295
const labelUList & faceCells() const
Return face-cell addressing.
Definition: polyPatch.C:382
const polyMesh & mesh() const noexcept
Return the mesh reference.
A class for handling words, derived from Foam::string.
Definition: word.H:63
bool randomLocalPoint(Random &rnd, point &result, label &facei, label &celli) const
Set a random point on the local patch.
bool randomGlobalPoint(Random &rnd, point &result, label &facei, label &celli) const
Set a global random point on the patch.
Vector< scalar > vector
Definition: vector.H:57
const Field< point_type > & points() const noexcept
Return reference to global points.
label min(const labelHashSet &set, label minValue=labelMax)
Find the min value in labelHashSet, optionally limited by second argument.
Definition: hashSets.C:26
Random number generator.
Definition: Random.H:55
A Vector of values with scalar precision, where scalar is float/double depending on the compilation f...
mesh update()
labelList f(nPoints)
T & emplace_back(Args &&... args)
Construct an element at the end of the list, return reference to the new list element.
Definition: ListI.H:205
static void allGatherList(UList< T > &values, const int tag=UPstream::msgType(), const label comm=UPstream::worldComm)
Gather data, but keep individual values separate. Uses MPI_Allgather or manual linear/tree communicat...
Performs a triangulation of a patch to return randomised point locations.
vector point
Point is a vector.
Definition: point.H:37
const dimensionedScalar c
Speed of light in a vacuum.
const std::string patch
OpenFOAM patch number as a std::string.
T & back()
Access last element of the list, position [size()-1].
Definition: UListI.H:244
label n
Mesh consisting of general polyhedral cells.
Definition: polyMesh.H:75
A patch is a list of labels that address the faces in the global face list.
Definition: polyPatch.H:69
uindirectPrimitivePatch pp(UIndirectList< face >(mesh.faces(), faceLabels), mesh.points())