1 /*---------------------------------------------------------------------------*\
3 \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
5 \\ / A nd | Copyright (C) 2004-2010 OpenCFD Ltd.
7 -------------------------------------------------------------------------------
9 This file is part of OpenFOAM.
11 OpenFOAM is free software: you can redistribute it and/or modify it
12 under the terms of the GNU General Public License as published by
13 the Free Software Foundation, either version 3 of the License, or
14 (at your option) any later version.
16 OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
17 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
18 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
21 You should have received a copy of the GNU General Public License
22 along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
24 \*---------------------------------------------------------------------------*/
26 #include "primitiveMesh.H"
27 #include "DynamicList.H"
28 #include "demandDrivenData.H"
29 #include "SortableList.H"
32 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
34 // Returns edgeI between two points.
35 Foam::label Foam::primitiveMesh::getEdge
37 List<DynamicList<label> >& pe,
38 DynamicList<edge>& es,
41 const label nextPointI
44 // Find connection between pointI and nextPointI
45 forAll(pe[pointI], ppI)
47 label eI = pe[pointI][ppI];
49 const edge& e = es[eI];
51 if (e.start() == nextPointI || e.end() == nextPointI)
58 label edgeI = es.size();
59 pe[pointI].append(edgeI);
60 pe[nextPointI].append(edgeI);
61 if (pointI < nextPointI)
63 es.append(edge(pointI, nextPointI));
67 es.append(edge(nextPointI, pointI));
73 void Foam::primitiveMesh::calcEdges(const bool doFaceEdges) const
77 Pout<< "primitiveMesh::calcEdges(const bool) : "
78 << "calculating edges, pointEdges and optionally faceEdges"
82 // It is an error to attempt to recalculate edges
83 // if the pointer is already set
84 if ((edgesPtr_ || pePtr_) || (doFaceEdges && fePtr_))
86 FatalErrorIn("primitiveMesh::calcEdges(const bool) const")
87 << "edges or pointEdges or faceEdges already calculated"
93 // Go through the faces list. Search pointEdges for existing edge.
94 // If not found create edge and add to pointEdges.
95 // In second loop sort edges in order of increasing neighbouring
97 // This algorithm replaces the one using pointFaces which used more
98 // allocations but less memory and was on practical cases
99 // quite a bit slower.
101 const faceList& fcs = faces();
106 // Estimate pointEdges storage
107 List<DynamicList<label> > pe(nPoints());
110 pe[pointI].setCapacity(primitiveMesh::edgesPerPoint_);
113 // Estimate edges storage
114 DynamicList<edge> es(pe.size()*primitiveMesh::edgesPerPoint_/2);
116 // Estimate faceEdges storage
119 fePtr_ = new labelListList(fcs.size());
120 labelListList& faceEdges = *fePtr_;
123 faceEdges[faceI].setSize(fcs[faceI].size());
128 // Find consecutive face points in edge list
129 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
131 // Edges on boundary faces
133 // Edges using no boundary point
134 nInternal0Edges_ = 0;
135 // Edges using 1 boundary point
136 label nInt1Edges = 0;
137 // Edges using two boundary points but not on boundary face:
138 // edges.size()-nExtEdges-nInternal0Edges_-nInt1Edges
140 // Ordering is different if points are ordered.
141 if (nInternalPoints_ == -1)
143 // No ordering. No distinction between types.
146 const face& f = fcs[faceI];
150 label pointI = f[fp];
151 label nextPointI = f[f.fcIndex(fp)];
153 label edgeI = getEdge(pe, es, pointI, nextPointI);
157 (*fePtr_)[faceI][fp] = edgeI;
161 // Assume all edges internal
163 nInternal0Edges_ = es.size();
168 // 1. Do external faces first. This creates external edges.
169 for (label faceI = nInternalFaces_; faceI < fcs.size(); faceI++)
171 const face& f = fcs[faceI];
175 label pointI = f[fp];
176 label nextPointI = f[f.fcIndex(fp)];
178 label oldNEdges = es.size();
179 label edgeI = getEdge(pe, es, pointI, nextPointI);
181 if (es.size() > oldNEdges)
187 (*fePtr_)[faceI][fp] = edgeI;
192 // 2. Do internal faces. This creates internal edges.
193 for (label faceI = 0; faceI < nInternalFaces_; faceI++)
195 const face& f = fcs[faceI];
199 label pointI = f[fp];
200 label nextPointI = f[f.fcIndex(fp)];
202 label oldNEdges = es.size();
203 label edgeI = getEdge(pe, es, pointI, nextPointI);
205 if (es.size() > oldNEdges)
207 if (pointI < nInternalPoints_)
209 if (nextPointI < nInternalPoints_)
220 if (nextPointI < nInternalPoints_)
226 // Internal edge with two points on boundary
232 (*fePtr_)[faceI][fp] = edgeI;
239 // For unsorted meshes the edges will be in order of occurrence inside
240 // the faces. For sorted meshes the first nExtEdges will be the external
243 if (nInternalPoints_ != -1)
245 nInternalEdges_ = es.size()-nExtEdges;
246 nInternal1Edges_ = nInternal0Edges_+nInt1Edges;
248 //Pout<< "Edge overview:" << nl
249 // << " total number of edges : " << es.size()
251 // << " boundary edges : " << nExtEdges
253 // << " edges using no boundary point : "
254 // << nInternal0Edges_
256 // << " edges using one boundary points : " << nInt1Edges
258 // << " edges using two boundary points : "
259 // << es.size()-nExtEdges-nInternal0Edges_-nInt1Edges << endl;
263 // Like faces sort edges in order of increasing neigbouring point.
264 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
265 // Automatically if points are sorted into internal and external points
266 // the edges will be sorted into
267 // - internal point to internal point
268 // - internal point to external point
269 // - external point to external point
270 // The problem is that the last one mixes external edges with internal
271 // edges with two points on the boundary.
274 // Map to sort into new upper-triangular order
275 labelList oldToNew(es.size());
281 // start of edges with 0 boundary points
282 label internal0EdgeI = 0;
284 // start of edges with 1 boundary points
285 label internal1EdgeI = nInternal0Edges_;
287 // start of edges with 2 boundary points
288 label internal2EdgeI = nInternal1Edges_;
290 // start of external edges
291 label externalEdgeI = nInternalEdges_;
294 // To sort neighbouring points in increasing order. Defined outside
295 // for optimisation reasons: if all connectivity size same will need
297 SortableList<label> nbrPoints(primitiveMesh::edgesPerPoint_);
301 const DynamicList<label>& pEdges = pe[pointI];
303 nbrPoints.setSize(pEdges.size());
307 const edge& e = es[pEdges[i]];
309 label nbrPointI = e.otherVertex(pointI);
311 if (nbrPointI < pointI)
317 nbrPoints[i] = nbrPointI;
323 if (nInternalPoints_ == -1)
325 // Sort all upper-triangular
328 if (nbrPoints[i] != -1)
330 label edgeI = pEdges[nbrPoints.indices()[i]];
332 oldToNew[edgeI] = internal0EdgeI++;
338 if (pointI < nInternalPoints_)
342 label nbrPointI = nbrPoints[i];
344 label edgeI = pEdges[nbrPoints.indices()[i]];
348 if (edgeI < nExtEdges)
351 oldToNew[edgeI] = externalEdgeI++;
353 else if (nbrPointI < nInternalPoints_)
355 // Both points inside
356 oldToNew[edgeI] = internal0EdgeI++;
360 // One points inside, one outside
361 oldToNew[edgeI] = internal1EdgeI++;
370 label nbrPointI = nbrPoints[i];
372 label edgeI = pEdges[nbrPoints.indices()[i]];
376 if (edgeI < nExtEdges)
379 oldToNew[edgeI] = externalEdgeI++;
381 else if (nbrPointI < nInternalPoints_)
384 FatalErrorIn("primitiveMesh::calcEdges(..)")
385 << abort(FatalError);
389 // Both points outside
390 oldToNew[edgeI] = internal2EdgeI++;
401 label edgeI = findIndex(oldToNew, -1);
405 const edge& e = es[edgeI];
407 FatalErrorIn("primitiveMesh::calcEdges(..)")
408 << "Did not sort edge " << edgeI << " points:" << e
409 << " coords:" << points()[e[0]] << points()[e[1]]
411 << "Current buckets:" << endl
412 << " internal0EdgeI:" << internal0EdgeI << endl
413 << " internal1EdgeI:" << internal1EdgeI << endl
414 << " internal2EdgeI:" << internal2EdgeI << endl
415 << " externalEdgeI:" << externalEdgeI << endl
416 << abort(FatalError);
422 // Renumber and transfer.
425 edgesPtr_ = new edgeList(es.size());
426 edgeList& edges = *edgesPtr_;
429 edges[oldToNew[edgeI]] = es[edgeI];
433 pePtr_ = new labelListList(nPoints());
434 labelListList& pointEdges = *pePtr_;
437 DynamicList<label>& pEdges = pe[pointI];
439 inplaceRenumber(oldToNew, pEdges);
440 pointEdges[pointI].transfer(pEdges);
441 Foam::sort(pointEdges[pointI]);
447 labelListList& faceEdges = *fePtr_;
448 forAll(faceEdges, faceI)
450 inplaceRenumber(oldToNew, faceEdges[faceI]);
457 Foam::label Foam::primitiveMesh::findFirstCommonElementFromSortedLists
459 const labelList& list1,
460 const labelList& list2
465 labelList::const_iterator iter1 = list1.begin();
466 labelList::const_iterator iter2 = list2.begin();
468 while (iter1 != list1.end() && iter2 != list2.end())
474 else if (*iter1 > *iter2)
488 "primitiveMesh::findFirstCommonElementFromSortedLists"
489 "(const labelList&, const labelList&)"
490 ) << "No common elements in lists " << list1 << " and " << list2
491 << abort(FatalError);
497 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
499 const Foam::edgeList& Foam::primitiveMesh::edges() const
510 const Foam::labelListList& Foam::primitiveMesh::pointEdges() const
522 const Foam::labelListList& Foam::primitiveMesh::faceEdges() const
528 Pout<< "primitiveMesh::faceEdges() : "
529 << "calculating faceEdges" << endl;
533 const faceList& fcs = faces();
534 const labelListList& pe = pointEdges();
535 const edgeList& es = edges();
537 fePtr_ = new labelListList(fcs.size());
538 labelListList& faceEdges = *fePtr_;
542 const face& f = fcs[faceI];
544 labelList& fEdges = faceEdges[faceI];
545 fEdges.setSize(f.size());
549 label pointI = f[fp];
550 label nextPointI = f[f.fcIndex(fp)];
552 // Find edge between pointI, nextPontI
553 const labelList& pEdges = pe[pointI];
557 label edgeI = pEdges[i];
559 if (es[edgeI].otherVertex(pointI) == nextPointI)
573 void Foam::primitiveMesh::clearOutEdges()
575 deleteDemandDrivenData(edgesPtr_);
576 deleteDemandDrivenData(pePtr_);
577 deleteDemandDrivenData(fePtr_);
583 const Foam::labelList& Foam::primitiveMesh::faceEdges
586 DynamicList<label>& storage
591 return faceEdges()[faceI];
595 const labelListList& pointEs = pointEdges();
596 const face& f = faces()[faceI];
599 if (f.size() > storage.capacity())
601 storage.setCapacity(f.size());
608 findFirstCommonElementFromSortedLists
611 pointEs[f.nextLabel(fp)]
621 const Foam::labelList& Foam::primitiveMesh::faceEdges(const label faceI) const
623 return faceEdges(faceI, labels_);
627 const Foam::labelList& Foam::primitiveMesh::cellEdges
630 DynamicList<label>& storage
635 return cellEdges()[cellI];
639 const labelList& cFaces = cells()[cellI];
645 const labelList& fe = faceEdges(cFaces[i]);
649 labelSet_.insert(fe[feI]);
655 if (labelSet_.size() > storage.capacity())
657 storage.setCapacity(labelSet_.size());
660 forAllConstIter(labelHashSet, labelSet_, iter)
662 storage.append(iter.key());
670 const Foam::labelList& Foam::primitiveMesh::cellEdges(const label cellI) const
672 return cellEdges(cellI, labels_);
676 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
678 // ************************************************************************* //