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-------------------------------------------------------------------------------
11License
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
34const 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// ************************************************************************* //
A 1D vector of objects of type <T> that resizes itself as necessary to accept the new objects.
Definition: DynamicList.H:72
void append(const T &val)
Copy append an element to the end of this list.
Definition: DynamicListI.H:503
const T & lookup(const Key &key, const T &deflt) const
Return hashed entry if it exists, or return the given default.
Definition: HashTableI.H:224
void transfer(List< T > &list)
Definition: List.C:447
A HashTable to objects of type <T> with a label key.
Definition: Map.H:60
const Field< point_type > & localPoints() const
Return pointField of points in patch.
const labelListList & faceEdges() const
Return face-edge addressing.
const List< face_type > & localFaces() const
Return patch faces addressing into local point list.
void size(const label n)
Older name for setAddressableSize.
Definition: UList.H:114
const faceList & enrichedFaces() const
Return enriched faces.
const Map< label > & pointMergeMap() const
Return map of point merges.
void calcEnrichedFaces(const labelListList &pointsIntoMasterEdges, const labelListList &pointsIntoSlaveEdges, const pointField &projectedSlavePoints)
Calculate enriched faces.
const Map< point > & pointMap() const
Return map of points.
bool checkSupport() const
Check if the patch is fully supported.
A face is a list of labels corresponding to mesh vertices.
Definition: face.H:75
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:453
label max(const labelHashSet &set, label maxValue=labelMin)
Find the max value in labelHashSet, optionally limited by second argument.
Definition: hashSets.C:47
messageStream Info
Information stream (stdout output on master, null elsewhere)
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:372
label min(const labelHashSet &set, label minValue=labelMax)
Find the min value in labelHashSet, optionally limited by second argument.
Definition: hashSets.C:33
errorManip< error > abort(error &err)
Definition: errorManip.H:144
error FatalError
List< face > faceList
A List of faces.
Definition: faceListFwd.H:47
dimensioned< typename typeOfMag< Type >::type > magSqr(const dimensioned< Type > &dt)
constexpr char nl
The newline '\n' character (0x0a)
Definition: Ostream.H:53
volScalarField & e
Definition: createFields.H:11
#define forAll(list, i)
Loop across all elements in list.
Definition: stdFoam.H:333