1 /*---------------------------------------------------------------------------*\
3 \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
5 \\ / A nd | Copyright held by original author
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 the
13 Free Software Foundation; either version 2 of the License, or (at your
14 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, write to the Free Software Foundation,
23 Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
25 \*---------------------------------------------------------------------------*/
27 #include "tetPolyMeshCellDecomp.H"
28 #include "tetPointRef.H"
29 #include "SquareMatrix.H"
31 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
36 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
38 label tetPolyMeshCellDecomp::nPoints() const
42 nPoints_ = mesh_.nPoints() + mesh_.nCells();
49 label tetPolyMeshCellDecomp::nEdges() const
53 nEdges_ = mesh_.nEdges();
55 // add edges going across the face
56 const faceList& f = mesh_.faces();
60 nEdges_ += f[fI].size() - 3;
63 // add point-to-cell edges
64 const labelListList& pc = mesh_.pointCells();
68 nEdges_ += pc[pointI].size();
76 label tetPolyMeshCellDecomp::nTets() const
83 const cellList& polyCells = mesh_.cells();
85 forAll (polyCells, cellI)
87 nTets_ += nTetsForCell(cellI);
95 tmp<pointField> tetPolyMeshCellDecomp::points() const
97 tmp<pointField> ttetPoints(new pointField(nPoints()));
98 pointField& tetPoints = ttetPoints();
100 const pointField& points = mesh_.points();
102 const pointField& cellCentres = mesh_.cellCentres();
106 forAll (points, pointI)
108 tetPoints[tetPointI] = points[pointI];
112 forAll (cellCentres, cellI)
114 tetPoints[tetPointI] = cellCentres[cellI];
122 cellShapeList tetPolyMeshCellDecomp::tetCells() const
124 cellShapeList t(nTets());
126 const cellList& polyCells = mesh_.cells();
130 forAll (polyCells, cellI)
132 tetCellList cellTets = tets(cellI);
134 forAll (cellTets, tetI)
136 t[nTetCells] = cellTets[tetI].tetCellShape();
145 // Return tetrahedral decomposition for cell
146 tetCellList tetPolyMeshCellDecomp::tets(const label cellID) const
148 const unallocFaceList& meshFaces = mesh_.faces();
150 const unallocLabelList& owner = mesh_.faceOwner();
152 // Initialise the size of the return
153 tetCellList t(nTetsForCell(cellID));
157 const labelList& cellFaces = mesh_.cells()[cellID];
159 forAll (cellFaces, faceI)
161 const label curFaceID = cellFaces[faceI];
163 face f = meshFaces[curFaceID];
165 // Take care of owner/neighbour face reversal
166 if (cellID == owner[curFaceID])
171 // Grab the point zero of the face and create triangles by grabbing the
172 // labels around the perimeter
173 label pointZeroID = f[0];
175 for (label i = 1; i < f.size() - 1; i++)
177 // Face is assumed to be inward-pointing
195 void tetPolyMeshCellDecomp::gradNiDotGradNj
198 SquareMatrix<scalar>& denseMatrix,
199 const labelList& globalToLocalBuffer
202 const unallocFaceList& meshFaces = mesh_.faces();
203 const unallocLabelList& owner = mesh_.faceOwner();
204 const labelList& cellFaces = mesh_.cells()[cellID];
206 const pointField& points = mesh_.points();
207 const pointField& cellCentres = mesh_.cellCentres();
209 scalarField tetBuffer(tetPointRef::nEdges);
211 // For optimisation, point allocation is taken out of the loop
212 label vertexI, edgeI, localI, localJ;
215 forAll (cellFaces, faceI)
217 const label curFaceID = cellFaces[faceI];
219 face f = meshFaces[curFaceID];
221 if (cellID == owner[curFaceID])
226 label pointZeroID = f[0];
228 for (label i = 1; i < f.size() - 1; i++)
235 cellOffset() + cellID
246 // Calculate the diagonal and insert into local matrix
247 tpr.gradNiSquared(tetBuffer);
252 vertexI < tetPointRef::nVertices;
256 localI = globalToLocalBuffer[curTet[vertexI]];
258 denseMatrix[localI][localI] += tetBuffer[vertexI];
261 // Note: the coefficient is symmetric, i.e. equal in the upper and
263 tpr.gradNiDotGradNj(tetBuffer);
265 for (edgeI = 0; edgeI < tetPointRef::nEdges; edgeI++)
267 edge curEdge = curTet.tetEdge(edgeI);
269 localI = globalToLocalBuffer[curEdge.start()];
270 localJ = globalToLocalBuffer[curEdge.end()];
272 // Insert the coefficient into upper and lower triangle
274 denseMatrix[localI][localJ] += tetBuffer[edgeI];
275 denseMatrix[localJ][localI] += tetBuffer[edgeI];
282 void tetPolyMeshCellDecomp::gradNiGradNj
285 SquareMatrix<tensor>& denseMatrix,
286 const labelList& globalToLocalBuffer
289 const unallocFaceList& meshFaces = mesh_.faces();
290 const unallocLabelList& owner = mesh_.faceOwner();
291 const labelList& cellFaces = mesh_.cells()[cellID];
293 const pointField& points = mesh_.points();
294 const pointField& cellCentres = mesh_.cellCentres();
296 tensorField tetBuffer(tetPointRef::nEdges);
298 // For optimisation, point allocation is taken out of the loop
299 label vertexI, edgeI, localI, localJ, minIJ, maxIJ;
302 forAll (cellFaces, faceI)
304 const label curFaceID = cellFaces[faceI];
306 face f = meshFaces[curFaceID];
308 if (cellID == owner[curFaceID])
313 label pointZeroID = f[0];
315 for (label i = 1; i < f.size() - 1; i++)
322 cellOffset() + cellID
333 // Calculate the diagonal and insert into local matrix
334 tpr.gradNiGradNi(tetBuffer);
339 vertexI < tetPointRef::nVertices;
343 localI = globalToLocalBuffer[curTet[vertexI]];
345 denseMatrix[localI][localI] += tetBuffer[vertexI];
348 tpr.gradNiGradNj(tetBuffer);
350 for (edgeI = 0; edgeI < tetPointRef::nEdges; edgeI++)
352 curEdge = curTet.tetEdge(edgeI);
354 localI = globalToLocalBuffer[curEdge.start()];
355 localJ = globalToLocalBuffer[curEdge.end()];
357 // Accumulate the off-diagonal; folding the matrix.
358 // It is unknown if the localI or localJ is lower:
359 // that depends on how the local points have been
360 // selected. Therefore, the matrix (which is
361 // symmetric!) needs to be "folded"
363 minIJ = min(localI, localJ);
364 maxIJ = max(localI, localJ);
366 // Take care of the directionality of the edge
367 if (curEdge.start() < curEdge.end())
369 denseMatrix[minIJ][maxIJ] += tetBuffer[edgeI];
373 denseMatrix[minIJ][maxIJ] += tetBuffer[edgeI].T();
381 // Fill buffer with the volume integral distributed into vertices
382 void tetPolyMeshCellDecomp::volIntegral
386 const labelList& globalToLocalBuffer
389 // The addressing and volume distribution has been done tet-by-tet
390 // and the combination is done later for the whole cell.
392 const unallocFaceList& meshFaces = mesh_.faces();
393 const unallocLabelList& owner = mesh_.faceOwner();
394 const labelList& cellFaces = mesh_.cells()[cellID];
396 const pointField& points = mesh_.points();
397 const pointField& cellCentres = mesh_.cellCentres();
399 label vertexI, localI;
401 forAll (cellFaces, faceI)
403 const label curFaceID = cellFaces[faceI];
405 face f = meshFaces[curFaceID];
407 // Take care of owner/neighbour face reversal
408 if (cellID == owner[curFaceID])
413 // Grab the point zero of the face and create triangles by grabbing the
414 // labels around the perimeter
415 label pointZeroID = f[0];
417 for (label i = 1; i < f.size() - 1; i++)
419 // Face is assumed to be inward-pointing
425 cellOffset() + cellID
428 scalar quarterVolume =
441 vertexI < tetPointRef::nVertices;
445 localI = globalToLocalBuffer[curTet[vertexI]];
447 // Accumulate the diagonal
448 buffer[localI] += quarterVolume;
455 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
457 } // End namespace Foam
459 // ************************************************************************* //