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