enrichedPatchFaces.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) 2011-2016 OpenFOAM Foundation
9  Copyright (C) 2017-2020 OpenCFD Ltd.
10 -------------------------------------------------------------------------------
11 License
12  This file is part of OpenFOAM.
13 
14  OpenFOAM is free software: you can redistribute it and/or modify it
15  under the terms of the GNU General Public License as published by
16  the Free Software Foundation, either version 3 of the License, or
17  (at your option) any later version.
18 
19  OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
20  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
21  FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
22  for more details.
23 
24  You should have received a copy of the GNU General Public License
25  along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
26 
27 \*---------------------------------------------------------------------------*/
28 
29 #include "enrichedPatch.H"
30 #include "DynamicList.H"
31 
32 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
33 
34 const Foam::label Foam::enrichedPatch::enrichedFaceRatio_ = 3;
35 
36 
37 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
38 
40 (
41  const labelListList& pointsIntoMasterEdges,
42  const labelListList& pointsIntoSlaveEdges,
43  const pointField& projectedSlavePoints
44 )
45 {
46  if (enrichedFacesPtr_)
47  {
49  << "Enriched faces already calculated."
50  << abort(FatalError);
51  }
52 
53  // Create a list of enriched faces
54  // Algorithm:
55  // 1) Grab the original face and start from point zero.
56  // 2) If the point has been merged away, grab the merge label;
57  // otherwise, keep the original label.
58  // 3) Go to the next edge. Collect all the points to be added along
59  // the edge; order them in the necessary direction and insert onto the
60  // face.
61  // 4) Grab the next point and return on step 2.
62  enrichedFacesPtr_.reset
63  (
64  new faceList(masterPatch_.size() + slavePatch_.size())
65  );
66  auto& enrichedFaces = *enrichedFacesPtr_;
67 
68  label nEnrichedFaces = 0;
69 
70  const pointField& masterLocalPoints = masterPatch_.localPoints();
71  const faceList& masterLocalFaces = masterPatch_.localFaces();
72  const labelListList& masterFaceEdges = masterPatch_.faceEdges();
73 
74  const faceList& slaveLocalFaces = slavePatch_.localFaces();
75  const labelListList& slaveFaceEdges = slavePatch_.faceEdges();
76 
77  // For correct functioning of the enrichedPatch class, the slave
78  // faces need to be inserted first. See comments in
79  // enrichedPatch.H
80 
81  // Get reference to the point merge map
82  const Map<label>& pmm = pointMergeMap();
83 
84  // Add slave faces into the enriched faces list
85 
86  forAll(slavePatch_, facei)
87  {
88  const face& oldFace = slavePatch_[facei];
89  const face& oldLocalFace = slaveLocalFaces[facei];
90  const labelList& curEdges = slaveFaceEdges[facei];
91 
92  // Info<< "old slave face[" << facei << "] " << oldFace << endl;
93 
94  DynamicList<label> newFace(oldFace.size()*enrichedFaceRatio_);
95 
96  // Note: The number of points and edges in a face is always identical
97  // so both can be done is the same loop
98  forAll(oldFace, i)
99  {
100  // Add the point.
101  // Using the mapped point id if possible
102 
103  const label mappedPointi = pmm.lookup(oldFace[i], oldFace[i]);
104 
105  newFace.append(mappedPointi);
106 
107  // Add the projected point into the patch support
108  pointMap().insert
109  (
110  mappedPointi, // Global label of point
111  projectedSlavePoints[oldLocalFace[i]] // Projected position
112  );
113 
114  // Grab the edge points
115 
116  const labelList& pointsOnEdge =
117  pointsIntoSlaveEdges[curEdges[i]];
118 
119  // Info<< "slave pointsOnEdge for "
120  // << curEdges[i] << ": " << pointsOnEdge
121  // << endl;
122 
123  // If there are no points on the edge, skip everything
124  // If there is only one point, no need for sorting
125  if (pointsOnEdge.size())
126  {
127  // Sort edge points in order
128  scalarField weightOnEdge(pointsOnEdge.size());
129 
130  const point& startPoint =
131  projectedSlavePoints[oldLocalFace[i]];
132 
133  const point& endPoint =
134  projectedSlavePoints[oldLocalFace.nextLabel(i)];
135 
136  vector e = (endPoint - startPoint);
137 
138  const scalar magSqrE = magSqr(e);
139 
140  if (magSqrE > SMALL)
141  {
142  e /= magSqrE;
143  }
144  else
145  {
147  << "Zero length edge in slave patch for face " << i
148  << ". This is not allowed."
149  << abort(FatalError);
150  }
151 
152  pointField positionOnEdge(pointsOnEdge.size());
153 
154  forAll(pointsOnEdge, edgePointi)
155  {
156  positionOnEdge[edgePointi] =
157  pointMap()[pointsOnEdge[edgePointi]];
158 
159  weightOnEdge[edgePointi] =
160  (
161  e
162  &
163  (
164  positionOnEdge[edgePointi]
165  - startPoint
166  )
167  );
168  }
169 
170  if (debug)
171  {
172  // Check weights: all new points should be on the edge
173  if (min(weightOnEdge) < 0 || max(weightOnEdge) > 1)
174  {
176  << " not on the edge for edge " << curEdges[i]
177  << " of face " << facei << " in slave patch." << nl
178  << "Min weight: " << min(weightOnEdge)
179  << " Max weight: " << max(weightOnEdge)
180  << abort(FatalError);
181  }
182  }
183 
184  // Go through the points and collect them based on
185  // weights from lower to higher. This gives the
186  // correct order of points along the edge.
187  forAll(weightOnEdge, passI)
188  {
189  // Max weight can only be one, so the sorting is
190  // done by elimination.
191  label nextPoint = -1;
192  scalar dist = 2;
193 
194  forAll(weightOnEdge, wI)
195  {
196  if (weightOnEdge[wI] < dist)
197  {
198  dist = weightOnEdge[wI];
199  nextPoint = wI;
200  }
201  }
202 
203  // Insert the next point and reset its weight to exclude it
204  // from future picks
205  newFace.append(pointsOnEdge[nextPoint]);
206  weightOnEdge[nextPoint] = GREAT;
207 
208  // Add the point into patch support
209  pointMap().insert
210  (
211  pointsOnEdge[nextPoint],
212  positionOnEdge[nextPoint]
213  );
214  }
215  }
216  }
217 
218  // Info<< "New slave face[" << facei << "] "
219  // << flatOutput(newFace) << " was " << flatOutput(oldFace)
220  // << endl;
221 
222  // Add the new face to the list
223  enrichedFaces[nEnrichedFaces].transfer(newFace);
224  nEnrichedFaces++;
225  }
226 
227 
228  // Add master faces into the enriched faces list
229 
230  forAll(masterPatch_, facei)
231  {
232  const face& oldFace = masterPatch_[facei];
233  const face& oldLocalFace = masterLocalFaces[facei];
234  const labelList& curEdges = masterFaceEdges[facei];
235 
236  // Info<< "old master face[" << facei << "] " << oldFace << endl;
237 
238  DynamicList<label> newFace(oldFace.size()*enrichedFaceRatio_);
239 
240  // Note: The number of points and edges in a face is always identical
241  // so both can be done is the same loop
242  forAll(oldFace, i)
243  {
244  // Add the point.
245  // Using the mapped point id if possible
246 
247  const label mappedPointi = pmm.lookup(oldFace[i], oldFace[i]);
248 
249  newFace.append(mappedPointi);
250 
251  // Add the point into patch support
252  pointMap().insert
253  (
254  mappedPointi, // Global label of point
255  masterLocalPoints[oldLocalFace[i]]
256  );
257 
258  // Grab the edge points
259 
260  const labelList& pointsOnEdge =
261  pointsIntoMasterEdges[curEdges[i]];
262 
263  // If there are no points on the edge, skip everything
264  // If there is only one point, no need for sorting
265  if (pointsOnEdge.size())
266  {
267  // Sort edge points in order
268  scalarField weightOnEdge(pointsOnEdge.size());
269 
270  const point& startPoint =
271  masterLocalPoints[oldLocalFace[i]];
272 
273  const point& endPoint =
274  masterLocalPoints[oldLocalFace.nextLabel(i)];
275 
276  vector e = (endPoint - startPoint);
277 
278  const scalar magSqrE = magSqr(e);
279 
280  if (magSqrE > SMALL)
281  {
282  e /= magSqrE;
283  }
284  else
285  {
287  << "Zero length edge in master patch for face " << i
288  << ". This is not allowed."
289  << abort(FatalError);
290  }
291 
292  pointField positionOnEdge(pointsOnEdge.size());
293 
294  forAll(pointsOnEdge, edgePointi)
295  {
296  positionOnEdge[edgePointi] =
297  pointMap()[pointsOnEdge[edgePointi]];
298 
299  weightOnEdge[edgePointi] =
300  (
301  e
302  &
303  (
304  positionOnEdge[edgePointi] - startPoint
305  )
306  );
307  }
308 
309  if (debug)
310  {
311  // Check weights: all new points should be on the edge
312  if (min(weightOnEdge) < 0 || max(weightOnEdge) > 1)
313  {
315  << " not on the edge for edge " << curEdges[i]
316  << " of face " << facei << " in master patch." << nl
317  << "Min weight: " << min(weightOnEdge)
318  << " Max weight: " << max(weightOnEdge)
319  << abort(FatalError);
320  }
321  }
322 
323  // Go through the points and collect them based on
324  // weights from lower to higher. This gives the
325  // correct order of points along the edge.
326  forAll(weightOnEdge, passI)
327  {
328  // Max weight can only be one, so the sorting is
329  // done by elimination.
330  label nextPoint = -1;
331  scalar dist = 2;
332 
333  forAll(weightOnEdge, wI)
334  {
335  if (weightOnEdge[wI] < dist)
336  {
337  dist = weightOnEdge[wI];
338  nextPoint = wI;
339  }
340  }
341 
342  // Insert the next point and reset its weight to exclude it
343  // from future picks
344  newFace.append(pointsOnEdge[nextPoint]);
345  weightOnEdge[nextPoint] = GREAT;
346 
347  // Add the point into patch support
348  pointMap().insert
349  (
350  pointsOnEdge[nextPoint],
351  positionOnEdge[nextPoint]
352  );
353  }
354  }
355  }
356 
357  // Info<< "New master face[" << facei << "] "
358  // << flatOutput(newFace) << " was " << flatOutput(oldFace)
359  // << endl;
360 
361  // Add the new face to the list
362  enrichedFaces[nEnrichedFaces].transfer(newFace);
363  nEnrichedFaces++;
364  }
365 
366  // Check the support for the enriched patch
367  if (debug)
368  {
369  if (!checkSupport())
370  {
371  Info<< "Enriched patch support OK. Slave faces: "
372  << slavePatch_.size() << " Master faces: "
373  << masterPatch_.size() << endl;
374  }
375  else
376  {
378  << "Error in enriched patch support"
379  << abort(FatalError);
380  }
381  }
382 }
383 
384 
385 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
386 
388 {
389  if (!enrichedFacesPtr_)
390  {
392  << "void enrichedPatch::calcEnrichedFaces\n"
393  << "(\n"
394  << " const labelListList& pointsIntoMasterEdges,\n"
395  << " const labelListList& pointsIntoSlaveEdges,\n"
396  << " const pointField& projectedSlavePoints\n"
397  << ")"
398  << " before trying to access faces."
399  << abort(FatalError);
400  }
401 
402  return *enrichedFacesPtr_;
403 }
404 
405 
406 // ************************************************************************* //
Foam::expressions::patchExpr::debug
int debug
Static debugging option.
Foam::DynamicList< label >
Foam::enrichedPatch::calcEnrichedFaces
void calcEnrichedFaces(const labelListList &pointsIntoMasterEdges, const labelListList &pointsIntoSlaveEdges, const pointField &projectedSlavePoints)
Calculate enriched faces.
Definition: enrichedPatchFaces.C:40
Foam::Map< label >
Foam::endl
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:369
Foam::min
label min(const labelHashSet &set, label minValue=labelMax)
Find the min value in labelHashSet, optionally limited by second argument.
Definition: hashSets.C:33
forAll
#define forAll(list, i)
Loop across all elements in list.
Definition: stdFoam.H:296
Foam::magSqr
dimensioned< typename typeOfMag< Type >::type > magSqr(const dimensioned< Type > &dt)
Foam::Field< vector >
Foam::Info
messageStream Info
Information stream (stdout output on master, null elsewhere)
Foam::max
label max(const labelHashSet &set, label maxValue=labelMin)
Find the max value in labelHashSet, optionally limited by second argument.
Definition: hashSets.C:47
Foam::FatalError
error FatalError
Foam::enrichedPatch::enrichedFaces
const faceList & enrichedFaces() const
Return enriched faces.
Definition: enrichedPatchFaces.C:387
Foam::abort
errorManip< error > abort(error &err)
Definition: errorManip.H:144
FatalErrorInFunction
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:453
Foam::nl
constexpr char nl
Definition: Ostream.H:404
Foam::faceList
List< face > faceList
A List of faces.
Definition: faceListFwd.H:47
Foam::Vector< scalar >
Foam::List< labelList >
Foam::constant::electromagnetic::e
const dimensionedScalar e
Elementary charge.
Definition: createFields.H:11
Foam::face
A face is a list of labels corresponding to mesh vertices.
Definition: face.H:72
DynamicList.H
enrichedPatch.H