Commit 1bf0e23e authored by Andrew Bauer's avatar Andrew Bauer
Browse files

Improve the Tecplot reader

The Tecplot reader should better handle the VARSHARELIST,
CONNECTIVITYSHAREZONE and ZONETYPE options/tags/labels
and time information.

Addresses paraview/paraivew#18366.
parent e412ca55
Pipeline #111802 failed with stage
......@@ -23,6 +23,8 @@
#include "vtkCamera.h"
#include "vtkCompositeDataPipeline.h"
#include "vtkCompositeDataGeometryFilter.h"
#include "vtkFloatArray.h"
#include "vtkMultiBlockDataSet.h"
#include "vtkPolyDataMapper.h"
#include "vtkPointData.h"
#include "vtkRenderer.h"
......@@ -31,7 +33,7 @@
#include "vtkRegressionTestImage.h"
#include "vtkSmartPointer.h"
#include "vtkTestUtilities.h"
#include "vtkUnstructuredGrid.h"
int TestTecplotReader( int argc, char *argv[] )
{
......@@ -155,11 +157,37 @@ int TestTecplotReader( int argc, char *argv[] )
iren->Start();
}
renWin->Delete();
ren->Delete();
iren->Delete();
exec->Delete();
exec2->Delete();
exec3->Delete();
//create the reader for the cell centered data set.
char* fname4 = vtkTestUtilities::ExpandDataFileName(argc, argv, "Data/timedependent.dat");
vtkSmartPointer<vtkTecplotReader> reader4 =
vtkSmartPointer<vtkTecplotReader>::New();
reader4->SetFileName(fname4);
reader4->SetDataArrayStatus("U",1);
reader4->UpdateTimeStep(120);
vtkMultiBlockDataSet* mb = vtkMultiBlockDataSet::SafeDownCast(reader4->GetOutput());
vtkUnstructuredGrid* grid = vtkUnstructuredGrid::SafeDownCast(mb->GetBlock(0));
if (grid->GetNumberOfPoints() != 4 || grid->GetNumberOfCells() != 2)
{
cerr << "ERROR: incorrect number of points or cells in file\n";
retVal = 0;
}
vtkFloatArray* uArray = vtkFloatArray::SafeDownCast(grid->GetPointData()->GetArray("U"));
double range[2];
uArray->GetRange(range);
if (range[0] > 3.1 || range[1] < 2.9)
{
cerr << "ERROR: incorrect range for U array\n";
retVal = 0;
}
delete [] fname4;
return !retVal;
}
......@@ -36,11 +36,11 @@
#include "vtkMultiBlockDataSet.h"
#include "vtkCompositeDataPipeline.h"
#include "vtkPoints.h"
#include "vtkCellData.h"
#include "vtkPointData.h"
#include "vtkCellArray.h"
#include "vtkCellData.h"
#include "vtkFloatArray.h"
#include "vtkPointData.h"
#include "vtkPoints.h"
#include "vtkIdTypeArray.h"
#include "vtkStructuredGrid.h"
#include "vtkUnstructuredGrid.h"
......@@ -50,9 +50,9 @@
#include "vtk_zlib.h"
#include <vtksys/SystemTools.hxx>
#include <fstream>
#include <cctype> // for isspace(), isalnum()
#include <fstream>
#include <map>
vtkStandardNewMacro( vtkTecplotReader );
......@@ -573,6 +573,46 @@ int vtkTecplotReader::RequestInformation( vtkInformation * request,
return 0;
}
if ( this->FileName == nullptr || strcmp( this->FileName, "" ) == 0 )
{
return 0;
}
this->Init();
this->Internal->ASCIIStream.open( this->FileName );
std::string tok = this->Internal->GetNextToken();
std::vector<double> timeSteps;
while ( !this->Internal->NextCharEOF )
{
if ( tok.empty() )
{
// whitespace: do nothing
}
else if ( tok == "SOLUTIONTIME" )
{
timeSteps.push_back(atof( this->Internal->GetNextToken().c_str() ));
}
tok = this->Internal->GetNextToken();
}
this->Internal->ASCIIStream.close();
vtkInformation* outInfo = outputVector->GetInformationObject(0);
if (timeSteps.empty())
{
outInfo->Remove(vtkStreamingDemandDrivenPipeline::TIME_STEPS());
outInfo->Remove(vtkStreamingDemandDrivenPipeline::TIME_RANGE());
}
else
{
// Tell the pipeline what steps are available
outInfo->Set(vtkStreamingDemandDrivenPipeline::TIME_STEPS(),
timeSteps.data(), static_cast<int>(timeSteps.size()));
double tRange[2] = {timeSteps[0], timeSteps.back()};
outInfo->Set(vtkStreamingDemandDrivenPipeline::TIME_RANGE(), tRange, 2);
}
this->GetDataArraysList();
return 1;
......@@ -587,10 +627,20 @@ int vtkTecplotReader::RequestData( vtkInformation * vtkNotUsed( request )
vtkMultiBlockDataSet * output = vtkMultiBlockDataSet::SafeDownCast
( outInf->Get( vtkDataObject::DATA_OBJECT() ) );
bool timeIsSet = false;
double time = 0;
if (outInf->Has(vtkStreamingDemandDrivenPipeline::UPDATE_TIME_STEP()))
{
timeIsSet = true;
time =
outInf->Get(vtkStreamingDemandDrivenPipeline::UPDATE_TIME_STEP());
//cerr << time << " is the requesting that I want\n";
}
output->GetInformation()->Set(vtkDataObject::DATA_TIME_STEP(), time);
this->Internal->Completed = 0;
this->ReadFile( output );
outInf = nullptr;
output = nullptr;
this->ReadFile( output, timeIsSet, time );
return 1;
}
......@@ -1446,7 +1496,8 @@ void vtkTecplotReader::GetDataArraysList()
}
// ----------------------------------------------------------------------------
void vtkTecplotReader::ReadFile( vtkMultiBlockDataSet * multZone )
void vtkTecplotReader::ReadFile( vtkMultiBlockDataSet * multZone,
bool timeIsSet, double time)
{
if ( ( this->Internal->Completed == 1 )
|| ( this->FileName == nullptr ) || ( strcmp( this->FileName, "" ) == 0 )
......@@ -1469,16 +1520,19 @@ void vtkTecplotReader::ReadFile( vtkMultiBlockDataSet * multZone )
tok != "TEXT" &&\
tok != "DATASETAUXDATA"
int zoneIndex = 0;
std::map<float, int> timeToZoneIndex;
bool firstToken = true;
bool tokenReady = false;
this->Init();
this->Internal->ASCIIStream.open( this->FileName );
std::string tok = this->Internal->GetNextToken();
std::map<int, vtkSmartPointer<vtkDataSet> > connectivityShareZoneMap;
while ( !this->Internal->NextCharEOF )
{
tokenReady = false;
//cerr << "token is " << tok << endl;
if ( tok.empty() )
{
// whitespace: do nothing
......@@ -1644,7 +1698,11 @@ void vtkTecplotReader::ReadFile( vtkMultiBlockDataSet * multZone )
std::string format;
std::string elemType;
std::string ZoneName = untitledZoneName;
std::string zoneType;
std::string zoneName = untitledZoneName;
double solutionTime = 0;
bool solutionTimeIsSet = false;
int connectivityShareZoneId = -1;
tok = this->Internal->GetNextToken();
while ( !( tok != "T" &&
......@@ -1652,21 +1710,27 @@ void vtkTecplotReader::ReadFile( vtkMultiBlockDataSet * multZone )
tok != "J" &&
tok != "K" &&
tok != "N" &&
tok != "NODES" &&
tok != "E" &&
tok != "ELEMENTS" &&
tok != "ET" &&
tok != "ZONETYPE" &&
tok != "F" &&
tok != "D" &&
tok != "DT" &&
tok != "STRANDID" &&
tok != "SOLUTIONTIME" &&
tok != "DATAPACKING" &&
tok != "VARLOCATION"
tok != "VARLOCATION" &&
tok != "CONNECTIVITYSHAREZONE" &&
tok != "VARSHARELIST"
)
)
{
//cerr << "other token is " << tok << endl;
if ( tok == "T" )
{
ZoneName = this->Internal->GetNextToken();
zoneName = this->Internal->GetNextToken();
if ( !this->Internal->TokenIsString )
{
vtkErrorMacro( << this->FileName << ": Zone titles MUST be "
......@@ -1686,11 +1750,11 @@ void vtkTecplotReader::ReadFile( vtkMultiBlockDataSet * multZone )
{
numK = atoi( this->Internal->GetNextToken().c_str() );
}
else if ( tok == "N" )
else if ( tok == "N" || tok == "NODES" )
{
numNodes = atoi( this->Internal->GetNextToken().c_str() );
}
else if ( tok == "E" )
else if ( tok == "E" || tok == "ELEMENTS")
{
numElements = atoi( this->Internal->GetNextToken().c_str() );
}
......@@ -1698,6 +1762,15 @@ void vtkTecplotReader::ReadFile( vtkMultiBlockDataSet * multZone )
{
elemType = this->Internal->GetNextToken();
}
else if ( tok == "CONNECTIVITYSHAREZONE")
{
connectivityShareZoneId = atoi( this->Internal->GetNextToken().c_str() );
}
else if ( tok == "VARSHARELIST")
{
tok = this->Internal->GetNextToken();
tok = this->Internal->GetNextToken();
}
else if ( tok == "F" || tok == "DATAPACKING" )
{
format = this->Internal->GetNextToken();
......@@ -1771,11 +1844,16 @@ void vtkTecplotReader::ReadFile( vtkMultiBlockDataSet * multZone )
}
else if ( tok == "DT" )
{
//cerr << "have a DT token\n";
for ( int i = 0; i < this->NumberOfVariables; i ++ )
{
this->Internal->GetNextToken();
}
}
else if ( tok == "ZONETYPE" )
{
zoneType = this->Internal->GetNextToken();
}
else if ( tok == "D" )
{
vtkWarningMacro( << this->FileName << "; Tecplot zone record parameter "
......@@ -1784,48 +1862,136 @@ void vtkTecplotReader::ReadFile( vtkMultiBlockDataSet * multZone )
}
else if ( tok == "STRANDID" )
{
vtkWarningMacro( << this->FileName << "; Tecplot zone record parameter "
<< "'STRANDID' is currently unsupported." );
// vtkWarningMacro( << this->FileName << "; Tecplot zone record parameter "
// << "'STRANDID' is currently unsupported." );
this->Internal->GetNextToken();
}
else if ( tok == "SOLUTIONTIME" )
{
vtkWarningMacro( << this->FileName << "; Tecplot zone record parameter "
<< "'SOLUTIONTIME' is currently unsupported." );
this->Internal->GetNextToken();
solutionTime = atof(this->Internal->GetNextToken().c_str());
//cerr << solutionTime << " is the solution time\n";
solutionTimeIsSet = true;
}
tok = this->Internal->GetNextToken();
}
this->Internal->TokenBackup = tok;
this->ZoneNames.push_back( ZoneName );
this->ZoneNames.push_back( zoneName );
if ( format == "FEBLOCK" )
{
this->GetUnstructuredGridFromBlockPackingZone( numNodes, numElements,
elemType.c_str(), zoneIndex, ZoneName.c_str(), multZone );
elemType.c_str(), zoneIndex, zoneName.c_str(), multZone);
}
else if ( format == "FEPOINT" )
{
this->GetUnstructuredGridFromPointPackingZone( numNodes, numElements,
elemType.c_str(), zoneIndex, ZoneName.c_str(), multZone );
elemType.c_str(), zoneIndex, zoneName.c_str(), multZone );
}
else if ( format == "BLOCK" )
{
this->GetStructuredGridFromBlockPackingZone
( numI, numJ, numK, zoneIndex, ZoneName.c_str(), multZone );
if ( zoneType == "FETRIANGLE" )
{
vtkNew<vtkUnstructuredGrid> unstruct;
if (connectivityShareZoneId > -1)
{ // we do 0-based indexing while Tecplot does 1-based indexing
auto it = connectivityShareZoneMap.find(connectivityShareZoneId-1);
if (it == connectivityShareZoneMap.end())
{
vtkErrorMacro("Issue with CONNECTIVITYSHAREZONE information. Cannot find zone id " << connectivityShareZoneId);
return;
}
unstruct->ShallowCopy(it->second);
unstruct->GetPointData()->Initialize();
unstruct->GetCellData()->Initialize();
}
else
{
vtkNew<vtkFloatArray> coords;
coords->SetNumberOfComponents(3);
coords->SetNumberOfTuples(numNodes);
for (int j=0;j<3;j++)
{
for (int i=0;i<numNodes;i++)
{
float val = atof( this->Internal->GetNextToken().c_str() );
coords->SetComponent(i, j, val);
}
}
vtkNew<vtkPoints> points;
points->SetData(coords);
unstruct->SetPoints(points);
}
for (int i=3;i<this->NumberOfVariables;i++) // the first 3 variables are the coordinates
{
vtkNew<vtkFloatArray> data;
int length = -1;
if (this->CellBased[i] == 1)
{
length = numElements;
unstruct->GetCellData()->AddArray(data);
}
else
{
length = numNodes;
unstruct->GetPointData()->AddArray(data);
}
data->SetNumberOfTuples(length);
data->SetName(this->Variables[i].c_str());
for (int j=0;j<length;j++)
{
float val = atof( this->Internal->GetNextToken().c_str() );
data->SetComponent(j, 0, val);
}
}
if (connectivityShareZoneId == -1)
{
unstruct->Allocate(numElements);
for (int j=0;j<numElements;j++)
{
vtkIdType ids[3];
for (int i=0;i<3;i++)
{ // cell ids are 1-based indexing
ids[i] = atoi( this->Internal->GetNextToken().c_str() ) - 1;
}
unstruct->InsertNextCell(VTK_TRIANGLE, 3, ids);
}
}
connectivityShareZoneMap[zoneIndex] = unstruct;
if (!timeIsSet)
{
multZone->SetBlock(zoneIndex, unstruct);
multZone->GetMetaData(zoneIndex)->Set( vtkCompositeDataSet::NAME(), zoneName.c_str() );
}
else if (timeIsSet && std::abs(time - solutionTime) < .00001 && solutionTimeIsSet)
{
auto it=timeToZoneIndex.find(time);
if (it == timeToZoneIndex.end())
{
timeToZoneIndex[time] = 0;
}
multZone->SetBlock(timeToZoneIndex[time], unstruct);
multZone->GetMetaData(timeToZoneIndex[time])->Set( vtkCompositeDataSet::NAME(), zoneName.c_str() );
timeToZoneIndex[time]++;
}
}
else
{
this->GetStructuredGridFromBlockPackingZone
( numI, numJ, numK, zoneIndex, zoneName.c_str(), multZone );
}
}
else if ( format == "POINT" )
{
this->GetStructuredGridFromPointPackingZone
( numI, numJ, numK, zoneIndex, ZoneName.c_str(), multZone );
( numI, numJ, numK, zoneIndex, zoneName.c_str(), multZone );
}
else if ( format.empty() )
{
// No format given; we will assume we got a POINT format
this->GetStructuredGridFromPointPackingZone
( numI, numJ, numK, zoneIndex, ZoneName.c_str(), multZone );
( numI, numJ, numK, zoneIndex, zoneName.c_str(), multZone );
}
else
{
......
......@@ -206,7 +206,7 @@ protected:
* This function, the data loading engine, parses the Tecplot file to fill
* a vtkMultiBlockDataSet object.
*/
void ReadFile( vtkMultiBlockDataSet * multZone);
void ReadFile( vtkMultiBlockDataSet * multZone, bool timeIsSet, double time);
/**
* This function extracts each variable array from a block-packing (component-
......
96eef49643113f1838b797500571134f496c495c1233de5409581f419eb303578bf7789d59983b423f44fecb003ca24cb1b056c45f8f21c7f85fbbc08e22fd80
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment