1 /*=========================================================================
2
3 Program: Visualization Toolkit
4 Module: vtkGAMBITReader.cxx
5
6 Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
7 All rights reserved.
8 See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
9
10 This software is distributed WITHOUT ANY WARRANTY; without even
11 the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
12 PURPOSE. See the above copyright notice for more information.
13
14 =========================================================================*/
15 // Thanks to Jean M. Favre (CSCS, Swiss Center for Scientific Computing) who
16 // developed this class.
17 // Please address all comments to Jean Favre (jfavre at cscs.ch)
18
19 #include "vtkGAMBITReader.h"
20
21 #include "vtkInformation.h"
22 #include "vtkInformationVector.h"
23 #include "vtkObjectFactory.h"
24 #include "vtkErrorCode.h"
25 #include "vtkUnstructuredGrid.h"
26 #include "vtkPointData.h"
27 #include "vtkCellData.h"
28 #include "vtkDoubleArray.h"
29 #include "vtkIntArray.h"
30 #include "vtkCellArray.h"
31
32 vtkStandardNewMacro(vtkGAMBITReader);
33
34 //----------------------------------------------------------------------------
vtkGAMBITReader()35 vtkGAMBITReader::vtkGAMBITReader()
36 {
37 this->FileName = NULL;
38 this->NumberOfCells = 0;
39 this->NumberOfNodes = 0;
40 this->NumberOfNodeFields = 0;
41 this->NumberOfCellFields = 0;
42 this->FileStream = NULL;
43
44 this->SetNumberOfInputPorts(0);
45 }
46
47 //----------------------------------------------------------------------------
~vtkGAMBITReader()48 vtkGAMBITReader::~vtkGAMBITReader()
49 {
50 delete [] this->FileName;
51 }
52
53 //----------------------------------------------------------------------------
RequestData(vtkInformation * vtkNotUsed (request),vtkInformationVector ** vtkNotUsed (inputVector),vtkInformationVector * outputVector)54 int vtkGAMBITReader::RequestData(
55 vtkInformation *vtkNotUsed(request),
56 vtkInformationVector **vtkNotUsed(inputVector),
57 vtkInformationVector *outputVector)
58 {
59 // get the info object
60 vtkInformation *outInfo = outputVector->GetInformationObject(0);
61
62 // get the ouptut
63 vtkUnstructuredGrid *output = vtkUnstructuredGrid::SafeDownCast(
64 outInfo->Get(vtkDataObject::DATA_OBJECT()));
65
66 vtkDebugMacro( << "Reading GAMBIT Neutral file");
67
68 // If ExecuteInformation() failed the FileStream will be NULL and
69 // ExecuteInformation() will have spit out an error.
70 if ( this->FileStream == NULL )
71 {
72 return 0;
73 }
74
75 this->ReadFile(output);
76
77 return 1;
78 }
79
80 //----------------------------------------------------------------------------
PrintSelf(ostream & os,vtkIndent indent)81 void vtkGAMBITReader::PrintSelf(ostream& os, vtkIndent indent)
82 {
83 this->Superclass::PrintSelf(os,indent);
84
85 os << indent << "File Name: "
86 << (this->FileName ? this->FileName : "(none)") << "\n";
87
88 os << indent << "Number Of Nodes: " << this->NumberOfNodes << endl;
89 os << indent << "Number Of Node Fields: "
90 << this->NumberOfNodeFields << endl;
91
92 os << indent << "Number Of Cells: " << this->NumberOfCells << endl;
93 os << indent << "Number Of Cell Fields: "
94 << this->NumberOfCellFields << endl;
95 }
96
97 //----------------------------------------------------------------------------
ReadFile(vtkUnstructuredGrid * output)98 void vtkGAMBITReader::ReadFile(vtkUnstructuredGrid *output)
99 {
100 this->ReadGeometry(output);
101
102 // yes, but, we cannot find any examples containing data.
103 // GAMBIT users seem to say that they use the Fluent solver and do not
104 // use Gambit as an output format, thus no data when used as input to solver
105 if(this->NumberOfNodeFields)
106 {
107 this->ReadNodeData(output);
108 }
109
110 if(this->NumberOfCellFields)
111 {
112 this->ReadCellData(output);
113 }
114
115 delete this->FileStream;
116 this->FileStream = NULL;
117 }
118
119 //----------------------------------------------------------------------------
ReadNodeData(vtkUnstructuredGrid * vtkNotUsed (output))120 void vtkGAMBITReader::ReadNodeData(vtkUnstructuredGrid *vtkNotUsed(output))
121 {
122 vtkWarningMacro("Not implemented due to lack of examples");
123 }
124
125 //----------------------------------------------------------------------------
ReadCellData(vtkUnstructuredGrid * vtkNotUsed (output))126 void vtkGAMBITReader::ReadCellData(vtkUnstructuredGrid *vtkNotUsed(output))
127 {
128 vtkWarningMacro("Not implemented due to lack of examples");
129 }
130
131 //----------------------------------------------------------------------------
RequestInformation(vtkInformation * vtkNotUsed (request),vtkInformationVector ** vtkNotUsed (inputVector),vtkInformationVector * vtkNotUsed (outputVector))132 int vtkGAMBITReader::RequestInformation(
133 vtkInformation *vtkNotUsed(request),
134 vtkInformationVector **vtkNotUsed(inputVector),
135 vtkInformationVector *vtkNotUsed(outputVector))
136 {
137 if ( !this->FileName )
138 {
139 this->NumberOfNodes = 0;
140 this->NumberOfCells = 0;
141 this->NumberOfNodeFields = 0;
142 this->NumberOfCellFields = 0;
143
144 vtkErrorMacro("No filename specified");
145 return 0;
146 }
147
148 this->FileStream = new ifstream(this->FileName, ios::in);
149
150 if (this->FileStream->fail())
151 {
152 this->SetErrorCode(vtkErrorCode::FileNotFoundError);
153 delete this->FileStream;
154 this->FileStream = NULL;
155 vtkErrorMacro("Specified filename not found");
156 return 0;
157 }
158
159 char c='\0', buf[128];
160
161 this->FileStream->get(buf, 128, '\n'); this->FileStream->get(c);
162 this->FileStream->get(buf, 128, '\n'); this->FileStream->get(c);
163 this->FileStream->get(buf, 128, '\n'); this->FileStream->get(c);
164 this->FileStream->get(buf, 128, '\n'); this->FileStream->get(c);
165 this->FileStream->get(buf, 128, '\n'); this->FileStream->get(c);
166 this->FileStream->get(buf, 128, '\n'); this->FileStream->get(c);
167
168 *(this->FileStream) >> this->NumberOfNodes;
169 *(this->FileStream) >> this->NumberOfCells;
170 *(this->FileStream) >> this->NumberOfElementGroups;
171 *(this->FileStream) >> this->NumberOfBoundaryConditionSets;
172 *(this->FileStream) >> this->NumberOfCoordinateDirections;
173 *(this->FileStream) >> this->NumberOfVelocityComponents;
174 this->FileStream->get(c);
175
176 // read here the end of section
177 this->FileStream->get(buf, 128, '\n'); this->FileStream->get(c);
178 if(strncmp(buf, "ENDOFSECTION", 12))
179 {
180 vtkErrorMacro(<<"Error reading file");
181 }
182 vtkDebugMacro(
183 << "\nNumberOfNodes " << this->NumberOfNodes
184 << "\nNumberOfCells " << this->NumberOfCells
185 << "\nNumberOfElementGroups " << this->NumberOfElementGroups
186 << "\nNumberOfBoundaryConditionSets " << this->NumberOfBoundaryConditionSets
187 << "\nNumberOfCoordinateDirections " << this->NumberOfCoordinateDirections
188 << "\nNumberOfVelocityComponents " << this->NumberOfVelocityComponents);
189
190 return 1;
191 }
192
193 //----------------------------------------------------------------------------
ReadGeometry(vtkUnstructuredGrid * output)194 void vtkGAMBITReader::ReadGeometry(vtkUnstructuredGrid *output)
195 {
196 vtkDoubleArray *coords = vtkDoubleArray::New();
197 coords->SetNumberOfComponents(3);
198 // allocate one more pt and store node id=0
199 coords->SetNumberOfTuples(this->NumberOfNodes);
200
201 this->ReadXYZCoords(coords);
202 this->ReadCellConnectivity(output);
203 if(this->NumberOfElementGroups > 0)
204 {
205 this->ReadMaterialTypes(output);
206 }
207 if(this->NumberOfBoundaryConditionSets > 0)
208 {
209 this->ReadBoundaryConditionSets(output);
210 }
211 vtkPoints *points = vtkPoints::New();
212 points->SetData(coords);
213 coords->Delete();
214
215 output->SetPoints(points);
216 points->Delete();
217 }
218
219 //----------------------------------------------------------------------------
ReadBoundaryConditionSets(vtkUnstructuredGrid * output)220 void vtkGAMBITReader::ReadBoundaryConditionSets(vtkUnstructuredGrid *output)
221 {
222 int bcs, f, itype, nentry, nvalues;
223 int isUsable=0;
224 int node, elt, eltype, facenumber;
225 char c, buf[128];
226
227 // no idea about how to treat element/cell, so we allocate a single array
228
229 vtkIntArray *bcscalar = vtkIntArray::New();
230 bcscalar->SetNumberOfComponents(1);
231 bcscalar->SetNumberOfTuples(this->NumberOfNodes);
232 bcscalar->SetName("Boundary Condition");
233 int *ptr = bcscalar->GetPointer(0);
234 // initialise with null values. When set later, will set to 1
235 memset((void*)ptr,0,sizeof(int)*this->NumberOfNodes);
236
237 for(bcs=1; bcs <= this->NumberOfBoundaryConditionSets; bcs++)
238 {
239 this->FileStream->get(buf, 128, '\n'); this->FileStream->get(c);
240 this->FileStream->get(buf, 128, '\n'); this->FileStream->get(c);
241 sscanf(&buf[32],"%10d%10d%10d", &itype, &nentry, &nvalues);
242 vtkDebugMacro(
243 << "\nitype " << itype
244 << "\tnentry " << nentry
245 << "\tnvalues " << nvalues);
246 // I have no example o how nvalues is used....So no implementation.
247 if(itype == 0) // nodes
248 {
249 isUsable = 1;
250 for(f=0; f < nentry; f++)
251 {
252 *(this->FileStream) >> node;
253 node--;
254 if( node >= 0 && node < this->NumberOfNodes)
255 {
256 bcscalar->SetValue(node, 1);
257 }
258 else
259 {
260 vtkErrorMacro(<<"Node value is outside of range");
261 }
262 }
263 this->FileStream->get(c);
264 // read here the end of section
265 this->FileStream->get(buf, 128, '\n'); this->FileStream->get(c);
266 if(strncmp(buf, "ENDOFSECTION", 12))
267 {
268 vtkErrorMacro(<<"Error reading ENDOFSECTION tag at end of group");
269 }
270 }
271 else // element/cell are parsed but nothing is done with the info read
272 {
273 for(f=0; f < nentry; f++)
274 {
275 *(this->FileStream) >> elt >> eltype >> facenumber;
276 }
277 this->FileStream->get(c);
278 // read here the end of section
279 this->FileStream->get(buf, 128, '\n'); this->FileStream->get(c);
280 if(strncmp(buf, "ENDOFSECTION", 12))
281 {
282 vtkErrorMacro(<<"Error reading ENDOFSECTION tag at end of group");
283 }
284 }
285 }
286 vtkDebugMacro(<< "All BCS read successfully");
287 if(isUsable)
288 {
289 output->GetPointData()->AddArray(bcscalar);
290 if (!output->GetPointData()->GetScalars())
291 {
292 output->GetPointData()->SetScalars(bcscalar);
293 }
294 }
295 bcscalar->Delete();
296 }
297
298 //----------------------------------------------------------------------------
ReadMaterialTypes(vtkUnstructuredGrid * output)299 void vtkGAMBITReader::ReadMaterialTypes(vtkUnstructuredGrid *output)
300 {
301 int grp, f, flag, id, nbelts, elt, mat, nbflags;
302 char c, buf[128];
303
304 vtkIntArray *materials = vtkIntArray::New();
305 materials->SetNumberOfComponents(1);
306 materials->SetNumberOfTuples(this->NumberOfCells);
307 materials->SetName("Material Type");
308
309 for(grp=1; grp <= this->NumberOfElementGroups; grp++)
310 {
311 this->FileStream->get(buf, 128, '\n'); this->FileStream->get(c);
312 this->FileStream->get(buf, 128, '\n'); this->FileStream->get(c);
313 sscanf(buf,"GROUP:%10d ELEMENTS: %10d MATERIAL: %10d NFLAGS:%10d", &id, &nbelts, &mat, &nbflags);
314
315 vtkDebugMacro(
316 << "\nid " << id
317 << "\tnbelts " << nbelts
318 << "\tmat " << mat
319 << "\tnbflags " << nbflags);
320
321 this->FileStream->get(buf, 128, '\n'); this->FileStream->get(c);
322 for(f=0; f < nbflags; f++)
323 {
324 *(this->FileStream) >> flag;
325 }
326 this->FileStream->get(c);
327 for(f=0; f < nbelts; f++)
328 {
329 *(this->FileStream) >> elt;
330 materials->SetValue(elt-1, mat);
331 }
332 this->FileStream->get(c);
333 // read here the end of section
334 this->FileStream->get(buf, 128, '\n'); this->FileStream->get(c);
335 if(strncmp(buf, "ENDOFSECTION", 12))
336 {
337 vtkErrorMacro(<<"Error reading ENDOFSECTION tag at end of group");
338 }
339 }
340 vtkDebugMacro(<< "All groups read successfully");
341
342 output->GetCellData()->AddArray(materials);
343 if (!output->GetCellData()->GetScalars())
344 {
345 output->GetCellData()->SetScalars(materials);
346 }
347 materials->Delete();
348 }
349
350 //----------------------------------------------------------------------------
ReadCellConnectivity(vtkUnstructuredGrid * output)351 void vtkGAMBITReader::ReadCellConnectivity(vtkUnstructuredGrid *output)
352 {
353 int i, k;
354 vtkIdType list[27];
355 char c, buf[128];
356
357 output->Allocate();
358
359 this->FileStream->get(buf, 128, '\n'); this->FileStream->get(c);
360
361 for(i=1; i <= this->NumberOfCells; i++)
362 {
363 int id; // no check is done to see that they are monotonously increasing
364 int ntype, ndp;
365 *(this->FileStream) >> id >> ntype >> ndp;
366
367 switch(ntype){
368 case EDGE:
369 {
370 for(k=0; k < 2; k++)
371 {
372 *(this->FileStream) >> list[k];
373 list[k]--;
374 }
375 output->InsertNextCell(VTK_LINE, 2, list);
376 }
377 break;
378 case TRI:
379 {
380 for(k=0; k < 3; k++)
381 {
382 *(this->FileStream) >> list[k];
383 list[k]--;
384 }
385 output->InsertNextCell(VTK_TRIANGLE, 3, list);
386 }
387 break;
388 case QUAD:
389 {
390 for(k=0; k < 4; k++)
391 {
392 *(this->FileStream) >> list[k];
393 list[k]--;
394 }
395 output->InsertNextCell(VTK_QUAD, 4, list);
396 }
397 break;
398 case TETRA:
399 {
400 for(k=0; k < 4; k++)
401 {
402 *(this->FileStream) >> list[k];
403 list[k]--;
404 }
405 output->InsertNextCell(VTK_TETRA, 4, list);
406 }
407 break;
408 case PYRAMID:
409 {
410 for(k=0; k < 5; k++)
411 {
412 *(this->FileStream) >> list[k];
413 list[k]--;
414 }
415 output->InsertNextCell(VTK_PYRAMID, 5, list);
416 }
417 break;
418 case PRISM:
419 {
420 for(k=0; k < 6; k++)
421 {
422 *(this->FileStream) >> list[k];
423 list[k]--;
424 }
425 output->InsertNextCell(VTK_WEDGE, 6, list);
426 }
427 break;
428 case BRICK:
429 {
430 for(k=0; k < 8; k++)
431 {
432 *(this->FileStream) >> list[k];
433 list[k]--;
434 }
435 output->InsertNextCell(VTK_HEXAHEDRON, 8, list);
436 }
437 break;
438 default:
439 {
440 vtkErrorMacro( << "cell type: " << ntype << " is not supported\n");
441 return;
442 }
443 } // for all cell, read the indices
444 }
445 // read here the end of section
446 this->FileStream->get(c); this->FileStream->get(buf, 128, '\n'); this->FileStream->get(c);
447 if(strncmp(buf, "ENDOFSECTION", 12))
448 {
449 vtkErrorMacro(<<"Error reading ENDOFSECTION tag at end of connectivity");
450 }
451 }
452
453 //----------------------------------------------------------------------------
ReadXYZCoords(vtkDoubleArray * coords)454 void vtkGAMBITReader::ReadXYZCoords(vtkDoubleArray *coords)
455 {
456 int i;
457 double *ptr = coords->GetPointer(0);
458 char c, buf[64];
459
460 int id; // no check is done to see that they are monotonously increasing
461 this->FileStream->get(buf, 64, '\n'); this->FileStream->get(c);
462
463 if(this->NumberOfCoordinateDirections == 3)
464 {
465 for(i=0; i < this->NumberOfNodes; i++)
466 {
467 *(this->FileStream) >> id;
468 *(this->FileStream) >> ptr[3*i] >> ptr[3*i+1] >> ptr[3*i+2];
469 }
470 }
471 else
472 {
473 for(i=0; i < this->NumberOfNodes; i++)
474 {
475 *(this->FileStream) >> id;
476 *(this->FileStream) >> ptr[3*i] >> ptr[3*i+1];
477 ptr[3*i+2] = 0.0;
478 }
479 }
480 this->FileStream->get(c); this->FileStream->get(buf, 128, '\n'); this->FileStream->get(c);
481 if(strncmp(buf, "ENDOFSECTION", 12))
482 {
483 vtkErrorMacro("Error reading ENDOFSECTION tag at end of coordinates section");
484 }
485 }
486