ensightPartCells.C
Go to the documentation of this file.
1 /*---------------------------------------------------------------------------*\
2  ========= |
3  \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
4  \\ / O peration | Website: https://openfoam.org
5  \\ / A nd | Copyright (C) 2011-2019 OpenFOAM Foundation
6  \\/ M anipulation |
7 -------------------------------------------------------------------------------
8 License
9  This file is part of OpenFOAM.
10 
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.
15 
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
19  for more details.
20 
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/>.
23 
24 \*---------------------------------------------------------------------------*/
25 
26 #include "ensightPartCells.H"
27 #include "IOstream.H"
28 #include "IStringStream.H"
29 #include "dictionary.H"
30 #include "cellModeller.H"
32 
33 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
34 
35 namespace Foam
36 {
39 }
40 
42 
44 (
45  IStringStream
46  (
47  "(tetra4 pyramid5 penta6 hexa8 nfaced)"
48  )()
49 );
50 
51 
52 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
53 
54 void Foam::ensightPartCells::classify
55 (
56  const polyMesh& mesh,
57  const labelUList& idList
58 )
59 {
60  // References to cell shape models
61  const cellModel& tet = *(cellModeller::lookup("tet"));
62  const cellModel& pyr = *(cellModeller::lookup("pyr"));
63  const cellModel& prism = *(cellModeller::lookup("prism"));
64  const cellModel& hex = *(cellModeller::lookup("hex"));
65 
66  const cellShapeList& cellShapes = mesh.cellShapes();
67 
68  offset_ = 0;
69  size_ = mesh.nCells();
70 
71  bool limited = false;
72  if (notNull(idList))
73  {
74  limited = true;
75  size_ = idList.size();
76  }
77 
78  // count the shapes
79  label nTet = 0;
80  label nPyr = 0;
81  label nPrism = 0;
82  label nHex = 0;
83  label nPoly = 0;
84 
85  for (label listI = 0; listI < size_; ++listI)
86  {
87  label cellId = listI;
88  if (limited)
89  {
90  cellId = idList[listI];
91  }
92 
93  const cellShape& cellShape = cellShapes[cellId];
94  const cellModel& cellModel = cellShape.model();
95 
96  if (cellModel == tet)
97  {
98  nTet++;
99  }
100  else if (cellModel == pyr)
101  {
102  nPyr++;
103  }
104  else if (cellModel == prism)
105  {
106  nPrism++;
107  }
108  else if (cellModel == hex)
109  {
110  nHex++;
111  }
112  else
113  {
114  nPoly++;
115  }
116  }
117 
118 
119  // we can avoid double looping, but at the cost of allocation
120  labelList tetCells(nTet);
121  labelList pyramidCells(nPyr);
122  labelList prismCells(nPrism);
123  labelList hexCells(nHex);
124  labelList polyCells(nPoly);
125 
126  nTet = 0,
127  nPyr = 0;
128  nPrism = 0;
129  nHex = 0;
130  nPoly = 0;
131 
132  // classify the shapes
133  for (label listI = 0; listI < size_; ++listI)
134  {
135  label cellId = listI;
136  if (limited)
137  {
138  cellId = idList[listI];
139  }
140 
141  const cellShape& cellShape = cellShapes[cellId];
142  const cellModel& cellModel = cellShape.model();
143 
144  if (cellModel == tet)
145  {
146  tetCells[nTet++] = cellId;
147  }
148  else if (cellModel == pyr)
149  {
150  pyramidCells[nPyr++] = cellId;
151  }
152  else if (cellModel == prism)
153  {
154  prismCells[nPrism++] = cellId;
155  }
156  else if (cellModel == hex)
157  {
158  hexCells[nHex++] = cellId;
159  }
160  else
161  {
162  polyCells[nPoly++] = cellId;
163  }
164  }
165 
166 
167  // MUST match with elementTypes
169 
171  elemLists_[pyramid5Elements].transfer(pyramidCells);
172  elemLists_[penta6Elements].transfer(prismCells);
173  elemLists_[hexa8Elements].transfer(hexCells);
174  elemLists_[nfacedElements].transfer(polyCells);
175 }
176 
177 
178 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
179 
181 (
182  label partNumber,
183  const string& partDescription
184 )
185 :
186  ensightPart(partNumber, partDescription),
187  mesh_(*polyMeshNullPtr_)
188 {}
189 
190 
192 (
193  label partNumber,
194  const polyMesh& mesh
195 )
196 :
197  ensightPart(partNumber, "cells", mesh.points()),
198  mesh_(mesh)
199 {
200  classify(mesh);
201 }
202 
203 
205 (
206  label partNumber,
207  const polyMesh& mesh,
208  const labelUList& idList
209 )
210 :
211  ensightPart(partNumber, "cells", mesh.points()),
212  mesh_(mesh)
213 {
214  classify(mesh, idList);
215 }
216 
217 
219 (
220  label partNumber,
221  const polyMesh& mesh,
222  const cellZone& cZone
223 )
224 :
225  ensightPart(partNumber, cZone.name(), mesh.points()),
226  mesh_(mesh)
227 {
228  classify(mesh, cZone);
229 }
230 
231 
233 :
234  ensightPart(part),
235  mesh_(part.mesh_)
236 {}
237 
238 
240 :
241  ensightPart(),
242  mesh_(*polyMeshNullPtr_)
243 {
244  reconstruct(is);
245 }
246 
247 
248 // * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
249 
251 {}
252 
253 
254 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
255 
256 Foam::ensightPart::localPoints Foam::ensightPartCells::calcLocalPoints() const
257 {
258  localPoints ptList(points_);
259  labelList& usedPoints = ptList.list;
260  label nPoints = 0;
261 
262  forAll(elemLists_, typeI)
263  {
264  const labelUList& idList = elemLists_[typeI];
265 
266  // add all points from cells
267  forAll(idList, i)
268  {
269  const label id = idList[i] + offset_;
270  const labelUList& cFaces = mesh_.cells()[id];
271 
272  forAll(cFaces, cFacei)
273  {
274  const face& f = mesh_.faces()[cFaces[cFacei]];
275 
276  forAll(f, fp)
277  {
278  if (usedPoints[f[fp]] == -1)
279  {
280  usedPoints[f[fp]] = nPoints++;
281  }
282  }
283  }
284  }
285  }
286 
287  // this is not absolutely necessary, but renumber anyhow
288  nPoints = 0;
289  forAll(usedPoints, ptI)
290  {
291  if (usedPoints[ptI] > -1)
292  {
293  usedPoints[ptI] = nPoints++;
294  }
295  }
296 
297  ptList.nPoints = nPoints;
298  return ptList;
299 }
300 
301 
302 void Foam::ensightPartCells::writeConnectivity
303 (
304  ensightGeoFile& os,
305  const word& key,
306  const labelUList& idList,
307  const labelUList& pointMap
308 ) const
309 {
310  os.writeKeyword(key);
311  os.write(idList.size());
312  os.newline();
313 
314  // write polyhedral
315  if (key == "nfaced")
316  {
317  const faceList& meshFaces = mesh_.faces();
318  const labelUList& owner = mesh_.faceOwner();
319 
320  // write the number of faces per element
321  forAll(idList, i)
322  {
323  const label id = idList[i] + offset_;
324  const labelUList& cFace = mesh_.cells()[id];
325 
326  os.write(cFace.size());
327  os.newline();
328  }
329 
330  // write the number of points per element face
331  forAll(idList, i)
332  {
333  const label id = idList[i] + offset_;
334  const labelUList& cFace = mesh_.cells()[id];
335 
336  forAll(cFace, facei)
337  {
338  const face& cf = meshFaces[cFace[facei]];
339 
340  os.write(cf.size());
341  os.newline();
342  }
343  }
344 
345  // write the points describing each element face
346  forAll(idList, i)
347  {
348  const label id = idList[i] + offset_;
349  const labelUList& cFace = mesh_.cells()[id];
350 
351  forAll(cFace, cFacei)
352  {
353  const label faceId = cFace[cFacei];
354  const face& cf = meshFaces[faceId];
355 
356  // convert global -> local index
357  // (note: Ensight indices start with 1)
358 
359  // ensight >= 9 needs consistently oriented nfaced cells
360  if (id == owner[faceId])
361  {
362  forAll(cf, ptI)
363  {
364  os.write(pointMap[cf[ptI]] + 1);
365  }
366  }
367  else
368  {
369  // as per face::reverseFace(), but without copying
370 
371  os.write(pointMap[cf[0]] + 1);
372  for (label ptI = cf.size()-1; ptI > 0; --ptI)
373  {
374  os.write(pointMap[cf[ptI]] + 1);
375  }
376  }
377 
378  os.newline();
379  }
380  }
381  }
382  else
383  {
384  // write primitive
385  const cellShapeList& cellShapes = mesh_.cellShapes();
386 
387  forAll(idList, i)
388  {
389  const label id = idList[i] + offset_;
390  const cellShape& cellPoints = cellShapes[id];
391 
392  // convert global -> local index
393  // (note: Ensight indices start with 1)
394  forAll(cellPoints, ptI)
395  {
396  os.write(pointMap[cellPoints[ptI]] + 1);
397  }
398  os.newline();
399  }
400  }
401 }
402 
403 
405 {
406  ensightPart::writeGeometry(os, points_);
407 }
408 
409 
410 // ************************************************************************* //
#define forAll(list, i)
Loop across all elements in list.
Definition: UList.H:434
Macros for easy insertion into run-time selection tables.
An Istream is an abstract base class for all input systems (streams, files, token lists etc)....
Definition: Istream.H:60
void transfer(List< T > &)
Transfer the contents of the argument List into this list.
Definition: List.C:342
void setSize(const label)
Reset size of List.
Definition: List.C:281
static const cellModel * lookup(const word &)
Look up a model by name and return a pointer to the model or nullptr.
Definition: cellModeller.C:100
A subset of mesh cells.
Definition: cellZone.H:64
Specialised Ensight output with extra geometry file header.
An implementation of ensightPart to hold volume mesh cells.
static const List< word > elemTypes_
static const polyMesh *const polyMeshNullPtr_
virtual ~ensightPartCells()
Destructor.
ensightPartCells(label partNumber, const string &partDescription)
Construct empty part with number and description.
virtual void writeGeometry(ensightGeoFile &) const
Write geometry.
virtual const List< word > & elementTypes() const
Static listing of the element types.
Track the points used by the part and map global to local indices.
Definition: ensightPart.H:106
Base class for ensightPartCells and ensightPartFaces.
Definition: ensightPart.H:66
label size_
Number of elements in this part.
Definition: ensightPart.H:90
label offset_
Start offset for elemLists_.
Definition: ensightPart.H:87
labelListList elemLists_
Simple labelList with a name.
Definition: ensightPart.H:84
void reconstruct(Istream &)
Reconstruct part characteristics (eg, element types) from Istream.
label size() const
Number of elements in this part.
Definition: ensightPart.H:235
virtual void writeGeometry(ensightGeoFile &) const
Write geometry.
Definition: ensightPart.H:307
A face is a list of labels corresponding to mesh vertices.
Definition: face.H:76
Mesh consisting of general polyhedral cells.
Definition: polyMesh.H:80
const cellShapeList & cellShapes
const pointField & points
label nPoints
const label cellId
label faceId(-1)
Namespace for OpenFOAM.
List< cellShape > cellShapeList
List of cellShapes and PtrList of List of cellShape.
Definition: cellShapeList.H:43
List< label > labelList
A List of labels.
Definition: labelList.H:56
intWM_LABEL_SIZE_t label
A label is an int32_t or int64_t as specified by the pre-processor macro WM_LABEL_SIZE.
Definition: label.H:59
IOstream & hex(IOstream &io)
Definition: IOstream.H:561
bool notNull(const T &t)
Return true if t is not a reference to the nullObject of type T.
Definition: nullObjectI.H:58
defineTypeNameAndDebug(combustionModel, 0)
word name(const complex &)
Return a string representation of a complex.
Definition: complex.C:47
List< face > faceList
Definition: faceListFwd.H:43
UList< label > labelUList
Definition: UList.H:65
addToRunTimeSelectionTable(ensightPart, ensightPartCells, istream)
labelList f(nPoints)