CEPS  24.01
Cardiac ElectroPhysiology Simulator
VtkMeshReader.cpp
Go to the documentation of this file.
1 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2  This file is part of CEPS.
3 
4  CEPS is free software: you can redistribute it and/or modify
5  it under the terms of the GNU General Public License as published by
6  the Free Software Foundation, either version 3 of the License, or
7  (at your option) any later version.
8 
9  CEPS is distributed in the hope that it will be useful,
10  but WITHOUT ANY WARRANTY; without even the implied warranty of
11  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  GNU General Public License for more details.
13 
14  You should have received a copy of the GNU General Public License
15  along with CEPS (see file LICENSE at root of project).
16  If not, see <https://www.gnu.org/licenses/>.
17 
18 
19  Copyright 2019-2024 Inria, Universite de Bordeaux
20 
21  Authors, in alphabetical order:
22 
23  Pierre-Elliott BECUE, Florian CARO, Yves COUDIERE(*), Andjela DAVIDOVIC,
24  Charlie DOUANLA-LONTSI, Marc FUENTES, Mehdi JUHOOR, Michael LEGUEBE(*),
25  Pauline MIGERDITICHAN, Valentin PANNETIER(*), Nejib ZEMZEMI.
26  * : currently active authors
27 
28 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
31 
32 VtkMeshReader::VtkMeshReader(const CepsString &fileName, const CepsUInt &dim, CepsBool quads) :
33  MeshReader (fileName, dim, quads),
34  m_mesh(vtkSmartPointer<vtkDataSet>())
35 {
37  "Implemented vtk mesh reader is not compatible with extension "
38  << ceps::getExtension (m_fileName) << "." << std::endl
39  << " Valid extenstions are vtk and pvtu."
40  );
41 }
42 
44 {
45 }
46 
47 void
49 {
50  CEPS_SAYS(" Reading " << m_fileName);
51 
52  // determine if reading a legacy file or a pvtu file
56 
57  if (ext=="vtk")
59  else if (ext=="pvtu")
61 
62  // vertices
63  m_nbNodes = m_mesh->GetNumberOfPoints();
64 
65  m_nbCells = 0u;
66  m_nbBdryCells = 0u;
67 
68  // try to find cells first
69  vtkIdType cellType, nbCellsTotal = m_mesh->GetNumberOfCells();
70  m_nbCellsTotal = nbCellsTotal;
71  vtkIdType cellNbPoints;
72  vtkIdList *cellPoints = vtkIdList::New();
73  for (vtkIdType i = 0; i < nbCellsTotal; ++i)
74  {
75  cellType = m_mesh->GetCellType(i);
76  switch (cellType)
77  {
78  // case VTK_HEXAHEDRON:
79  // case VTK_VOXEL:
80  // if (m_quads and m_expectedDim == 3)
81  // m_nbCells++;
82  // break;
83  case VTK_TETRA:
84  if (not m_quads and m_expectedDim == 3)
85  m_nbCells++;
86  break;
87  case VTK_TRIANGLE:
88  {
89  if (not m_quads)
90  {
91  if (m_expectedDim == 3)
92  m_nbBdryCells++;
93  else if (m_expectedDim == 2)
94  m_nbCells++;
95  }
96  break;
97  }
98  // case VTK_QUAD:
99  // {
100  // if (m_quads)
101  // {
102  // if (m_expectedDim == 3)
103  // m_nbBdryCells++;
104  // else if (m_expectedDim == 2)
105  // m_nbCells++;
106  // }
107  // break;
108  // }
109  case VTK_POLYGON:
110  {
111  m_mesh->GetCellPoints(i, cellPoints);
112  cellNbPoints = cellPoints->GetNumberOfIds ();
113  if ((cellNbPoints == 3 and not m_quads) or (cellNbPoints == 4 and m_quads))
114  {
115  if (m_expectedDim == 3)
116  m_nbBdryCells++;
117  else if (m_expectedDim == 2)
118  m_nbCells++;
119  }
120  break;
121  }
122  case VTK_LINE:
123  {
124  if (m_expectedDim == 2)
125  m_nbBdryCells++;
126  else if (m_expectedDim == 1)
127  m_nbCells++;
128  break;
129  }
130  }
131  }
132 
133  CEPS_ABORT_IF(m_nbCells == 0 and m_nbBdryCells == 0,
134  "No cells or boundary cells found in file " << m_fileName << " for mesh of dimension "
135  << m_expectedDim
136  );
137 
138  m_nbAttrPerNode = 0;
139  m_nbAttrPerCell = 0;
141  // check for attributes
144 
145  m_initialized = true;
146 }
147 
148 void
150  CepsUInt indexStart,
151  CepsUInt indexEnd,
152  CepsUInt nodeOffset,
153  CepsVector<CepsReal>& coords,
155  CepsVector<CepsUInt>& attrPtr
156 )
157 {
158  checkCanReadNodes(indexStart,indexEnd);
159 
160  double pt[3];
161  vtkPointSet *p = vtkPointSet::SafeDownCast(m_mesh);
162 
163  for (vtkIdType i=0; (CepsUInt) i<m_nbNodes; ++i)
164  {
165  CepsUInt nodeId = nodeOffset+i;
166  p->GetPoint (i,pt);
167  if (i>=indexStart and i<indexEnd)
168  {
169  coords[3*nodeId ] = static_cast<CepsReal>(pt[0]);
170  coords[3*nodeId+1] = static_cast<CepsReal>(pt[1]);
171  coords[3*nodeId+2] = static_cast<CepsReal>(pt[2]);
172 
173  // read attributes
174  for (CepsUInt j=0; j<m_pointArrayToRead.size(); ++j)
175  attr[attrPtr[nodeId]+j] = m_pointArrayToRead[j]->GetTuple1(i);
176 
177  attrPtr[nodeId+1] = attrPtr[nodeId] + m_pointArrayToRead.size();
178  }
179  }
180 
181 }
182 
183 void
185  CepsUInt indexStart,
186  CepsUInt indexEnd,
187  CepsUInt nodeOffset,
188  CepsUInt cellOffset,
189  CepsVector<CepsNodeGlobalIndex>& nodeIndices,
190  CepsVector<CepsUInt>& nodeIndicesPtr,
191  CepsVector<CepsAttribute>& cellAttr,
192  CepsVector<CepsUInt>& cellAttrPtr,
193  CepsVector<CepsChar>& isBoundaryCell
194 )
195 {
196  checkCanReadCells(indexStart,indexEnd);
197 
198  // We do the loop twice, the first parses the volumic cells, the second the boundary cells
199  for (vtkIdType i=0; i<m_nbCellsTotal; ++i)
200  getNextCell(
201  cellOffset+m_cellsRead,i,nodeOffset,nodeIndices,nodeIndicesPtr,
202  cellAttr,cellAttrPtr,isBoundaryCell,false
203  );
204 
205  for (vtkIdType i=0; i<m_nbCellsTotal; ++i)
206  getNextCell(
207  cellOffset+m_cellsRead+m_bdryCellsRead,i,nodeOffset,nodeIndices,nodeIndicesPtr,
208  cellAttr,cellAttrPtr,isBoundaryCell,true
209  );
210 
211  return;
212 }
213 
214 CepsBool
215 VtkMeshReader::isVtkFile(const CepsString &fileName) const
216 {
217  CepsString extension = ceps::getExtension (fileName);
218  return (extension == "vtk" or extension == "pvtu");
219 }
220 
221 void
223  CepsUInt cellId,
224  CepsUInt fileCellId,
225  CepsUInt nodeOffset,
226  CepsVector<CepsNodeGlobalIndex>& nodeIndices,
227  CepsVector<CepsUInt>& nodeIndicesPtr,
228  CepsVector<CepsAttribute>& cellAttr,
229  CepsVector<CepsUInt>& cellAttrPtr,
230  CepsVector<CepsChar>& isBoundaryCell,
231  CepsBool boundaryFlag
232 )
233 {
234  vtkIdList *ptIds = vtkIdList::New();
235  m_mesh->GetCellPoints(fileCellId,ptIds);
236 
237  CepsUInt nbPoints = boundaryFlag ? m_nbNodesPerBdryCell : m_nbNodesPerCell;
238 
239  // Add the cell only if there is a match between the read Ids and the expected number of points
240  if (nbPoints == ptIds->GetNumberOfIds())
241  {
242  for (CepsUInt i = 0U; i < nbPoints; i++)
243  nodeIndices[nodeIndicesPtr[cellId]+i] = ptIds->GetId(i)+nodeOffset;
244 
245  // Read cellAttributes
246  for (CepsUInt i=0; i<m_cellArrayToRead.size(); ++i)
247  cellAttr[cellAttrPtr[cellId]+i] = m_cellArrayToRead[i]->GetTuple1(fileCellId);
248 
249  cellAttrPtr [cellId+1] = cellAttrPtr [cellId] + m_cellArrayToRead.size();
250  nodeIndicesPtr[cellId+1] = nodeIndicesPtr[cellId] + nbPoints;
251  isBoundaryCell[cellId ] = boundaryFlag;
252 
253  if (boundaryFlag)
254  m_bdryCellsRead++;
255  else
256  m_cellsRead++;
257  }
258 
259  ptIds->Delete();
260 }
261 
262 void
264 {
265  vtkXMLPUnstructuredGridReader *reader = vtkXMLPUnstructuredGridReader::New();
266  reader->SetFileName (fileName.c_str());
267  reader->Update();
268 
269  reader->GetOutput()->Register(reader);
270  m_mesh = vtkDataSet::SafeDownCast(reader->GetOutput());
271  reader->Delete ();
272 }
273 
274 void
276 {
277  vtkNew<vtkDataSetReader> reader;
278 
279  reader->SetFileName (fileName.c_str());
280  reader->SetReadAllScalars(1);
281  reader->SetReadAllVectors(1);
282  reader->SetReadAllNormals(1);
283  reader->SetReadAllTensors(1);
284  reader->SetReadAllFields (1);
285 
286  reader->Update();
287 
288  reader->GetOutput()->Register(reader);
289  m_mesh = vtkDataSet::SafeDownCast(reader->GetOutput());
290 
291 }
292 
293 void
295 {
296  vtkCellData *cellData = m_mesh->GetCellData();
297  vtkDataArray *array = nullptr;
298 
299  CepsInt i;
300  CepsInt nbCells = m_mesh->GetNumberOfCells();
301  for (i = 0; i < cellData->GetNumberOfArrays(); ++i)
302  {
303  array = cellData->GetArray(i);
304  // check only arrays of integer type
305  switch (array->GetDataType())
306  {
307  case VTK_UNSIGNED_SHORT:
308  case VTK_UNSIGNED_CHAR:
309  case VTK_UNSIGNED_LONG:
310  case VTK_UNSIGNED_INT:
311  case VTK_ID_TYPE:
312  case VTK_SHORT:
313  case VTK_LONG:
314  case VTK_INT:
315  case VTK_LONG_LONG:
316  {
317  if ((array->GetNumberOfComponents()==1) and (array->GetNumberOfTuples() == nbCells))
318  {
319  // use this array as an attribute field
320  m_nbAttrPerCell++;
322  m_cellArrayToRead.push_back (array);
323  CEPS_SAYS(" Detected attributes array \"" << array->GetName() << "\" on cells");
324  }
325  break;
326  }
327  default:
328  // ignore this array
329  break;
330  }
331  }
332 }
333 
334 void
336 {
337  vtkPointData *data = m_mesh->GetPointData();
338  vtkDataArray *array = nullptr;
339 
340  CepsInt i;
341  for (i = 0; i < data->GetNumberOfArrays(); ++i)
342  {
343  array = data->GetArray(i);
344  // check only arrays of integer type
345  switch (array->GetDataType())
346  {
347  case VTK_UNSIGNED_SHORT:
348  case VTK_UNSIGNED_CHAR:
349  case VTK_UNSIGNED_LONG:
350  case VTK_UNSIGNED_INT:
351  case VTK_ID_TYPE:
352  case VTK_SHORT:
353  case VTK_INT:
354  {
355  if ((array->GetNumberOfComponents() == 1) and ((CepsUInt)(array->GetNumberOfTuples()) == m_nbNodes))
356  {
357  // use this array as an attribute field
358  m_nbAttrPerNode++;
359  m_pointArrayToRead.push_back(array);
360  CEPS_SAYS(" Detected attributes array \"" << array->GetName() << "\" on points");
361  }
362  break;
363  }
364  default: break;
365  }
366  }
367 }
#define CEPS_SAYS(message)
Writes a message in the debug log and in the terminal (stdio).
#define CEPS_ABORT_IF(condition, message)
Stops the execution with a message if condition is true. If testing is enabled, only throws a runtime...
std::basic_string< CepsChar > CepsString
C++ format string.
Definition: CepsTypes.hpp:128
std::vector< _Type, _Alloc > CepsVector
C++ vector.
Definition: CepsTypes.hpp:155
bool CepsBool
Booleans.
Definition: CepsTypes.hpp:124
std::make_unsigned_t< CepsInt > CepsUInt
Unsigned version on CepsInt.
Definition: CepsTypes.hpp:109
float CepsReal
Need single precision floating point.
Definition: CepsTypes.hpp:100
int32_t CepsInt
Need 32 bit integer.
Definition: CepsTypes.hpp:106
CepsString m_fileName
file to open
Definition: FileReader.hpp:145
Abstract base class that encapsulates primary functionalities of each mesh reader.
Definition: MeshReader.hpp:42
CepsUInt m_nbAttrPerCell
attributes per cell
Definition: MeshReader.hpp:194
CepsBool m_initialized
Flag to ensure call of initializeReader()
Definition: MeshReader.hpp:176
void checkCanReadNodes(CepsUInt indexStart, CepsUInt indexEnd) const
Aborts if passed indices are wrong.
Definition: MeshReader.cpp:137
CepsUInt m_nbNodesPerBdryCell
nb nodes per boundary cell
Definition: MeshReader.hpp:181
CepsBool m_quads
Reader for quadratic cells.
Definition: MeshReader.hpp:175
CepsUInt m_bdryCellsRead
Keeps track of already read boundary cells.
Definition: MeshReader.hpp:180
CepsUInt m_nbNodesPerCell
nb nodes per cell
Definition: MeshReader.hpp:179
CepsUInt m_nbBdryCells
number of boundary cells in mesh, appropriate for dimension
Definition: MeshReader.hpp:191
CepsUInt m_nbAttrPerBdryCell
attributes per boundary cell
Definition: MeshReader.hpp:195
CepsUInt m_cellsRead
Keeps track of already read cells.
Definition: MeshReader.hpp:178
CepsUInt m_nbAttrPerNode
attributes per node
Definition: MeshReader.hpp:193
CepsUInt m_expectedDim
Expected dimension of mesh.
Definition: MeshReader.hpp:174
CepsUInt m_nbCellsTotal
number of all cells in file
Definition: MeshReader.hpp:188
CepsUInt m_nbNodes
number of nodes in mesh
Definition: MeshReader.hpp:184
CepsUInt m_nbCells
number of cells in mesh, appropriate for dimension
Definition: MeshReader.hpp:187
void checkCanReadCells(CepsUInt indexStart, CepsUInt indexEnd) const
Aborts if passed indices are wrong.
Definition: MeshReader.cpp:151
~VtkMeshReader() override
Destructor.
void getNextCell(CepsUInt cellId, CepsUInt fileCellId, CepsUInt nodeOffset, CepsVector< CepsNodeGlobalIndex > &nodeIndices, CepsVector< CepsUInt > &nodeIndicesPtr, CepsVector< CepsAttribute > &cellAttr, CepsVector< CepsUInt > &cellAttrPtr, CepsVector< CepsChar > &isBoundaryCell, CepsBool boundaryFlag) override
Reads a single cell in mesh file.
void readNodes(CepsUInt indexStart, CepsUInt indexEnd, CepsUInt nodeOffset, CepsVector< CepsReal > &coords, CepsVector< CepsAttribute > &attr, CepsVector< CepsUInt > &attrPtr) override
Reads several nodes in mesh file.
void determinePointDataToRead()
Selects the integer array that should be present, which contains node attributes.
CepsVector< vtkDataArray * > m_cellArrayToRead
Arrays of data defined on cells.
void readCells(CepsUInt indexStart, CepsUInt indexEnd, CepsUInt nodeOffset, CepsUInt cellOffset, CepsVector< CepsNodeGlobalIndex > &nodeIndices, CepsVector< CepsUInt > &nodeIndicesPtr, CepsVector< CepsAttribute > &cellAttr, CepsVector< CepsUInt > &cellAttrPtr, CepsVector< CepsChar > &isBoundaryCell) override
Reads several cells in mesh file.
VtkMeshReader(const CepsString &fileName, const CepsUInt &dim, CepsBool quads=false)
Constructor with full file name.
void determineCellDataToRead()
Selects the integer array that should be present, which contains cell attributes.
void initializePvtu(const CepsString &fileName)
Reads global information for parallel unstructured grids.
vtkSmartPointer< vtkDataSet > m_mesh
VTK mesh structure.
CepsVector< vtkDataArray * > m_pointArrayToRead
Arrays of data defined on points.
void initializeLegacy(const CepsString &fileName)
Reads global information for legacy files.
void initialize() override
Read nodes from indexStart to indexEnd, filling the arrays of coordinates and attributes.
CepsBool isVtkFile(const CepsString &fileName) const
Test if file is legacy file .vtk or .pvtu.
CepsString getDir(const CepsString &str)
Get a substring of s, from beginning of s to the last '/' character. Example: "/home/someone/file....
Definition: CepsString.cpp:521
CepsString getFilename(const CepsString &str)
Returns a substring corresponding to the string after the last '/' character. Example: "/home/someone...
Definition: CepsString.cpp:556
CepsString getExtension(const CepsString &str)
Returns the extension of a file, if any.
Definition: CepsString.cpp:580