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