edgeMesh.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) 2015-2021 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 "edgeMesh.H"
30#include "bitSet.H"
31#include "edgeHashes.H"
32#include "mergePoints.H"
33#include "ListOps.H"
36
37// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
38
39namespace Foam
40{
44}
45
46
47// * * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * //
48
50{
51 return wordHashSet(*fileExtensionConstructorTablePtr_);
52}
53
54
56{
57 return wordHashSet(*writefileExtensionMemberFunctionTablePtr_);
58}
59
60
61bool Foam::edgeMesh::canReadType(const word& fileType, bool verbose)
62{
63 return checkSupport
64 (
65 readTypes(),
66 fileType,
67 verbose,
68 "reading"
69 );
70}
71
72
73bool Foam::edgeMesh::canWriteType(const word& fileType, bool verbose)
74{
75 return checkSupport
76 (
77 writeTypes(),
78 fileType,
79 verbose,
80 "writing"
81 );
82}
83
84
85bool Foam::edgeMesh::canRead(const fileName& name, bool verbose)
86{
87 word ext(name.ext());
88 if (ext == "gz")
89 {
90 ext = name.lessExt().ext();
91 }
92 return canReadType(ext, verbose);
93}
94
95
96// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
97
98void Foam::edgeMesh::calcPointEdges() const
99{
100 if (pointEdgesPtr_)
101 {
103 << "pointEdges already calculated."
104 << abort(FatalError);
105 }
106
107 pointEdgesPtr_.reset(new labelListList(points_.size()));
108 auto& pointEdges = *pointEdgesPtr_;
109
110 invertManyToMany(pointEdges.size(), edges_, pointEdges);
111}
112
113
114// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
115
117{
118 points_.clear();
119 edges_.clear();
120 pointEdgesPtr_.reset(nullptr);
121}
122
123
125{
126 if (&mesh == this)
127 {
128 return; // Self-transfer is a no-op
129 }
130
131 points_.transfer(mesh.points_);
132 edges_.transfer(mesh.edges_);
133 pointEdgesPtr_ = std::move(mesh.pointEdgesPtr_);
134}
135
136
137Foam::label Foam::edgeMesh::regions(labelList& edgeRegion) const
138{
139 edgeRegion.setSize(edges_.size());
140 edgeRegion = -1;
141
142 label startEdgeI = 0;
143 label currentRegion = 0;
144
145 while (true)
146 {
147 while (startEdgeI < edges_.size() && edgeRegion[startEdgeI] != -1)
148 {
149 startEdgeI++;
150 }
151
152 if (startEdgeI == edges_.size())
153 {
154 break;
155 }
156
157 // Found edge that has not yet been assigned a region.
158 // Mark connected region with currentRegion starting at startEdgeI.
159
160 edgeRegion[startEdgeI] = currentRegion;
161 labelList edgesToVisit(1, startEdgeI);
162
163 while (edgesToVisit.size())
164 {
165 // neighbours of current edgesToVisit
166 DynamicList<label> newEdgesToVisit(edgesToVisit.size());
167
168 // Mark all point connected edges with current region.
169 forAll(edgesToVisit, i)
170 {
171 label edgeI = edgesToVisit[i];
172
173 // Mark connected edges
174 const edge& e = edges_[edgeI];
175
176 forAll(e, fp)
177 {
178 const labelList& pEdges = pointEdges()[e[fp]];
179
180 forAll(pEdges, pEdgeI)
181 {
182 label nbrEdgeI = pEdges[pEdgeI];
183
184 if (edgeRegion[nbrEdgeI] == -1)
185 {
186 edgeRegion[nbrEdgeI] = currentRegion;
187 newEdgesToVisit.append(nbrEdgeI);
188 }
189 }
190 }
191 }
192
193 edgesToVisit.transfer(newEdgesToVisit);
194 }
195
196 currentRegion++;
197 }
198
199 return currentRegion;
200}
201
202
203void Foam::edgeMesh::scalePoints(const scalar scaleFactor)
204{
205 // avoid bad scaling
206 if (scaleFactor > VSMALL && !equal(scaleFactor, 1))
207 {
208 points_ *= scaleFactor;
209 }
210}
211
212
213void Foam::edgeMesh::mergePoints(const scalar mergeDist)
214{
215 labelList pointMap;
216
217 label nChanged = Foam::inplaceMergePoints
218 (
219 points_,
220 mergeDist,
221 false,
222 pointMap
223 );
224
225 if (nChanged)
226 {
227 pointEdgesPtr_.reset(nullptr); // connectivity change
228
229 for (edge& e : edges_)
230 {
231 e[0] = pointMap[e[0]];
232 e[1] = pointMap[e[1]];
233 }
234 }
235
236 this->mergeEdges();
237}
238
239
241{
242 edgeHashSet uniqEdges(2*edges_.size());
243 bitSet pointIsUsed(points_.size());
244
245 label nUniqEdges = 0;
246 label nUniqPoints = 0;
247 forAll(edges_, edgeI)
248 {
249 const edge& e = edges_[edgeI];
250
251 // Remove degenerate and repeated edges
252 // - reordering (e[0] < e[1]) is not really necessary
253 if (e[0] != e[1] && uniqEdges.insert(e))
254 {
255 if (nUniqEdges != edgeI)
256 {
257 edges_[nUniqEdges] = e;
258 }
259 edges_[nUniqEdges].sort();
260 ++nUniqEdges;
261
262 if (pointIsUsed.set(e[0]))
263 {
264 ++nUniqPoints;
265 }
266 if (pointIsUsed.set(e[1]))
267 {
268 ++nUniqPoints;
269 }
270 }
271 }
272
273 if (debug)
274 {
275 Info<< "Merging duplicate edges: "
276 << (edges_.size() - nUniqEdges)
277 << " edges will be deleted, "
278 << (points_.size() - nUniqPoints)
279 << " unused points will be removed." << endl;
280 }
281
282 if (nUniqEdges < edges_.size())
283 {
284 pointEdgesPtr_.reset(nullptr); // connectivity change
285 edges_.setSize(nUniqEdges); // truncate
286 }
287
288 if (nUniqPoints < points_.size())
289 {
290 pointEdgesPtr_.reset(nullptr); // connectivity change
291
292 // build a oldToNew point-map and rewrite the points.
293 // We can do this simultaneously since the point order is unchanged
294 // and we are only effectively eliminating some entries.
295 labelList pointMap(points_.size(), -1);
296
297 label newId = 0;
298 forAll(pointMap, pointi)
299 {
300 if (pointIsUsed.test(pointi))
301 {
302 pointMap[pointi] = newId;
303
304 if (newId < pointi)
305 {
306 // copy down
307 points_[newId] = points_[pointi];
308 }
309 ++newId;
310 }
311 }
312 points_.setSize(newId);
313
314 // Renumber edges - already sorted (above)
315 forAll(edges_, edgeI)
316 {
317 edge& e = edges_[edgeI];
318
319 e[0] = pointMap[e[0]];
320 e[1] = pointMap[e[1]];
321 }
322 }
323}
324
325
326// ************************************************************************* //
Various functions to operate on Lists.
Macros for easy insertion into member function selection tables.
Macros for easy insertion into run-time selection tables.
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
bool insert(const Key &key)
Insert a new entry, not overwriting existing entries.
Definition: HashSet.H:191
void transfer(List< T > &list)
Definition: List.C:447
void setSize(const label n)
Alias for resize()
Definition: List.H:218
void size(const label n)
Older name for setAddressableSize.
Definition: UList.H:114
A bitSet stores bits (elements with only two states) in packed internal format and supports a variety...
Definition: bitSet.H:66
void set(const bitSet &bitset)
Set specified bits from another bitset.
Definition: bitSetI.H:590
bool test(const label pos) const
Test value at specified position, never auto-vivify entries.
Definition: bitSetI.H:521
Mesh data needed to do the Finite Area discretisation.
Definition: edgeFaMesh.H:56
virtual void mergeEdges()
Merge duplicate edges and eliminate unused points.
Definition: edgeMesh.C:240
static bool canWriteType(const word &fileType, bool verbose=false)
Can we write this file format type?
Definition: edgeMesh.C:73
static wordHashSet writeTypes()
Summary of supported write file types.
Definition: edgeMesh.C:55
virtual void mergePoints(const scalar mergeDist)
Geometric merge points (points within mergeDist) prior to.
Definition: edgeMesh.C:213
static bool canReadType(const word &fileType, bool verbose=false)
Can we read this file format?
Definition: edgeMesh.C:61
static bool canRead(const fileName &name, bool verbose=false)
Can we read this file format?
Definition: edgeMesh.C:85
virtual void clear()
Clear all storage.
Definition: edgeMesh.C:116
virtual void scalePoints(const scalar scaleFactor)
Scale points. A non-positive factor is ignored.
Definition: edgeMesh.C:203
static wordHashSet readTypes()
Summary of supported read file types.
Definition: edgeMesh.C:49
An edge is a list of two point labels. The functionality it provides supports the discretisation on a...
Definition: edge.H:66
A class for handling file names.
Definition: fileName.H:76
const labelList & regions() const
A class for handling words, derived from Foam::string.
Definition: word.H:68
word ext() const
Return file name extension (part after last .)
Definition: word.C:126
word lessExt() const
Return word without extension (part before last .)
Definition: word.C:113
#define defineTypeNameAndDebug(Type, DebugSwitch)
Define the typeName and debug information.
Definition: className.H:121
dynamicFvMesh & mesh
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:453
#define defineMemberFunctionSelectionTable(baseType, funcName, argNames)
Define run-time selection table.
Geometric merging of points. See below.
Namespace for OpenFOAM.
void invertManyToMany(const label len, const UList< InputIntListType > &input, List< OutputIntListType > &output)
Invert many-to-many.
messageStream Info
Information stream (stdout output on master, null elsewhere)
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:372
bool equal(const T &s1, const T &s2)
Compare two values for equality.
Definition: doubleFloat.H:46
List< labelList > labelListList
A List of labelList.
Definition: labelList.H:56
errorManip< error > abort(error &err)
Definition: errorManip.H:144
HashSet< word, Hash< word > > wordHashSet
A HashSet of words, uses string hasher.
Definition: HashSet.H:82
error FatalError
word name(const expressions::valueTypeCode typeCode)
A word representation of a valueTypeCode. Empty for INVALID.
Definition: exprTraits.C:59
label inplaceMergePoints(PointList &points, const scalar mergeTol, const bool verbose, labelList &pointToUnique)
runTime write()
#define defineRunTimeSelectionTable(baseType, argNames)
Define run-time selection table.
volScalarField & e
Definition: createFields.H:11
#define forAll(list, i)
Loop across all elements in list.
Definition: stdFoam.H:333