You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
5002 lines
142 KiB
5002 lines
142 KiB
/*=========================================================================
|
|
|
|
Program: Visualization Toolkit
|
|
Module: $RCSfile: vtkExodusReader.cxx,v $
|
|
|
|
Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
|
|
All rights reserved.
|
|
See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
|
|
|
|
This software is distributed WITHOUT ANY WARRANTY; without even
|
|
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
|
PURPOSE. See the above copyright notice for more information.
|
|
|
|
=========================================================================*/
|
|
|
|
/*----------------------------------------------------------------------------
|
|
Copyright (c) Sandia Corporation
|
|
See Copyright.txt or http://www.paraview.org/HTML/Copyright.html for details.
|
|
----------------------------------------------------------------------------*/
|
|
|
|
#include "vtkExodusReader.h"
|
|
#include "vtkExodusModel.h"
|
|
#include "vtkCell.h"
|
|
#include "vtkCellData.h"
|
|
#include "vtkPointData.h"
|
|
#include "vtkFloatArray.h"
|
|
#include "vtkInformation.h"
|
|
#include "vtkInformationDoubleVectorKey.h"
|
|
#include "vtkInformationVector.h"
|
|
#include "vtkIntArray.h"
|
|
#include "vtkMath.h"
|
|
#include "vtkObjectFactory.h"
|
|
#include "vtkStreamingDemandDrivenPipeline.h"
|
|
#include "vtkUnstructuredGrid.h"
|
|
#include "vtkXMLParser.h"
|
|
#include "vtkWarpVector.h"
|
|
#include "vtkDSPFilterDefinition.h"
|
|
|
|
#include <sys/stat.h>
|
|
#include <ctype.h>
|
|
#include <exodusII.h>
|
|
|
|
#include <vtkstd/algorithm>
|
|
#include <vtkstd/string>
|
|
#include <vtkstd/vector>
|
|
#include <vtkstd/map>
|
|
#include <vtkstd/list>
|
|
#include "vtkStdString.h"
|
|
|
|
#define DEBUG 0
|
|
|
|
// vtkExodusMetadata is an internal helper class that
|
|
// manages the metadata associated with the point and cell
|
|
// arrays. This class uses stl
|
|
class vtkExodusMetadata
|
|
{
|
|
private:
|
|
int ArrayStatusInitValue[vtkExodusReader::NUM_ARRAY_TYPES];
|
|
|
|
// Field array stuff
|
|
vtkstd::vector<vtkStdString> pointArrayNames;
|
|
vtkstd::vector<int> pointArrayComponents;
|
|
vtkstd::vector<int> pointArrayStatus;
|
|
|
|
vtkstd::vector<vtkStdString> cellArrayNames;
|
|
vtkstd::vector<int> cellArrayComponents;
|
|
vtkstd::vector<int> cellArrayStatus;
|
|
|
|
int originalNumberOfPointArrays;
|
|
int originalNumberOfCellArrays;
|
|
|
|
// This is a cruddy hack... because we need to pass a
|
|
// char ** pointer to the exodus function
|
|
char **pointArrayRawBuffer;
|
|
char **cellArrayRawBuffer;
|
|
|
|
// Block stuff
|
|
vtkstd::vector<vtkStdString> blockNames;
|
|
vtkstd::vector<int> blockIds;
|
|
vtkstd::vector<int> blockStatus;
|
|
vtkstd::vector<int> numElementsInBlock;
|
|
|
|
// Node/Side set id stuff
|
|
// Store *Ids* for each node/side set
|
|
// Store *Size* for each node/side set
|
|
// Store number of *Distribution Factors** for each node/side set
|
|
// FIXME!!! since node/side set ids should be unique, should this
|
|
// be a 'set' instead of a 'vector'?
|
|
// FIXME!!! should we store side/edge type along with side set info?
|
|
vtkstd::vector<int> nodeSetId;
|
|
vtkstd::vector<int> nodeSetSize;
|
|
vtkstd::vector<int> nodeSetDistFact;
|
|
vtkstd::vector<int> nodeSetStatus;
|
|
vtkstd::vector<vtkStdString> nodeSetName;
|
|
|
|
vtkstd::vector<int> sideSetId;
|
|
vtkstd::vector<int> sideSetSize;
|
|
vtkstd::vector<int> sideSetDistFact;
|
|
vtkstd::vector<int> sideSetStatus;
|
|
vtkstd::vector<vtkStdString> sideSetName;
|
|
|
|
//part stuff. There is no PartStatus array
|
|
//a part is active only if all its blocks are active
|
|
vtkstd::vector<vtkStdString> partNames;
|
|
vtkstd::map<int,int> blockIDToPartID;
|
|
vtkstd::map<int,vtkstd::vector<int> > partIDToBlockIDs;
|
|
|
|
//material stuff. Again, no material array
|
|
//a material is active only is all its blocks are active
|
|
vtkstd::vector<vtkStdString> materialNames;
|
|
vtkstd::map<int,int> blockIDToMaterialID;
|
|
vtkstd::map<int,vtkstd::vector<int> > materialIDToBlockIDs;
|
|
|
|
//assembly stuff
|
|
vtkstd::vector<vtkStdString> assemblyNames;
|
|
vtkstd::map<int,vtkstd::vector<int> > blockIDToAssemblyIDs;
|
|
vtkstd::map<int,vtkstd::vector<int> > assemblyIDToBlockIDs;
|
|
|
|
|
|
//sortedorder[sortedID]=unsortedID
|
|
//can do name[sortedOrder[idx]]
|
|
vtkstd::map<int,int> sortedOrder;
|
|
|
|
int DisplayType;
|
|
|
|
public:
|
|
|
|
// Constructor
|
|
vtkExodusMetadata()
|
|
{
|
|
pointArrayRawBuffer = NULL;
|
|
cellArrayRawBuffer = NULL;
|
|
originalNumberOfPointArrays = 0;
|
|
originalNumberOfCellArrays = 0;
|
|
DisplayType=1;
|
|
for ( int i=0;i<vtkExodusReader::NUM_ARRAY_TYPES;i++ )
|
|
{
|
|
this->ArrayStatusInitValue[i] = 0;
|
|
}
|
|
}
|
|
|
|
// Destructor
|
|
~vtkExodusMetadata()
|
|
{
|
|
int i;
|
|
for (i=0; i< this->originalNumberOfPointArrays; i++)
|
|
{
|
|
delete [] this->pointArrayRawBuffer[i];
|
|
}
|
|
if (this->pointArrayRawBuffer)
|
|
{
|
|
delete [] this->pointArrayRawBuffer;
|
|
}
|
|
for (i=0; i< this->originalNumberOfCellArrays; i++)
|
|
{
|
|
delete [] this->cellArrayRawBuffer[i];
|
|
}
|
|
if (this->cellArrayRawBuffer)
|
|
{
|
|
delete [] this->cellArrayRawBuffer;
|
|
}
|
|
}
|
|
|
|
// Point array attributes
|
|
char** AllocatePointArrayNameBuffer(int num_strings);
|
|
char** GetPointArrayNameBuffer();
|
|
char *GetPointArrayOriginalName(int i)
|
|
{
|
|
return pointArrayRawBuffer[i];
|
|
}
|
|
inline int GetNumberOfPointArrays()
|
|
{
|
|
return pointArrayNames.size();
|
|
}
|
|
inline const char* GetPointArrayName(int idx)
|
|
{
|
|
return pointArrayNames[idx].c_str();
|
|
}
|
|
inline int GetPointArrayComponents(int idx)
|
|
{
|
|
return pointArrayComponents[idx];
|
|
}
|
|
inline int GetPointArrayStatus(int idx)
|
|
{
|
|
return pointArrayStatus[idx];
|
|
}
|
|
inline void SetPointArrayStatus(int idx, int on)
|
|
{
|
|
pointArrayStatus[idx] = on;
|
|
}
|
|
inline void SetPointArrayStatus(vtkStdString name, int flag)
|
|
{
|
|
for(int idx=0; idx<this->GetNumberOfPointArrays(); ++idx)
|
|
{
|
|
if ( name == this->pointArrayNames[idx] )
|
|
{
|
|
this->pointArrayStatus[idx] = flag;
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
inline int GetPointArrayStatus(vtkStdString name)
|
|
{
|
|
for(int idx=0; idx<this->GetNumberOfPointArrays(); ++idx)
|
|
{
|
|
if ( name == this->pointArrayNames[idx] )
|
|
return this->pointArrayStatus[idx];
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
// Cell array attributes
|
|
char** AllocateCellArrayNameBuffer(int num_strings);
|
|
char** GetCellArrayNameBuffer();
|
|
char *GetCellArrayOriginalName(int i)
|
|
{
|
|
return cellArrayRawBuffer[i];
|
|
}
|
|
inline int GetNumberOfCellArrays()
|
|
{
|
|
return cellArrayNames.size();
|
|
}
|
|
inline const char* GetCellArrayName(int idx)
|
|
{
|
|
return cellArrayNames[idx].c_str();
|
|
}
|
|
inline int GetCellArrayComponents(int idx)
|
|
{
|
|
return cellArrayComponents[idx];
|
|
}
|
|
inline void SetCellArrayStatus(int idx, int flag)
|
|
{
|
|
cellArrayStatus[idx] = flag;
|
|
}
|
|
inline void SetCellArrayStatus(vtkStdString name, int flag)
|
|
{
|
|
for(int idx=0; idx<this->GetNumberOfCellArrays(); ++idx)
|
|
{
|
|
if ( name == this->cellArrayNames[idx] )
|
|
{
|
|
this->cellArrayStatus[idx] = flag;
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
inline int GetCellArrayStatus(int idx)
|
|
{
|
|
return cellArrayStatus[idx];
|
|
}
|
|
inline int GetCellArrayStatus(vtkStdString name) {
|
|
for(int idx=0; idx<this->GetNumberOfCellArrays(); ++idx)
|
|
{
|
|
if ( name == this->cellArrayNames[idx] )
|
|
return this->cellArrayStatus[idx];
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
// These are used when accessing things like truth tables indices
|
|
inline int GetOriginalNumberOfPointArrays()
|
|
{
|
|
return originalNumberOfPointArrays;
|
|
}
|
|
inline int GetOriginalNumberOfCellArrays()
|
|
{
|
|
return originalNumberOfCellArrays;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------
|
|
// Node/Side set functions
|
|
//-----------------------------------------------------------------------
|
|
// id - node/side set exodus id
|
|
// size - node/side set size
|
|
// dist - number of distribution factors
|
|
// default node/side set status to 'of' or '0'
|
|
inline void AddNodeSet( const int id, const int size, const int dist )
|
|
{
|
|
char buffer[80];
|
|
sprintf(buffer, "NodeSet %d",id);
|
|
|
|
this->nodeSetId.push_back( id );
|
|
this->nodeSetName.push_back( buffer );
|
|
this->nodeSetSize.push_back( size );
|
|
this->nodeSetDistFact.push_back( dist );
|
|
this->nodeSetStatus.push_back( 0 );
|
|
}
|
|
inline void AddSideSet( const int id, const int size, const int dist )
|
|
{
|
|
char buffer[80];
|
|
sprintf(buffer, "SideSet %d",id);
|
|
|
|
this->sideSetId.push_back( id );
|
|
this->sideSetName.push_back( buffer );
|
|
this->sideSetSize.push_back( size );
|
|
this->sideSetDistFact.push_back( dist );
|
|
this->sideSetStatus.push_back( 0 );
|
|
}
|
|
|
|
// Do a bound check and return a non-sensical -1 for a count if the user
|
|
// asks for a non-existent id. The return value is not an error value
|
|
// per se, but we have to return something instead of overrunning the
|
|
// array bounds
|
|
//
|
|
// FIXME!!! this is simply the number of node/side sets set by
|
|
// vtkExodusReader, it *could* be different than the number
|
|
// reported by the exodus file. since vtkExodusReader loads
|
|
// metadata for all node/side sets this *should* agree with
|
|
// the number reported by exodus. Status flags specify which
|
|
// node/side sets get loaded and visualized.
|
|
inline int GetNumberOfNodeSets() { return this->nodeSetId.size(); }
|
|
inline int GetNumberOfSideSets() { return this->sideSetId.size(); }
|
|
|
|
inline int GetNodeSetId( const int id )
|
|
{
|
|
return (id>=0 && id<(int)nodeSetId.size()) ? nodeSetId[id] : -1;
|
|
}
|
|
inline int GetSideSetId( const int id )
|
|
{
|
|
return (id>=0 && id<(int)sideSetId.size()) ? sideSetId[id] : -1;
|
|
}
|
|
inline const char* GetNodeSetName( const int id )
|
|
{
|
|
return nodeSetName[id].c_str();
|
|
}
|
|
inline const char* GetSideSetName( const int id )
|
|
{
|
|
return sideSetName[id].c_str();
|
|
}
|
|
|
|
inline int GetNodeSetSize( const int id )
|
|
{
|
|
return (id>=0 && id<(int)nodeSetSize.size()) ? nodeSetSize[id] : -1;
|
|
}
|
|
inline int GetSideSetSize( const int id )
|
|
{
|
|
return (id>=0 && id<(int)sideSetSize.size()) ? sideSetSize[id] : -1;
|
|
}
|
|
|
|
inline int GetNodeSetDistFact( const int id )
|
|
{
|
|
return (id>=0 && id<(int)nodeSetDistFact.size()) ? nodeSetDistFact[id] : -1;
|
|
}
|
|
inline int GetSideSetDistFact( const int id )
|
|
{
|
|
return (id>=0 && id<(int)sideSetDistFact.size()) ? sideSetDistFact[id] : -1;
|
|
}
|
|
|
|
inline void SetNodeSetStatus( const int id, const int status )
|
|
{
|
|
if( id>=0 && id<(int)this->nodeSetStatus.size() )
|
|
{
|
|
this->nodeSetStatus[id] = status;
|
|
}
|
|
return;
|
|
}
|
|
inline void SetNodeSetStatus(vtkStdString name, int status)
|
|
{
|
|
for(vtkstd::vector<int>::size_type id=0; id < this->nodeSetStatus.size(); ++id)
|
|
{
|
|
if ( name == this->nodeSetName[id] )
|
|
{
|
|
this->SetNodeSetStatus(id,status);
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
inline void SetSideSetStatus( const int id, const int status )
|
|
{
|
|
if( id>=0 && id<(int)this->sideSetStatus.size() )
|
|
{
|
|
this->sideSetStatus[id] = status;
|
|
}
|
|
return;
|
|
}
|
|
inline void SetSideSetStatus(vtkStdString name, int status)
|
|
{
|
|
for(vtkstd::vector<int>::size_type id=0; id < this->sideSetStatus.size(); ++id)
|
|
{
|
|
if ( name == this->sideSetName[id] )
|
|
{
|
|
this->SetSideSetStatus(id,status);
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Return node/side set status if the id corresponds to a real node/side set.
|
|
// I the user asks for the status of a node/side set that doesn't exist, return
|
|
// zero and let the philosophers debate whether a node/side set that doesn't exist
|
|
// is on or off; that's at least 3 Phd thesies right there!
|
|
inline int GetNodeSetStatus(const int id )
|
|
{
|
|
return (id>=0 && id<(int)nodeSetStatus.size()) ? nodeSetStatus[id] : 0;
|
|
}
|
|
inline int GetNodeSetStatus(vtkStdString name)
|
|
{
|
|
for(vtkstd::vector<int>::size_type id=0; id < this->nodeSetStatus.size(); ++id)
|
|
{
|
|
if ( name == this->nodeSetName[id] )
|
|
{
|
|
return this->GetNodeSetStatus(id);
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
inline int GetSideSetStatus( const int id )
|
|
{
|
|
return (id>=0 && id<(int)sideSetStatus.size()) ? sideSetStatus[id] : 0;
|
|
}
|
|
inline int GetSideSetStatus(vtkStdString name)
|
|
{
|
|
for(vtkstd::vector<int>::size_type id=0; id < this->sideSetStatus.size(); ++id)
|
|
{
|
|
if ( name == this->sideSetName[id] )
|
|
{
|
|
return this->GetSideSetStatus(id);
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
//-----------------------------------------------------------------------
|
|
// End Node/Side set functions
|
|
//-----------------------------------------------------------------------
|
|
|
|
|
|
// Block attributes
|
|
inline void AddBlock(vtkStdString blockName, vtkStdString partName,
|
|
vtkStdString materialName,
|
|
vtkstd::vector<vtkStdString> localAssemblyNames,
|
|
int id, int num_elem, int status)
|
|
{
|
|
blockNames.push_back(blockName);
|
|
//cout << "added block " << blockName << " " << blockNames.size() << endl;
|
|
blockIds.push_back(id);
|
|
blockStatus.push_back(status);
|
|
numElementsInBlock.push_back(num_elem);
|
|
unsigned int i;
|
|
int found=0;
|
|
int blockID=blockNames.size()-1;
|
|
sortedOrder[blockID]=blockID;
|
|
//set up the Part Arrays
|
|
for (i=0;i<partNames.size();i++){
|
|
if (partNames[i]==partName)
|
|
{
|
|
blockIDToPartID[blockID]=i;
|
|
partIDToBlockIDs[i].push_back(blockID);
|
|
found=1;
|
|
}
|
|
}
|
|
if (!found)
|
|
{
|
|
int partID=partNames.size();
|
|
partNames.push_back(partName);
|
|
blockIDToPartID[blockID]=partID;
|
|
partIDToBlockIDs[partID]=vtkstd::vector<int>();
|
|
partIDToBlockIDs[partID].push_back(blockID);
|
|
}
|
|
|
|
//set up the material arrays
|
|
found=0;
|
|
for (i=0;i<materialNames.size();i++)
|
|
{
|
|
if (materialNames[i]==materialName)
|
|
{
|
|
blockIDToMaterialID[blockID]=i;
|
|
materialIDToBlockIDs[i].push_back(blockID);
|
|
found=1;
|
|
}
|
|
}
|
|
if (!found)
|
|
{
|
|
int materialID=materialNames.size();
|
|
materialNames.push_back(materialName);
|
|
blockIDToMaterialID[blockID]=materialID;
|
|
materialIDToBlockIDs[materialID]=vtkstd::vector<int>();
|
|
materialIDToBlockIDs[materialID].push_back(blockID);
|
|
}
|
|
|
|
//handle assembly stuff
|
|
for (i=0;i<localAssemblyNames.size();i++)
|
|
{
|
|
vtkStdString assemblyName=localAssemblyNames[i];
|
|
found=0;
|
|
for (vtkStdString::size_type j=0;j<assemblyNames.size();j++)
|
|
{
|
|
if (assemblyNames[j]==assemblyName){
|
|
blockIDToAssemblyIDs[blockID].push_back(j);
|
|
assemblyIDToBlockIDs[j].push_back(blockID);
|
|
found=1;
|
|
//cout << "added block " << blockID << " to assembly " << assemblyName << endl;
|
|
}
|
|
}
|
|
if (!found)
|
|
{
|
|
int assemblyID=assemblyNames.size();
|
|
assemblyNames.push_back(assemblyName);
|
|
blockIDToAssemblyIDs[blockID]=vtkstd::vector<int>();
|
|
blockIDToAssemblyIDs[blockID].push_back(assemblyID);
|
|
assemblyIDToBlockIDs[assemblyID]=vtkstd::vector<int>();
|
|
assemblyIDToBlockIDs[assemblyID].push_back(blockID);
|
|
//cout << "n added block " << blockID << " to assembly " << assemblyName << endl;
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
inline void ResetBlocks()
|
|
{
|
|
blockNames.erase(blockNames.begin(), blockNames.end());
|
|
blockIds.erase(blockIds.begin(), blockIds.end());
|
|
blockStatus.erase(blockStatus.begin(), blockStatus.end());
|
|
numElementsInBlock.erase(numElementsInBlock.begin(), numElementsInBlock.end());
|
|
partNames.erase(partNames.begin(),partNames.end());
|
|
materialNames.erase(materialNames.begin(),materialNames.end());
|
|
unsigned int i;
|
|
for (i=0;i<materialIDToBlockIDs.size();i++)
|
|
{
|
|
materialIDToBlockIDs[i].erase(materialIDToBlockIDs[i].begin(),
|
|
materialIDToBlockIDs[i].end());
|
|
}
|
|
materialIDToBlockIDs.erase(materialIDToBlockIDs.begin(),
|
|
materialIDToBlockIDs.end());
|
|
for (i=0;i<partIDToBlockIDs.size();i++)
|
|
{
|
|
partIDToBlockIDs[i].erase(partIDToBlockIDs[i].begin(),
|
|
partIDToBlockIDs[i].end());
|
|
}
|
|
for (i=0;i<assemblyIDToBlockIDs.size();i++)
|
|
{
|
|
assemblyIDToBlockIDs[i].erase(assemblyIDToBlockIDs[i].begin(),
|
|
assemblyIDToBlockIDs[i].end());
|
|
}
|
|
for (i=0;i<blockIDToAssemblyIDs.size();i++)
|
|
{
|
|
blockIDToAssemblyIDs[i].erase(blockIDToAssemblyIDs[i].begin(),
|
|
blockIDToAssemblyIDs[i].end());
|
|
}
|
|
partIDToBlockIDs.erase(partIDToBlockIDs.begin(),
|
|
partIDToBlockIDs.end());
|
|
blockIDToPartID.erase(blockIDToPartID.begin(),blockIDToPartID.end());
|
|
blockIDToMaterialID.erase(blockIDToMaterialID.begin(),
|
|
blockIDToMaterialID.end());
|
|
assemblyNames.erase(assemblyNames.begin(),assemblyNames.end());
|
|
blockIDToAssemblyIDs.erase(
|
|
blockIDToAssemblyIDs.begin(),blockIDToAssemblyIDs.end());
|
|
assemblyIDToBlockIDs.erase(
|
|
assemblyIDToBlockIDs.begin(),assemblyIDToBlockIDs.end());
|
|
sortedOrder.erase(sortedOrder.begin(),sortedOrder.end());
|
|
}
|
|
|
|
inline void SetDisplayType(int type)
|
|
{
|
|
DisplayType=type;
|
|
}
|
|
|
|
inline int GetNumberOfBlocks()
|
|
{
|
|
return blockNames.size();
|
|
}
|
|
inline int GetSortedOrder(int idx)
|
|
{
|
|
return sortedOrder[idx];
|
|
}
|
|
inline const char* GetBlockName(int idx)
|
|
{
|
|
return blockNames[sortedOrder[idx]].c_str();
|
|
}
|
|
inline int GetBlockId(int idx)
|
|
{
|
|
return blockIds[sortedOrder[idx]];
|
|
}
|
|
inline int GetNumElementsInBlock(int idx)
|
|
{
|
|
return numElementsInBlock[sortedOrder[idx]];
|
|
}
|
|
inline void SetBlockStatus(int idx, int flag)
|
|
{
|
|
blockStatus[sortedOrder[idx]] = flag;
|
|
}
|
|
inline void SetBlockStatus(vtkStdString name, int flag)
|
|
{
|
|
for(int idx=0; idx<this->GetNumberOfBlocks(); ++idx)
|
|
{
|
|
if ( name == this->blockNames[idx] )
|
|
{
|
|
this->blockStatus[idx] = flag;
|
|
//this->SetBlockStatus(idx,flag);
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
inline void SetUnsortedBlockStatus(int idx, int flag)
|
|
{
|
|
blockStatus[idx] = flag;
|
|
}
|
|
|
|
inline int GetUnsortedBlockStatus(int idx)
|
|
{
|
|
return blockStatus[idx];
|
|
}
|
|
inline int GetBlockStatus(int idx)
|
|
{
|
|
return blockStatus[sortedOrder[idx]];
|
|
}
|
|
inline int GetBlockStatus(vtkStdString name)
|
|
{
|
|
for(int idx=0; idx<this->GetNumberOfBlocks(); ++idx)
|
|
{
|
|
if ( name == this->blockNames[idx] )
|
|
return this->blockStatus[idx];
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
|
|
|
|
|
|
//Parts and Materials need to act directly on the
|
|
//blockStatus array. Otherwise the index is put through
|
|
//the sortedOrder array, which gives us garbage since we have a
|
|
//valid index already
|
|
inline int GetNumberOfParts()
|
|
{
|
|
return partNames.size();
|
|
}
|
|
inline const char* GetPartName(int idx)
|
|
{
|
|
return partNames[idx].c_str();
|
|
}
|
|
inline const char* GetPartBlockInfo(int idx)
|
|
{
|
|
static vtkStdString blocks;
|
|
blocks.erase();
|
|
char buffer[80];
|
|
for (unsigned int i=0;i<partIDToBlockIDs[idx].size();i++)
|
|
{
|
|
sprintf(buffer,"%d, ",blockIds[partIDToBlockIDs[idx][i]]);
|
|
blocks += buffer;
|
|
}
|
|
|
|
blocks.erase(blocks.size()-2,blocks.size()-1);
|
|
return blocks.c_str();
|
|
}
|
|
|
|
inline int GetPartStatus(int idx)
|
|
{
|
|
//a part is only active if all its blocks are active
|
|
for (unsigned int i=0;i<partIDToBlockIDs[idx].size();i++)
|
|
{
|
|
if (!blockStatus[partIDToBlockIDs[idx][i]])
|
|
{
|
|
return 0;
|
|
}
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
inline int GetPartStatus(vtkStdString name)
|
|
{
|
|
for (unsigned int i=0;i<partNames.size();i++)
|
|
{
|
|
if (partNames[i]==name)
|
|
{
|
|
return GetPartStatus(i);
|
|
}
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
inline void SetPartStatus(int idx, int on)
|
|
{
|
|
//update the block status for all the blocks in this part
|
|
for (unsigned int i=0;i<partIDToBlockIDs[idx].size();i++)
|
|
{
|
|
//this->SetBlockStatus(partIDToBlockIDs[idx][i],on);
|
|
this->blockStatus[partIDToBlockIDs[idx][i]]=on;
|
|
}
|
|
}
|
|
|
|
inline void SetPartStatus(vtkStdString name, int flag)
|
|
{
|
|
for(int idx=0; idx<this->GetNumberOfParts(); ++idx)
|
|
{
|
|
if ( name == this->partNames[idx] )
|
|
{
|
|
this->SetPartStatus(idx,flag);
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
inline int GetNumberOfMaterials()
|
|
{
|
|
return materialNames.size();
|
|
}
|
|
|
|
inline const char* GetMaterialName(int idx)
|
|
{
|
|
return materialNames[idx].c_str();
|
|
}
|
|
|
|
inline int GetMaterialStatus(int idx)
|
|
{
|
|
for (unsigned int i=0;i<materialIDToBlockIDs[idx].size();i++)
|
|
{
|
|
if (!blockStatus[materialIDToBlockIDs[idx][i]])
|
|
{
|
|
return 0;
|
|
}
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
inline int GetMaterialStatus(vtkStdString name)
|
|
{
|
|
for (unsigned int i=0;i<materialNames.size();i++)
|
|
{
|
|
if (materialNames[i]==name)
|
|
{
|
|
return GetMaterialStatus(i);
|
|
}
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
inline void SetMaterialStatus(int idx, int on)
|
|
{
|
|
//update the block status for all the blocks in this material
|
|
for (unsigned int i=0;i<materialIDToBlockIDs[idx].size();i++)
|
|
{
|
|
//this->SetBlockStatus(materialIDToBlockIDs[idx][i],on);
|
|
this->blockStatus[materialIDToBlockIDs[idx][i]]=on;
|
|
}
|
|
}
|
|
|
|
inline void SetMaterialStatus(vtkStdString name, int flag)
|
|
{
|
|
for(int idx=0; idx<this->GetNumberOfMaterials(); ++idx)
|
|
{
|
|
if ( name == this->materialNames[idx] )
|
|
{
|
|
this->SetMaterialStatus(idx,flag);
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
//Assembly stuff
|
|
inline int GetNumberOfAssemblies()
|
|
{
|
|
return assemblyNames.size();
|
|
}
|
|
|
|
inline const char* GetAssemblyName(int idx)
|
|
{
|
|
return assemblyNames[idx].c_str();
|
|
}
|
|
|
|
inline int GetAssemblyStatus(int idx)
|
|
{
|
|
for (unsigned int i=0;i<assemblyIDToBlockIDs[idx].size();i++)
|
|
{
|
|
if (!blockStatus[assemblyIDToBlockIDs[idx][i]])
|
|
{
|
|
return 0;
|
|
}
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
inline int GetAssemblyStatus(vtkStdString name)
|
|
{
|
|
for (unsigned int i=0;i<assemblyNames.size();i++)
|
|
{
|
|
if (assemblyNames[i]==name)
|
|
{
|
|
return GetAssemblyStatus(i);
|
|
}
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
inline void SetAssemblyStatus(int idx, int on)
|
|
{
|
|
//update the block status for all the blocks in this material
|
|
for (unsigned int i=0;i<assemblyIDToBlockIDs[idx].size();i++)
|
|
{
|
|
//this->SetBlockStatus(materialIDToBlockIDs[idx][i],on);
|
|
this->blockStatus[assemblyIDToBlockIDs[idx][i]]=on;
|
|
}
|
|
}
|
|
|
|
inline void SetAssemblyStatus(vtkStdString name, int flag)
|
|
{
|
|
for(int idx=0; idx<this->GetNumberOfAssemblies(); ++idx)
|
|
{
|
|
if ( name == this->assemblyNames[idx] )
|
|
{
|
|
this->SetAssemblyStatus(idx,flag);
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
//performs a mapping from the exodus block ID to the block ID used by
|
|
//Set/GetUnsortedBlockStatus
|
|
inline int GetBlockIndex(int exodusID)
|
|
{
|
|
for (vtkstd::vector<int>::size_type i=0;i<blockIds.size();i++)
|
|
{
|
|
if (exodusID==blockIds[i])
|
|
{
|
|
return i;
|
|
}
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
|
|
// This method is important to call when your done setting metadata
|
|
void Finalize();
|
|
|
|
//BTX
|
|
static int VectorizeArrays(
|
|
int numOriginalNames, char **originalNames,
|
|
vtkstd::vector<vtkStdString> *newNames, vtkstd::vector<int> *newSize);
|
|
//ETX
|
|
|
|
void SortBlocks()
|
|
{
|
|
int i;
|
|
for (i=blockIds.size()-1;i>=0;i--)
|
|
{
|
|
for (int j=1;j<=i;j++)
|
|
{
|
|
if (blockIds[sortedOrder[j-1]]>blockIds[sortedOrder[j]])
|
|
{
|
|
int t=sortedOrder[j-1];
|
|
sortedOrder[j-1]=sortedOrder[j];
|
|
sortedOrder[j]=t;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void SetArrayStatusInitValue( vtkExodusReader::ArrayType type, int value )
|
|
{
|
|
this->ArrayStatusInitValue[type] = value;
|
|
}
|
|
|
|
int GetArrayStatusInitValue( vtkExodusReader::ArrayType type )
|
|
{
|
|
return this->ArrayStatusInitValue[type];
|
|
}
|
|
|
|
};
|
|
|
|
|
|
class vtkExodusXMLParser: public vtkXMLParser
|
|
{
|
|
private:
|
|
vtkstd::map<vtkStdString,vtkStdString> MaterialSpecifications;
|
|
vtkstd::map<vtkStdString,vtkStdString> MaterialDescriptions;
|
|
vtkstd::map<vtkStdString,vtkStdString> PartDescriptions;
|
|
vtkstd::vector<vtkStdString> MaterialNames;
|
|
vtkstd::vector<vtkStdString> BlockNames;
|
|
char* Filename;
|
|
vtkStdString PartNumber;
|
|
vtkStdString InstanceNumber;
|
|
vtkstd::map<int,vtkStdString> BlockIDToPartNumber;
|
|
vtkstd::map<vtkStdString,vtkstd::vector<vtkStdString> > PartNumberToAssemblyNumbers;
|
|
vtkstd::map<vtkStdString,vtkstd::vector<vtkStdString> > PartNumberToAssemblyDescriptions;
|
|
vtkstd::map<vtkStdString,vtkStdString> AssemblyDescriptions;
|
|
vtkstd::vector<vtkStdString> CurrentAssemblyNumbers;
|
|
vtkstd::vector<vtkStdString> CurrentAssemblyDescriptions;
|
|
|
|
//hierarchical list mappings
|
|
vtkstd::list<vtkStdString> apbList;
|
|
vtkstd::map<vtkStdString,vtkstd::vector<int> > apbToBlocks;
|
|
vtkstd::map<vtkStdString,int> apbIndents;
|
|
public:
|
|
|
|
vtkExodusXMLParser(char* filename)
|
|
{
|
|
this->SetFileName(filename);
|
|
this->Parse();
|
|
this->PartNumber="";
|
|
this->InstanceNumber="";
|
|
}
|
|
|
|
virtual ~vtkExodusXMLParser() {}
|
|
|
|
virtual vtkStdString GetPartNumber(int block)
|
|
{
|
|
return this->BlockIDToPartNumber[block];
|
|
}
|
|
virtual vtkStdString GetPartDescription(int block)
|
|
{
|
|
return this->PartDescriptions[this->BlockIDToPartNumber[block]];
|
|
}
|
|
virtual vtkStdString GetMaterialDescription(int block)
|
|
{
|
|
return this->MaterialDescriptions[this->BlockIDToPartNumber[block]];
|
|
}
|
|
virtual vtkStdString GetMaterialSpecification(int block)
|
|
{
|
|
return this->MaterialSpecifications[this->BlockIDToPartNumber[block]];
|
|
}
|
|
virtual vtkstd::vector<vtkStdString> GetAssemblyNumbers(int block)
|
|
{
|
|
return this->PartNumberToAssemblyNumbers[this->BlockIDToPartNumber[block]];
|
|
}
|
|
virtual vtkstd::vector<vtkStdString> GetAssemblyDescriptions(int block)
|
|
{
|
|
return this->PartNumberToAssemblyDescriptions[this->BlockIDToPartNumber[block]];
|
|
}
|
|
|
|
virtual int GetNumberOfHierarchyEntries()
|
|
{
|
|
return this->apbList.size();
|
|
}
|
|
|
|
virtual vtkStdString GetHierarchyEntry(int num)
|
|
{
|
|
//since it's an STL list, we need to get the correct entry
|
|
vtkstd::list<vtkStdString>::iterator iter=this->apbList.begin();
|
|
for(int i=0;i<num;i++){
|
|
iter++;
|
|
}
|
|
return (*iter);
|
|
}
|
|
|
|
virtual vtkstd::vector<int> GetBlocksForEntry(int num)
|
|
{
|
|
return this->apbToBlocks[this->GetHierarchyEntry(num)];
|
|
}
|
|
|
|
virtual vtkstd::vector<int> GetBlocksForEntry(vtkStdString entry)
|
|
{
|
|
return this->apbToBlocks[entry];
|
|
}
|
|
|
|
protected:
|
|
virtual void StartElement(const char* tname, const char** attrs)
|
|
{
|
|
const char* name=strrchr(tname,':');
|
|
if (!name)
|
|
{
|
|
name=tname;
|
|
}
|
|
else
|
|
{
|
|
name++;
|
|
}
|
|
|
|
if (strcmp(name,"assembly")==0)
|
|
{
|
|
const char* assemblyNumber=this->GetValue("number",attrs);
|
|
if (assemblyNumber)
|
|
{
|
|
this->CurrentAssemblyNumbers.push_back(vtkStdString(assemblyNumber));
|
|
}
|
|
|
|
const char* assemblyDescription=this->GetValue("description",attrs);
|
|
if (assemblyDescription)
|
|
{
|
|
this->CurrentAssemblyDescriptions.push_back(vtkStdString(assemblyDescription));
|
|
}
|
|
|
|
//make the entry for the hierarchical list
|
|
vtkStdString result=vtkStdString("");
|
|
for (vtkstd::vector<int>::size_type i=0;
|
|
i<this->CurrentAssemblyNumbers.size()-1;
|
|
i++)
|
|
{
|
|
result+=vtkStdString(" ");
|
|
}
|
|
|
|
result+=vtkStdString("Assembly: ")+
|
|
assemblyDescription+vtkStdString(" (")+
|
|
assemblyNumber+vtkStdString(")");
|
|
apbList.push_back(result);
|
|
//record the indent level, used when we add blocks
|
|
apbIndents[result]=this->CurrentAssemblyNumbers.size()-1;
|
|
//make the blocks array
|
|
apbToBlocks[result]=vtkstd::vector<int>();
|
|
}
|
|
if (strcmp(name,"part")==0)
|
|
{
|
|
const char* instance=this->GetValue("instance",attrs);
|
|
vtkStdString instanceString=vtkStdString("");
|
|
if (instance)
|
|
{
|
|
instanceString=vtkStdString(instance);
|
|
}
|
|
|
|
const char* partString=this->GetValue("number",attrs);
|
|
if (partString)
|
|
{
|
|
this->PartNumber=vtkStdString(partString)+
|
|
vtkStdString(" Instance: ")+
|
|
instanceString;
|
|
}
|
|
|
|
const char* partDescString=this->GetValue("description",attrs);
|
|
if (partDescString && this->PartNumber!="")
|
|
{
|
|
this->PartDescriptions[this->PartNumber]=
|
|
partDescString;
|
|
}
|
|
|
|
//copy the current assemblies to the assemblies list for this part.
|
|
this->PartNumberToAssemblyNumbers[this->PartNumber]=
|
|
vtkstd::vector<vtkStdString>(this->CurrentAssemblyNumbers);
|
|
this->PartNumberToAssemblyDescriptions[this->PartNumber]=
|
|
vtkstd::vector<vtkStdString>(this->CurrentAssemblyDescriptions);
|
|
|
|
//make the hierarchical display entry
|
|
vtkStdString result=vtkStdString("");
|
|
for (vtkstd::vector<int>::size_type i=0;
|
|
i<this->CurrentAssemblyNumbers.size();
|
|
i++)
|
|
{
|
|
result+=vtkStdString(" ");
|
|
}
|
|
result+=vtkStdString("Part: ")+
|
|
partDescString+vtkStdString(" (")+
|
|
partString+vtkStdString(")")+vtkStdString(" Instance: ")+
|
|
instanceString;
|
|
apbList.push_back(result);
|
|
//record the indent level
|
|
apbIndents[result]=this->CurrentAssemblyNumbers.size();
|
|
apbToBlocks[result]=vtkstd::vector<int>();
|
|
}
|
|
else if (strcmp(name,"material-specification")==0)
|
|
{
|
|
if (this->PartNumber!="")
|
|
{
|
|
const char * materialDescriptionString=
|
|
GetValue("description",attrs);
|
|
if (materialDescriptionString)
|
|
{
|
|
this->MaterialDescriptions[this->PartNumber]=
|
|
vtkStdString(materialDescriptionString);
|
|
}
|
|
|
|
const char * materialSpecificationString=
|
|
GetValue("specification",attrs);
|
|
if (materialSpecificationString)
|
|
{
|
|
this->MaterialSpecifications[this->PartNumber]=
|
|
vtkStdString(materialSpecificationString);
|
|
}
|
|
}
|
|
}
|
|
else if (strcmp(name,"blocks")==0 || strcmp(name,"dart:blocks")==0)
|
|
{
|
|
const char* instance=this->GetValue("part-instance",attrs);
|
|
vtkStdString instanceString=vtkStdString("");
|
|
if (instance)
|
|
{
|
|
this->InstanceNumber=vtkStdString(instance);
|
|
}
|
|
const char* partString=this->GetValue("part-number",attrs);
|
|
if (partString)
|
|
{
|
|
this->PartNumber=vtkStdString(partString);
|
|
}
|
|
}
|
|
else if (strcmp(name,"block")==0 || strcmp(name,"dart:block")==0)
|
|
{
|
|
|
|
if (this->PartNumber!="")
|
|
{
|
|
const char* blockString=this->GetValue("id",attrs);
|
|
if (blockString)
|
|
{
|
|
int id=atoi(blockString);
|
|
this->BlockIDToPartNumber[id]=this->PartNumber+
|
|
vtkStdString(" Instance: ")+this->InstanceNumber;
|
|
|
|
//first insert block entry into apblist
|
|
vtkStdString apbIndexString=this->PartNumber+
|
|
vtkStdString(") Instance: ")+this->InstanceNumber;
|
|
vtkStdString partEntry=findEntry(this->apbList,apbIndexString);
|
|
vtkStdString blockEntry;
|
|
if (partEntry!=vtkStdString(""))
|
|
{
|
|
//insert into apbList
|
|
vtkstd::list<vtkStdString>::iterator pos=
|
|
vtkstd::find(this->apbList.begin(),this->apbList.end(),partEntry);
|
|
pos++;
|
|
|
|
vtkStdString result=vtkStdString("");
|
|
for (int i=0;i<apbIndents[partEntry]+1;i++)
|
|
{
|
|
result+=vtkStdString(" ");
|
|
}
|
|
result+=vtkStdString("Block: ")+vtkStdString(blockString);
|
|
blockEntry=result;
|
|
this->apbList.insert(pos,result);
|
|
apbToBlocks[result]=vtkstd::vector<int>();
|
|
}
|
|
|
|
//update mapping
|
|
//we know block number, so can get part number to update that.
|
|
//using part number, we can update assembly mappings
|
|
vtkStdString partIndexString=this->PartNumber+
|
|
vtkStdString(" Instance: ")+this->InstanceNumber;
|
|
//we know the part entry
|
|
//add block ID to block entry
|
|
apbToBlocks[blockEntry].push_back(id);
|
|
//add block ID to part
|
|
apbToBlocks[partEntry].push_back(id);
|
|
|
|
//get the assemblies
|
|
vtkstd::vector<vtkStdString> assemblies=
|
|
this->PartNumberToAssemblyNumbers[partIndexString];
|
|
//add block ID to assemblies
|
|
for (vtkstd::vector<vtkStdString>::size_type j=0;j<assemblies.size();j++)
|
|
{
|
|
vtkStdString assemblyEntry=findEntry(this->apbList,assemblies[j]);
|
|
apbToBlocks[assemblyEntry].push_back(id);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//returns the first string that contains sstring
|
|
virtual vtkStdString findEntry(vtkstd::list<vtkStdString> slist,
|
|
vtkStdString sstring){
|
|
for (vtkstd::list<vtkStdString>::iterator i=slist.begin();
|
|
i!=slist.end();
|
|
i++)
|
|
{
|
|
if ((*i).find(sstring)!=vtkStdString::npos)
|
|
{
|
|
return (*i);
|
|
}
|
|
}
|
|
return vtkStdString("");
|
|
}
|
|
|
|
virtual void EndElement(const char* tname)
|
|
{
|
|
const char* name=strrchr(tname,':');
|
|
if (!name)
|
|
{
|
|
name=tname;
|
|
}
|
|
else
|
|
{
|
|
name++;
|
|
}
|
|
|
|
if (strcmp(name,"assembly")==0)
|
|
{
|
|
this->CurrentAssemblyNumbers.pop_back();
|
|
this->CurrentAssemblyDescriptions.pop_back();
|
|
}
|
|
if (strcmp(name,"blocks")==0 || strcmp(name,"dart:blocks")==0)
|
|
{
|
|
this->PartNumber="";
|
|
}
|
|
}
|
|
|
|
virtual int ParsingComplete()
|
|
{
|
|
//cout << "done parsing\n";
|
|
//vtkstd::map<int,vtkStdString>::iterator i;
|
|
//for (i=this->BlockIDToPartNumber.begin();
|
|
// i!=this->BlockIDToPartNumber.end();i++)
|
|
//{
|
|
//cout << "Block " << (*i).first << "\n Part Number: " << (*i).second
|
|
// << "\n Part Description: " << this->PartDescriptions[(*i).second]
|
|
// << "\n Material Description: "
|
|
// << this->MaterialDescriptions[(*i).second]
|
|
// <<"\n Material Specifications: "
|
|
// << this->MaterialSpecifications[(*i).second] << endl;
|
|
//
|
|
//
|
|
//}
|
|
//cout << "Block " << (*i).first << "\n Part Number: " << (*i).second << " Assemblies: ";
|
|
//for (int j=0;j<this->PartNumberToAssemblyNumbers[(*i).second].size();j++){
|
|
// cout << this->PartNumberToAssemblyNumbers[(*i).second][j] << " ";
|
|
//}
|
|
//cout << endl;
|
|
//}
|
|
//int count=0;
|
|
//for (vtkstd::list<vtkStdString>::iterator i=this->apbList.begin();i!=this->apbList.end();i++){
|
|
//cout << (*i) << " blocks:";
|
|
//for (int j=0;j<apbToBlocks[(*i)].size();j++){
|
|
// cout << " " << apbToBlocks[(*i)][j];
|
|
//}
|
|
//cout << endl;
|
|
//cout << count++ << endl;
|
|
//}
|
|
|
|
return vtkXMLParser::ParsingComplete();
|
|
}
|
|
|
|
virtual const char* GetValue(const char* attr,const char** attrs)
|
|
{
|
|
int i;
|
|
for (i=0;attrs[i];i+=2)
|
|
{
|
|
const char* name=strrchr(attrs[i],':');
|
|
if (!name)
|
|
{
|
|
name=attrs[i];
|
|
}
|
|
else
|
|
{
|
|
name++;
|
|
}
|
|
if (strcmp(attr,name)==0)
|
|
{
|
|
return attrs[i+1];
|
|
}
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
private:
|
|
vtkExodusXMLParser(const vtkExodusXMLParser&); // Not implemented
|
|
void operator=(const vtkExodusXMLParser&); // Not implemented
|
|
};
|
|
|
|
|
|
// This is a cruddy hack... because we need to pass a
|
|
// char ** pointer to the exodus function
|
|
char** vtkExodusMetadata::GetPointArrayNameBuffer()
|
|
{
|
|
return this->pointArrayRawBuffer;
|
|
}
|
|
|
|
char** vtkExodusMetadata::AllocatePointArrayNameBuffer(int num_strings)
|
|
{
|
|
int idx;
|
|
|
|
if (this->pointArrayRawBuffer)
|
|
{
|
|
for (idx = 0; idx < this->originalNumberOfPointArrays; ++idx)
|
|
{
|
|
delete [] this->pointArrayRawBuffer[idx];
|
|
}
|
|
delete [] this->pointArrayRawBuffer;
|
|
this->pointArrayRawBuffer = NULL;
|
|
this->originalNumberOfPointArrays = 0;
|
|
}
|
|
|
|
if (num_strings > 0)
|
|
{
|
|
this->originalNumberOfPointArrays = num_strings;
|
|
this->pointArrayRawBuffer = new char*[num_strings];
|
|
|
|
for (idx = 0; idx < num_strings; ++idx)
|
|
{
|
|
this->pointArrayRawBuffer[idx] = new char[MAX_STR_LENGTH+1];
|
|
}
|
|
}
|
|
|
|
return this->pointArrayRawBuffer;
|
|
}
|
|
|
|
char** vtkExodusMetadata::GetCellArrayNameBuffer()
|
|
{
|
|
return this->cellArrayRawBuffer;
|
|
}
|
|
|
|
char** vtkExodusMetadata::AllocateCellArrayNameBuffer(int num_strings)
|
|
{
|
|
int idx;
|
|
|
|
if (this->cellArrayRawBuffer)
|
|
{
|
|
for (idx = 0; idx < this->originalNumberOfCellArrays; ++idx)
|
|
{
|
|
delete [] this->cellArrayRawBuffer[idx];
|
|
}
|
|
delete [] this->cellArrayRawBuffer;
|
|
this->cellArrayRawBuffer = NULL;
|
|
this->originalNumberOfCellArrays = 0;
|
|
}
|
|
|
|
if (num_strings > 0)
|
|
{
|
|
this->originalNumberOfCellArrays = num_strings;
|
|
this->cellArrayRawBuffer = new char*[num_strings];
|
|
|
|
for (idx = 0; idx < num_strings; ++idx)
|
|
{
|
|
this->cellArrayRawBuffer[idx] = new char[MAX_STR_LENGTH+1];
|
|
}
|
|
}
|
|
|
|
return this->cellArrayRawBuffer;
|
|
}
|
|
|
|
int vtkExodusMetadata::VectorizeArrays(
|
|
int numOriginalNames, char **originalNames,
|
|
vtkstd::vector<vtkStdString> *newNames, vtkstd::vector<int> *newSize)
|
|
{
|
|
newNames->erase(newNames->begin(),newNames->end());
|
|
newSize->erase(newSize->begin(),newSize->end());
|
|
|
|
// Go through names and combine any vectors
|
|
//
|
|
// namex )
|
|
// namey )-> name
|
|
// namez )
|
|
|
|
int idx = 0;
|
|
while (idx < numOriginalNames)
|
|
{
|
|
int len = strlen(originalNames[idx]);
|
|
char last_char = toupper(originalNames[idx][len-1]);
|
|
|
|
char *newName = vtkExodusReader::StrDupWithNew(originalNames[idx]);
|
|
int nextIdx = idx + 1;
|
|
|
|
if (last_char=='X')
|
|
{
|
|
if ((nextIdx < numOriginalNames) &&
|
|
(toupper(originalNames[nextIdx][len-1])=='Y') &&
|
|
!(strncmp(newName, originalNames[nextIdx], len-1)))
|
|
{
|
|
nextIdx++;
|
|
newName[len-1] = '\0';
|
|
|
|
if ((nextIdx < numOriginalNames) &&
|
|
(toupper(originalNames[nextIdx][len-1])=='Z') &&
|
|
!(strncmp(newName, originalNames[nextIdx], len-1)))
|
|
{
|
|
nextIdx++;
|
|
}
|
|
}
|
|
}
|
|
|
|
int numComponents = nextIdx - idx;
|
|
|
|
newNames->push_back(newName);
|
|
delete []newName;
|
|
newSize->push_back(numComponents);
|
|
|
|
idx = nextIdx;
|
|
}
|
|
|
|
return newNames->size();
|
|
}
|
|
|
|
void vtkExodusMetadata::Finalize()
|
|
{
|
|
int i;
|
|
|
|
////////////////////////////////
|
|
// Point Arrays
|
|
////////////////////////////////
|
|
|
|
int numNewArrays = vtkExodusMetadata::VectorizeArrays(
|
|
originalNumberOfPointArrays, pointArrayRawBuffer,
|
|
&pointArrayNames, &pointArrayComponents);
|
|
|
|
pointArrayStatus.erase(pointArrayStatus.begin(), pointArrayStatus.end());
|
|
|
|
for (i=0; i<numNewArrays; i++)
|
|
{
|
|
pointArrayStatus.push_back(
|
|
this->GetArrayStatusInitValue( vtkExodusReader::POINT ) );
|
|
}
|
|
|
|
////////////////////////////////
|
|
// Cell Arrays
|
|
////////////////////////////////
|
|
|
|
numNewArrays = vtkExodusMetadata::VectorizeArrays(
|
|
originalNumberOfCellArrays, cellArrayRawBuffer,
|
|
&cellArrayNames, &cellArrayComponents);
|
|
|
|
cellArrayStatus.erase(cellArrayStatus.begin(), cellArrayStatus.end());
|
|
|
|
for (i=0; i<numNewArrays; i++)
|
|
{
|
|
cellArrayStatus.push_back(
|
|
this->GetArrayStatusInitValue( vtkExodusReader::CELL ) );
|
|
}
|
|
|
|
this->SortBlocks();
|
|
}
|
|
|
|
|
|
vtkCxxRevisionMacro(vtkExodusReader, "$Revision: 1.9 $");
|
|
vtkStandardNewMacro(vtkExodusReader);
|
|
|
|
#ifdef ARRAY_TYPE_NAMES_IN_CXX_FILE
|
|
const char *ArrayTypeNames[vtkExodusReader::NUM_ARRAY_TYPES] = {
|
|
"CELL",
|
|
"POINT",
|
|
"BLOCK",
|
|
"PART",
|
|
"MATERIAL",
|
|
"ASSEMBLY",
|
|
"HIERARCHY"
|
|
};
|
|
|
|
const char *
|
|
vtkExodusReader::GetArrayTypeName( vtkExodusReader::ArrayType type )
|
|
{
|
|
return ArrayTypeNames[ type ];
|
|
}
|
|
|
|
#else // method in .h file
|
|
const char *vtkExodusReader::ArrayTypeNames[NUM_ARRAY_TYPES] = {
|
|
"CELL",
|
|
"POINT",
|
|
"BLOCK",
|
|
"PART",
|
|
"MATERIAL",
|
|
"ASSEMBLY",
|
|
"HIERARCHY"
|
|
};
|
|
#endif
|
|
|
|
//----------------------------------------------------------------------------
|
|
// Description:
|
|
// Instantiate object with NULL filename.
|
|
vtkExodusReader::vtkExodusReader()
|
|
{
|
|
this->FileName = NULL;
|
|
this->XMLFileName=NULL;
|
|
|
|
this->TimeStep = 0;
|
|
this->ActualTimeStep = 0;
|
|
this->GenerateBlockIdCellArray = 1;
|
|
this->GenerateGlobalElementIdArray = 0;
|
|
this->GenerateGlobalNodeIdArray = 1;
|
|
this->ApplyDisplacements = 1;
|
|
this->DisplacementMagnitude = 1;
|
|
|
|
this->Title = new char[MAX_LINE_LENGTH+1];
|
|
this->NumberOfBlocks = 0;
|
|
this->NumberOfUsedNodes = 0;
|
|
this->NumberOfNodesInFile = 0;
|
|
this->NumberOfTimeSteps = 0;
|
|
this->ExodusCPUWordSize = 0;
|
|
this->ExodusIOWordSize = 0;
|
|
this->ExodusVersion = 0.0;
|
|
this->CurrentHandle = -1;
|
|
this->CurrentFileName = NULL;
|
|
this->CurrentXMLFileName = NULL;
|
|
this->TimeStepRange[0] = 0;
|
|
this->TimeStepRange[1] = 0;
|
|
|
|
this->DataCache = vtkUnstructuredGrid::New();
|
|
this->MetaData = new vtkExodusMetadata;
|
|
this->RemakeDataCacheFlag = 1;
|
|
this->NewGeometryCount = 0;
|
|
|
|
this->CellVarTruthTable = vtkIntArray::New();
|
|
this->PointMap = vtkIntArray::New();
|
|
this->ReversePointMap = vtkIntArray::New();
|
|
|
|
this->ExodusModel = NULL;
|
|
this->ExodusModelMetadata = 0;
|
|
this->PackExodusModelOntoOutput = 1;
|
|
this->DisplayType=1;
|
|
this->Parser=NULL;
|
|
|
|
this->GlobalElementIdCache=NULL;
|
|
|
|
//begin USE_EXO_DSP_FILTERS
|
|
this->DSPFilteringIsEnabled=0;
|
|
this->DSPFilters=NULL;
|
|
this->AddingFilter = vtkDSPFilterDefinition::New();
|
|
//end USE_EXO_DSP_FILTERS
|
|
|
|
this->SetNumberOfInputPorts(0);
|
|
}
|
|
|
|
|
|
//----------------------------------------------------------------------------
|
|
vtkExodusReader::~vtkExodusReader()
|
|
{
|
|
this->SetFileName(NULL);
|
|
this->SetXMLFileName(NULL);
|
|
|
|
this->SetTitle(NULL);
|
|
this->SetCurrentFileName(NULL);
|
|
|
|
this->DataCache->Delete();
|
|
this->DataCache = NULL;
|
|
|
|
this->CellVarTruthTable->Delete();
|
|
this->CellVarTruthTable = NULL;
|
|
|
|
this->PointMap->Delete();
|
|
this->PointMap = NULL;
|
|
this->ReversePointMap->Delete();
|
|
this->ReversePointMap = NULL;
|
|
|
|
if (this->ExodusModel)
|
|
{
|
|
this->ExodusModel->Delete();
|
|
this->ExodusModel = NULL;
|
|
}
|
|
|
|
this->SetGlobalElementIdCache(NULL);
|
|
|
|
//begin USE_EXO_DSP_FILTERS
|
|
if(this->DSPFilters)
|
|
{
|
|
for(int i=0;i<this->GetNumberOfBlockArrays();i++)
|
|
{
|
|
this->DSPFilters[i]->Delete();
|
|
}
|
|
delete[] this->DSPFilters ;
|
|
this->DSPFilters=NULL;
|
|
}
|
|
//end USE_EXO_DSP_FILTERS
|
|
|
|
|
|
if (this->Parser){
|
|
this->Parser->Delete();
|
|
this->Parser=NULL;
|
|
}
|
|
|
|
delete this->MetaData;
|
|
|
|
//begin USE_EXO_DSP_FILTERS
|
|
if (this->AddingFilter)
|
|
{
|
|
this->AddingFilter->Delete();
|
|
}
|
|
//end USE_EXO_DSP_FILTERS
|
|
|
|
}
|
|
|
|
void vtkExodusReader::NewExodusModel()
|
|
{
|
|
// These arrays are required by vtkExodusIIWriter
|
|
|
|
this->GenerateBlockIdCellArrayOn();
|
|
this->GenerateGlobalElementIdArrayOn();
|
|
this->GenerateGlobalNodeIdArrayOn();
|
|
|
|
if (this->ExodusModel)
|
|
{
|
|
this->ExodusModel->Reset();
|
|
return;
|
|
}
|
|
|
|
this->ExodusModel = vtkExodusModel::New();
|
|
}
|
|
|
|
void vtkExodusReader::SetGlobalElementIdCache(int *list)
|
|
{
|
|
if (this->GlobalElementIdCache)
|
|
{
|
|
delete [] this->GlobalElementIdCache;
|
|
this->GlobalElementIdCache = NULL;
|
|
}
|
|
|
|
if (list)
|
|
{
|
|
this->GlobalElementIdCache = list;
|
|
}
|
|
}
|
|
|
|
// Point array info accessors
|
|
int vtkExodusReader::GetNumberOfPointArrays()
|
|
{
|
|
return this->MetaData->GetNumberOfPointArrays();
|
|
}
|
|
|
|
const char* vtkExodusReader::GetPointArrayName(int arrayIdx)
|
|
{
|
|
return this->MetaData->GetPointArrayName(arrayIdx);
|
|
}
|
|
|
|
int vtkExodusReader::GetPointArrayNumberOfComponents(int arrayIdx)
|
|
{
|
|
return this->MetaData->GetPointArrayComponents(arrayIdx);
|
|
}
|
|
|
|
void vtkExodusReader::SetPointArrayStatus(int index, int flag)
|
|
{
|
|
int n = this->MetaData->GetOriginalNumberOfPointArrays();
|
|
|
|
if ((index >= 0) && (index < n))
|
|
{
|
|
this->MetaData->SetPointArrayStatus(index, flag);
|
|
this->Modified();
|
|
}
|
|
}
|
|
|
|
void vtkExodusReader::SetPointArrayStatus(const char* name, int flag)
|
|
{
|
|
this->MetaData->SetPointArrayStatus(name, flag);
|
|
this->Modified();
|
|
}
|
|
|
|
int vtkExodusReader::GetPointArrayStatus(int index)
|
|
{
|
|
int n = this->MetaData->GetOriginalNumberOfPointArrays();
|
|
|
|
if ((index >= 0) && (index < n))
|
|
{
|
|
return this->MetaData->GetPointArrayStatus(index);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
int vtkExodusReader::GetPointArrayStatus(const char* name)
|
|
{
|
|
return this->MetaData->GetPointArrayStatus(name);
|
|
}
|
|
|
|
// Cell array info accessors
|
|
int vtkExodusReader::GetNumberOfCellArrays()
|
|
{
|
|
return this->MetaData->GetNumberOfCellArrays();
|
|
}
|
|
|
|
const char* vtkExodusReader::GetCellArrayName(int arrayIdx)
|
|
{
|
|
return this->MetaData->GetCellArrayName(arrayIdx);
|
|
}
|
|
|
|
int vtkExodusReader::GetCellArrayNumberOfComponents(int arrayIdx)
|
|
{
|
|
return this->MetaData->GetCellArrayComponents(arrayIdx);
|
|
}
|
|
|
|
void vtkExodusReader::SetCellArrayStatus(int index, int flag)
|
|
{
|
|
int n = this->MetaData->GetOriginalNumberOfCellArrays();
|
|
|
|
if ((index >= 0) && (index < n))
|
|
{
|
|
this->MetaData->SetCellArrayStatus(index, flag);
|
|
this->Modified();
|
|
}
|
|
}
|
|
|
|
void vtkExodusReader::SetCellArrayStatus(const char* name, int flag)
|
|
{
|
|
this->MetaData->SetCellArrayStatus(name, flag);
|
|
this->Modified();
|
|
}
|
|
|
|
int vtkExodusReader::GetCellArrayStatus(int index)
|
|
{
|
|
int n = this->MetaData->GetOriginalNumberOfCellArrays();
|
|
|
|
if ((index >= 0) && (index < n))
|
|
{
|
|
return this->MetaData->GetCellArrayStatus(index);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
int vtkExodusReader::GetCellArrayStatus(const char* name)
|
|
{
|
|
return this->MetaData->GetCellArrayStatus(name);
|
|
}
|
|
|
|
// Block info accessors
|
|
int vtkExodusReader::GetNumberOfBlockArrays()
|
|
{
|
|
return this->MetaData->GetNumberOfBlocks();
|
|
}
|
|
|
|
const char* vtkExodusReader::GetBlockArrayName(int arrayIdx)
|
|
{
|
|
return this->MetaData->GetBlockName(arrayIdx);
|
|
}
|
|
|
|
void vtkExodusReader::SetBlockArrayStatus(int index, int flag)
|
|
{
|
|
// Only modify if we are 'out of sync'
|
|
//cout << "called SetBlockArrayStatus " << index << endl;
|
|
if (this->MetaData->GetBlockStatus(index) != flag)
|
|
{
|
|
this->MetaData->SetBlockStatus(index, flag);
|
|
|
|
// Because which blocks are on/off affects the
|
|
// geometry we need to remake the mesh cache
|
|
this->RemakeDataCacheFlag = 1;
|
|
this->Modified();
|
|
}
|
|
}
|
|
|
|
void vtkExodusReader::SetBlockArrayStatus(const char* name, int flag)
|
|
{
|
|
// Only modify if we are 'out of sync'
|
|
if (this->MetaData->GetBlockStatus(name) != flag)
|
|
{
|
|
this->MetaData->SetBlockStatus(name, flag);
|
|
|
|
// Because which blocks are on/off affects the
|
|
// geometry we need to remake the mesh cache
|
|
this->RemakeDataCacheFlag = 1;
|
|
this->Modified();
|
|
}
|
|
}
|
|
|
|
int vtkExodusReader::GetBlockArrayStatus(int index)
|
|
{
|
|
return this->MetaData->GetBlockStatus(index);
|
|
}
|
|
|
|
int vtkExodusReader::GetBlockArrayStatus(const char* name)
|
|
{
|
|
return this->MetaData->GetBlockStatus(name);
|
|
}
|
|
|
|
int vtkExodusReader::GetNumberOfElementsInBlock(int block_idx)
|
|
{
|
|
return this->MetaData->GetNumElementsInBlock(block_idx);
|
|
}
|
|
|
|
//----------------------------
|
|
// Node/Side set accessors
|
|
//----------------------------
|
|
void vtkExodusReader::SetNodeSetArrayStatus(int index, int flag)
|
|
{
|
|
// Only modify if we are 'out of sync'
|
|
if (this->MetaData->GetNodeSetStatus(index) != flag)
|
|
{
|
|
this->MetaData->SetNodeSetStatus(index, flag);
|
|
|
|
// Because which node sets are on/off affects the
|
|
// geometry we need to remake the mesh cache
|
|
this->RemakeDataCacheFlag = 1;
|
|
this->Modified();
|
|
}
|
|
}
|
|
void vtkExodusReader::SetNodeSetArrayStatus(const char* name, int flag)
|
|
{
|
|
// Only modify if we are 'out of sync'
|
|
if (this->MetaData->GetNodeSetStatus(name) != flag)
|
|
{
|
|
this->MetaData->SetNodeSetStatus(name, flag);
|
|
|
|
// Because which node sets are on/off affects the
|
|
// geometry we need to remake the mesh cache
|
|
this->RemakeDataCacheFlag = 1;
|
|
this->Modified();
|
|
}
|
|
}
|
|
int vtkExodusReader::GetNodeSetArrayStatus(int index )
|
|
{
|
|
return this->MetaData->GetNodeSetStatus( index );
|
|
}
|
|
int vtkExodusReader::GetNodeSetArrayStatus(const char* name )
|
|
{
|
|
return this->MetaData->GetNodeSetStatus( name );
|
|
}
|
|
const char* vtkExodusReader::GetNodeSetArrayName(int index)
|
|
{
|
|
return this->MetaData->GetNodeSetName(index);
|
|
}
|
|
|
|
void vtkExodusReader::SetSideSetArrayStatus(int index, int flag)
|
|
{
|
|
// Only modify if we are 'out of sync'
|
|
if (this->MetaData->GetSideSetStatus(index) != flag)
|
|
{
|
|
this->MetaData->SetSideSetStatus(index, flag);
|
|
|
|
// Because which side sets are on/off affects the
|
|
// geometry we need to remake the mesh cache
|
|
this->RemakeDataCacheFlag = 1;
|
|
this->Modified();
|
|
}
|
|
}
|
|
void vtkExodusReader::SetSideSetArrayStatus(const char* name, int flag)
|
|
{
|
|
// Only modify if we are 'out of sync'
|
|
if (this->MetaData->GetSideSetStatus(name) != flag)
|
|
{
|
|
this->MetaData->SetSideSetStatus(name, flag);
|
|
|
|
// Because which side sets are on/off affects the
|
|
// geometry we need to remake the mesh cache
|
|
this->RemakeDataCacheFlag = 1;
|
|
this->Modified();
|
|
}
|
|
}
|
|
int vtkExodusReader::GetSideSetArrayStatus(int index)
|
|
{
|
|
return this->MetaData->GetSideSetStatus( index );
|
|
}
|
|
int vtkExodusReader::GetSideSetArrayStatus(const char* name)
|
|
{
|
|
return this->MetaData->GetSideSetStatus( name );
|
|
}
|
|
const char* vtkExodusReader::GetSideSetArrayName(int index)
|
|
{
|
|
return this->MetaData->GetSideSetName(index);
|
|
}
|
|
|
|
//----------------------------
|
|
// End Node/Side set accessors
|
|
//----------------------------
|
|
|
|
// Part info accessors
|
|
int vtkExodusReader::GetNumberOfPartArrays()
|
|
{
|
|
return this->MetaData->GetNumberOfParts();
|
|
}
|
|
|
|
const char* vtkExodusReader::GetPartArrayName(int arrayIdx)
|
|
{
|
|
return this->MetaData->GetPartName(arrayIdx);
|
|
}
|
|
|
|
const char* vtkExodusReader::GetPartBlockInfo(int arrayIdx)
|
|
{
|
|
return this->MetaData->GetPartBlockInfo(arrayIdx);
|
|
}
|
|
|
|
void vtkExodusReader::SetPartArrayStatus(int index, int flag)
|
|
{
|
|
// Only modify if we are 'out of sync'
|
|
if (this->MetaData->GetPartStatus(index) != flag)
|
|
{
|
|
this->MetaData->SetPartStatus(index, flag);
|
|
|
|
// Because which parts are on/off affects the
|
|
// geometry we need to remake the mesh cache
|
|
this->RemakeDataCacheFlag = 1;
|
|
this->Modified();
|
|
}
|
|
}
|
|
|
|
void vtkExodusReader::SetPartArrayStatus(const char* name, int flag)
|
|
{
|
|
// Only modify if we are 'out of sync'
|
|
if (this->MetaData->GetPartStatus(name) != flag)
|
|
{
|
|
this->MetaData->SetPartStatus(name, flag);
|
|
|
|
// Because which parts are on/off affects the
|
|
// geometry we need to remake the mesh cache
|
|
this->RemakeDataCacheFlag = 1;
|
|
this->Modified();
|
|
}
|
|
}
|
|
|
|
int vtkExodusReader::GetPartArrayStatus(int index)
|
|
{
|
|
return this->MetaData->GetPartStatus(index);
|
|
}
|
|
|
|
int vtkExodusReader::GetPartArrayStatus(const char* name)
|
|
{
|
|
return this->MetaData->GetPartStatus(name);
|
|
}
|
|
|
|
// Material info accessors
|
|
int vtkExodusReader::GetNumberOfMaterialArrays()
|
|
{
|
|
//cout << "reader asked for nummat " << this->MetaData->GetNumberOfMaterials() << endl;
|
|
return this->MetaData->GetNumberOfMaterials();
|
|
}
|
|
|
|
const char* vtkExodusReader::GetMaterialArrayName(int arrayIdx)
|
|
{
|
|
return this->MetaData->GetMaterialName(arrayIdx);
|
|
}
|
|
|
|
void vtkExodusReader::SetMaterialArrayStatus(int index, int flag)
|
|
{
|
|
// Only modify if we are 'out of sync'
|
|
if (this->MetaData->GetMaterialStatus(index) != flag)
|
|
{
|
|
this->MetaData->SetMaterialStatus(index, flag);
|
|
|
|
// Because which materials are on/off affects the
|
|
// geometry we need to remake the mesh cache
|
|
this->RemakeDataCacheFlag = 1;
|
|
this->Modified();
|
|
}
|
|
}
|
|
|
|
void vtkExodusReader::SetMaterialArrayStatus(const char* name, int flag)
|
|
{
|
|
// Only modify if we are 'out of sync'
|
|
if (this->MetaData->GetMaterialStatus(name) != flag)
|
|
{
|
|
this->MetaData->SetMaterialStatus(name, flag);
|
|
|
|
// Because which materials are on/off affects the
|
|
// geometry we need to remake the mesh cache
|
|
this->RemakeDataCacheFlag = 1;
|
|
this->Modified();
|
|
}
|
|
}
|
|
|
|
int vtkExodusReader::GetMaterialArrayStatus(int index)
|
|
{
|
|
return this->MetaData->GetMaterialStatus(index);
|
|
}
|
|
|
|
int vtkExodusReader::GetMaterialArrayStatus(const char* name)
|
|
{
|
|
return this->MetaData->GetMaterialStatus(name);
|
|
}
|
|
//end of Material Accessors
|
|
|
|
// Assembly info accessors
|
|
int vtkExodusReader::GetNumberOfAssemblyArrays()
|
|
{
|
|
return this->MetaData->GetNumberOfAssemblies();
|
|
}
|
|
|
|
const char* vtkExodusReader::GetAssemblyArrayName(int arrayIdx)
|
|
{
|
|
return this->MetaData->GetAssemblyName(arrayIdx);
|
|
}
|
|
|
|
int vtkExodusReader::GetAssemblyArrayID( char const *name )
|
|
{
|
|
int numArrays = this->GetNumberOfAssemblyArrays();
|
|
for ( int i=0;i<numArrays;i++ )
|
|
{
|
|
if ( strcmp( name, this->GetAssemblyArrayName( i ) ) == 0 )
|
|
{
|
|
return i;
|
|
}
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
void vtkExodusReader::SetAssemblyArrayStatus(int index, int flag)
|
|
{
|
|
// Only modify if we are 'out of sync'
|
|
if (this->MetaData->GetAssemblyStatus(index) != flag)
|
|
{
|
|
this->MetaData->SetAssemblyStatus(index, flag);
|
|
|
|
// Because which materials are on/off affects the
|
|
// geometry we need to remake the mesh cache
|
|
this->RemakeDataCacheFlag = 1;
|
|
this->Modified();
|
|
}
|
|
}
|
|
|
|
void vtkExodusReader::SetAssemblyArrayStatus(const char* name, int flag)
|
|
{
|
|
// Only modify if we are 'out of sync'
|
|
if (this->MetaData->GetAssemblyStatus(name) != flag)
|
|
{
|
|
this->MetaData->SetAssemblyStatus(name, flag);
|
|
|
|
// Because which materials are on/off affects the
|
|
// geometry we need to remake the mesh cache
|
|
this->RemakeDataCacheFlag = 1;
|
|
this->Modified();
|
|
}
|
|
}
|
|
|
|
int vtkExodusReader::GetAssemblyArrayStatus(int index)
|
|
{
|
|
return this->MetaData->GetAssemblyStatus(index);
|
|
}
|
|
|
|
int vtkExodusReader::GetAssemblyArrayStatus(const char* name)
|
|
{
|
|
return this->MetaData->GetAssemblyStatus(name);
|
|
}
|
|
|
|
//end of Assembly Accessor
|
|
|
|
// Hierarchy Entry info accessors
|
|
int vtkExodusReader::GetNumberOfHierarchyArrays()
|
|
{
|
|
if (this->Parser)
|
|
{
|
|
return this->Parser->GetNumberOfHierarchyEntries();
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
const char* vtkExodusReader::GetHierarchyArrayName(int arrayIdx)
|
|
{
|
|
if (this->Parser)
|
|
{
|
|
//MEMORY LEAK - without copying the result, the list does not appear on SGI's
|
|
char* result=new char[512];
|
|
sprintf(result,"%s",this->Parser->GetHierarchyEntry(arrayIdx).c_str());
|
|
return result;
|
|
//return this->Parser->GetHierarchyEntry(arrayIdx).c_str();
|
|
}
|
|
return "Should not see this";
|
|
}
|
|
|
|
void vtkExodusReader::SetHierarchyArrayStatus(int index, int flag)
|
|
{
|
|
// Only modify if we are 'out of sync'
|
|
//if (this->GetHierarchyArrayStatus(index) != flag)
|
|
// {
|
|
if (this->Parser)
|
|
{
|
|
vtkstd::vector<int> blocks=this->Parser->GetBlocksForEntry(index);
|
|
for (vtkstd::vector<int>::size_type i=0;i<blocks.size();i++)
|
|
{
|
|
//cout << "turning block " << blocks[i] << " " << flag << endl;
|
|
this->MetaData->SetUnsortedBlockStatus
|
|
(this->MetaData->GetBlockIndex(blocks[i]),flag);
|
|
}
|
|
|
|
// Because which materials are on/off affects the
|
|
// geometry we need to remake the mesh cache
|
|
this->RemakeDataCacheFlag = 1;
|
|
this->Modified();
|
|
}
|
|
}
|
|
|
|
void vtkExodusReader::SetHierarchyArrayStatus(const char* name, int flag)
|
|
{
|
|
// Only modify if we are 'out of sync'
|
|
//if (this->GetHierarchyArrayStatus(name) != flag)
|
|
//{
|
|
if (this->Parser)
|
|
{
|
|
vtkstd::vector<int> blocks=this->Parser->GetBlocksForEntry
|
|
(vtkStdString(name));
|
|
for (vtkstd::vector<int>::size_type i=0;i<blocks.size();i++)
|
|
{
|
|
//cout << "turning block " << blocks[i] << " " << flag << endl;
|
|
this->MetaData->SetUnsortedBlockStatus
|
|
(this->MetaData->GetBlockIndex(blocks[i]),flag);
|
|
}
|
|
|
|
// Because which materials are on/off affects the
|
|
// geometry we need to remake the mesh cache
|
|
this->RemakeDataCacheFlag = 1;
|
|
this->Modified();
|
|
}
|
|
}
|
|
|
|
int vtkExodusReader::GetHierarchyArrayStatus(int index)
|
|
{
|
|
if (this->Parser)
|
|
{
|
|
vtkstd::vector<int> blocks=this->Parser->GetBlocksForEntry(index);
|
|
for (vtkstd::vector<int>::size_type i=0;i<blocks.size();i++)
|
|
{
|
|
if (this->MetaData->GetUnsortedBlockStatus
|
|
(this->MetaData->GetBlockIndex(blocks[i]))==0)
|
|
return 0;
|
|
}
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
int vtkExodusReader::GetHierarchyArrayStatus(const char* name)
|
|
{
|
|
if (this->Parser)
|
|
{
|
|
vtkstd::vector<int> blocks=this->Parser->GetBlocksForEntry(name);
|
|
for (vtkstd::vector<int>::size_type i=0;i<blocks.size();i++)
|
|
{
|
|
if (this->MetaData->GetUnsortedBlockStatus
|
|
(this->MetaData->GetBlockIndex(blocks[i]))==0)
|
|
return 0;
|
|
}
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
//end of Hierarchy Entry Accessors
|
|
|
|
int vtkExodusReader::GetBlockId(int block_idx)
|
|
{
|
|
return this->MetaData->GetBlockId(block_idx);
|
|
}
|
|
|
|
void vtkExodusReader::SetDisplayType(int type){
|
|
if (this->MetaData)
|
|
{
|
|
this->MetaData->SetDisplayType(type);
|
|
}
|
|
this->DisplayType=type;
|
|
}
|
|
|
|
// Helper function
|
|
int vtkExodusReaderFileExist(char *file_name)
|
|
{
|
|
struct stat fs;
|
|
if (file_name)
|
|
{
|
|
return (stat(file_name, &fs) != -1);
|
|
}
|
|
else
|
|
{
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
int vtkExodusReader::RequestInformation(
|
|
vtkInformation *vtkNotUsed(request),
|
|
vtkInformationVector **vtkNotUsed(inputVector),
|
|
vtkInformationVector *outputVector)
|
|
{
|
|
int error;
|
|
float fdum;
|
|
int num_node_vars, num_ele_vars;
|
|
int i;
|
|
int num_elem_in_block;
|
|
int num_nodes_per_elem;
|
|
int num_attr;
|
|
char *cdum = NULL;
|
|
char elem_type[MAX_STR_LENGTH+1];
|
|
|
|
// We can skip ExecuteInformation if all of these are true:
|
|
// The filename has not changed
|
|
// The XML filename has not changed
|
|
// The request for metadata has not changed
|
|
|
|
int newXMLFile = 1;
|
|
int newMetaData = 1;
|
|
|
|
int newFile =
|
|
(vtkExodusReader::StringsEqual(this->FileName, this->CurrentFileName) == 0);
|
|
|
|
if (!newFile)
|
|
{
|
|
newXMLFile =
|
|
(vtkExodusReader::StringsEqual(this->XMLFileName, this->CurrentXMLFileName) == 0);
|
|
|
|
newMetaData = ((this->ExodusModelMetadata && (this->ExodusModel == NULL)) ||
|
|
(!this->ExodusModelMetadata && this->ExodusModel));
|
|
}
|
|
|
|
if ( !newFile && !newXMLFile && !newMetaData)
|
|
{
|
|
return 1;
|
|
}
|
|
|
|
if (newXMLFile)
|
|
{
|
|
// Clean up any old xml parsers
|
|
if (this->Parser)
|
|
{
|
|
this->Parser->Delete();
|
|
this->Parser=NULL;
|
|
}
|
|
|
|
// If the xml file does not exist, try try again
|
|
if (!vtkExodusReaderFileExist(this->XMLFileName))
|
|
{
|
|
// Okay try to create an xml file using exodus file as basename
|
|
char tempName[512];
|
|
strcpy(tempName,this->FileName);
|
|
char* fpt=strrchr(tempName,'.');
|
|
if (fpt) strncpy(fpt,".xml\0",5);
|
|
// Does the xml file exist?
|
|
if (vtkExodusReaderFileExist(tempName))
|
|
{
|
|
SetXMLFileName(tempName);
|
|
}
|
|
else
|
|
{
|
|
//try .dart
|
|
fpt=strrchr(tempName,'.');
|
|
if (fpt) strncpy(fpt,".dart\0",6);
|
|
if (vtkExodusReaderFileExist(tempName))
|
|
{
|
|
SetXMLFileName(tempName);
|
|
}
|
|
else
|
|
{
|
|
SetXMLFileName(NULL);
|
|
}
|
|
}
|
|
}
|
|
|
|
// Okay if we have a valid file create a parser
|
|
if (this->XMLFileName)
|
|
{
|
|
//cout << "parsing: " << this->XMLFileName << endl;
|
|
this->Parser=new vtkExodusXMLParser(this->XMLFileName);
|
|
}
|
|
|
|
// The filename is different so we need to open the file
|
|
// and remake the data cache and get all the metadata
|
|
this->RemakeDataCacheFlag = 1;
|
|
newFile = 1;
|
|
this->SetCurrentXMLFileName(this->XMLFileName);
|
|
}
|
|
|
|
if ( this->OpenCurrentFile() != 1 )
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
if (newMetaData)
|
|
{
|
|
if (this->ExodusModelMetadata)
|
|
{
|
|
// Write the global metadata now. This is all the information
|
|
// which does not depend on which cells, timestep, or field data
|
|
// we are going to read in.
|
|
|
|
this->NewExodusModel();
|
|
|
|
this->ExodusModel->SetGlobalInformation( this->CurrentHandle,
|
|
this->ExodusCPUWordSize );
|
|
}
|
|
else
|
|
{
|
|
if (this->ExodusModel)
|
|
{
|
|
this->ExodusModel->Delete();
|
|
this->ExodusModel = NULL;
|
|
}
|
|
}
|
|
}
|
|
|
|
// **KEN** Why not have vtkExodusMetadata do all of this instead.
|
|
// Encapsulate the functionality of reading it along with the data.
|
|
// That's the whole idea behind object oriented programming, right?
|
|
|
|
if (newFile)
|
|
{
|
|
this->SetGlobalElementIdCache(NULL);
|
|
|
|
// Get metadata
|
|
error = ex_get_init(this->CurrentHandle, this->Title, &this->Dimensionality,
|
|
&this->NumberOfNodesInFile, &this->NumberOfElementsInFile,
|
|
&this->NumberOfBlocks, &this->NumberOfNodeSets, &this->NumberOfSideSets);
|
|
if (error < 0)
|
|
{
|
|
vtkErrorMacro("Error: " << error << " calling ex_get_init " << this->FileName);
|
|
this->CloseCurrentFile();
|
|
return 0;
|
|
}
|
|
|
|
// Read the number of time steps available.
|
|
error = ex_inquire(this->CurrentHandle,
|
|
EX_INQ_TIME, &this->NumberOfTimeSteps, &fdum,cdum);
|
|
if (error < 0)
|
|
{
|
|
vtkErrorMacro("Error: " << error << " calling ex_inquire " << this->FileName);
|
|
this->CloseCurrentFile();
|
|
return 0;
|
|
}
|
|
|
|
this->TimeStepRange[0] = 0;
|
|
this->TimeStepRange[1] = this->NumberOfTimeSteps-1;
|
|
|
|
this->GetAllTimes(outputVector);
|
|
|
|
// Read element block paramemters.
|
|
this->MetaData->ResetBlocks();
|
|
int *ids = new int[this->NumberOfBlocks];
|
|
char block_name_buffer[80];
|
|
ex_get_elem_blk_ids (this->CurrentHandle, ids);
|
|
|
|
for (i = 0; i < this->NumberOfBlocks; ++i)
|
|
{
|
|
error = ex_get_elem_block (this->CurrentHandle, ids[i], elem_type,
|
|
&(num_elem_in_block),
|
|
&(num_nodes_per_elem), &(num_attr));
|
|
if (error < 0)
|
|
{
|
|
vtkErrorMacro(
|
|
"Error: " << error << " calling ex_get_elem_blk_ids " << this->FileName);
|
|
this->CloseCurrentFile();
|
|
delete [] ids;
|
|
return 0;
|
|
}
|
|
|
|
// Check for empty block
|
|
if (!strcmp(elem_type,"NULL"))
|
|
{
|
|
strcpy(elem_type,"empty");
|
|
}
|
|
|
|
sprintf(block_name_buffer,"Block: %d (%s)",ids[i],elem_type);
|
|
if (this->Parser && this->Parser->GetPartDescription(ids[i])!="")
|
|
{
|
|
//construct assembly names from number and description arrays
|
|
vtkstd::vector<vtkStdString> assemblyNumbers=
|
|
this->Parser->GetAssemblyNumbers(ids[i]);
|
|
vtkstd::vector<vtkStdString> assemblyDescriptions=
|
|
this->Parser->GetAssemblyDescriptions(ids[i]);
|
|
|
|
vtkstd::vector<vtkStdString> assemblyNames;
|
|
for (vtkstd::vector<int>::size_type j=0;j<assemblyNumbers.size();j++)
|
|
{
|
|
assemblyNames.push_back(assemblyDescriptions[j]+vtkStdString(" (")+
|
|
assemblyNumbers[j]+vtkStdString(")"));
|
|
}
|
|
sprintf(block_name_buffer,"Block: %d (%s) %s",ids[i],
|
|
this->Parser->GetPartDescription(ids[i]).c_str(),
|
|
this->Parser->GetPartNumber(ids[i]).c_str());
|
|
this->MetaData->AddBlock(block_name_buffer,
|
|
this->Parser->GetPartDescription(ids[i])+" ("+
|
|
this->Parser->GetMaterialDescription(ids[i])+")"+" : "+
|
|
this->Parser->GetPartNumber(ids[i]),
|
|
this->Parser->GetMaterialDescription(ids[i])+" : "+
|
|
this->Parser->GetMaterialSpecification(ids[i]),
|
|
assemblyNames,
|
|
ids[i], num_elem_in_block, 1);
|
|
}
|
|
else
|
|
{
|
|
vtkstd::vector<vtkStdString> assemblyNames;
|
|
assemblyNames.push_back(vtkStdString("Default Assembly"));
|
|
this->MetaData->AddBlock(block_name_buffer,"Default Part",
|
|
"Default Material", assemblyNames,ids[i],
|
|
num_elem_in_block, 1);
|
|
}
|
|
|
|
}
|
|
delete [] ids;
|
|
|
|
// Read the number of node arrays
|
|
error = ex_get_var_param(this->CurrentHandle, "n", &(num_node_vars));
|
|
if (error < 0)
|
|
{
|
|
vtkErrorMacro(
|
|
"Error: " << error << " calling ex_get_var_param " << this->FileName);
|
|
this->CloseCurrentFile();
|
|
return 0;
|
|
}
|
|
|
|
// Get node array information
|
|
if (num_node_vars > 0)
|
|
{
|
|
error = ex_get_var_names(this->CurrentHandle, "n", num_node_vars,
|
|
MetaData->AllocatePointArrayNameBuffer(num_node_vars));
|
|
if (error < 0)
|
|
{
|
|
vtkErrorMacro(
|
|
"Error: " << error << " reading point array names " << this->FileName);
|
|
this->CloseCurrentFile();
|
|
return 0;
|
|
}
|
|
|
|
this->RemoveBeginningAndTrailingSpaces(
|
|
MetaData->GetPointArrayNameBuffer(),num_node_vars);
|
|
}
|
|
|
|
// Read the number of cell arrays
|
|
error = ex_get_var_param(this->CurrentHandle, "e", &(num_ele_vars));
|
|
if (error < 0)
|
|
{
|
|
vtkErrorMacro(
|
|
"Error: " << error << " calling ex_get_var_param " << this->FileName);
|
|
this->CloseCurrentFile();
|
|
return 0;
|
|
}
|
|
|
|
// Get cell array information
|
|
if (num_ele_vars > 0)
|
|
{
|
|
// Not all cell variables exist over all element blocks. A "truth table"
|
|
// will say whether a variable is defined for a certain block.
|
|
|
|
this->CellVarTruthTable->Resize(num_ele_vars*this->NumberOfBlocks);
|
|
int *ptr = CellVarTruthTable->GetPointer(0);
|
|
ex_get_elem_var_tab(this->CurrentHandle, this->NumberOfBlocks,
|
|
num_ele_vars, ptr);
|
|
error = ex_get_var_names (this->CurrentHandle, "e", num_ele_vars,
|
|
MetaData->AllocateCellArrayNameBuffer(num_ele_vars));
|
|
if (error < 0)
|
|
{
|
|
vtkErrorMacro("Error: " << error << " calling ex_get_var_names " << this->FileName);
|
|
this->CloseCurrentFile();
|
|
return 0;
|
|
}
|
|
|
|
this->RemoveBeginningAndTrailingSpaces(
|
|
MetaData->GetCellArrayNameBuffer(),num_ele_vars);
|
|
}
|
|
|
|
// Read Node Set and Side Set metadata
|
|
this->ReadNodeSetMetadata();
|
|
this->ReadSideSetMetadata();
|
|
}
|
|
|
|
// Close the exodus file
|
|
this->CloseCurrentFile();
|
|
|
|
if (newFile)
|
|
{
|
|
// Call finalize on the array metadata. This is important
|
|
// otherwise does not work at all
|
|
|
|
MetaData->Finalize();
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
|
|
//------------------------------------------------------------------------
|
|
// Read Node Set and Side Set MetaData for future use
|
|
// Set ids
|
|
// Set size
|
|
// number of distribution factors in each set
|
|
//------------------------------------------------------------------------
|
|
void vtkExodusReader::ReadNodeSetMetadata()
|
|
{
|
|
// Stop if there are no Node Sets
|
|
if ( this->NumberOfNodeSets <= 0 )
|
|
{
|
|
return;
|
|
}
|
|
// allocate memory for node set ids
|
|
vtkstd::vector<int> nodeSetId( this->NumberOfNodeSets, -1 );
|
|
int size = 0;
|
|
int dist = 0;
|
|
// read node set ids
|
|
int error = ex_get_node_set_ids( this->CurrentHandle, &nodeSetId[0] );
|
|
if (error < 0)
|
|
{
|
|
vtkErrorMacro("Error: " << error << " calling ex_get_node_set_ids " << this->FileName);
|
|
}
|
|
// read meta data for each node set
|
|
int i = 0;
|
|
for( i = 0; i < this->NumberOfNodeSets; i++ )
|
|
{
|
|
error = ex_get_node_set_param( this->CurrentHandle, nodeSetId[i], &size, &dist );
|
|
if (error < 0)
|
|
{
|
|
vtkErrorMacro("Error: " << error << " calling ex_get_node_set_param " << this->FileName);
|
|
}
|
|
// Add a node set's metadata to vtkExodusMetaData
|
|
// Store it's Exodus Id, size, and number of distribution factors
|
|
this->MetaData->AddNodeSet( nodeSetId[i], size, dist );
|
|
}
|
|
}
|
|
void vtkExodusReader::ReadSideSetMetadata()
|
|
{
|
|
// Stop if there are no Side Sets
|
|
if ( this->NumberOfSideSets <= 0 )
|
|
{
|
|
return;
|
|
}
|
|
// allocate memory for side set ids
|
|
vtkstd::vector<int> sideSetId( this->NumberOfSideSets, -1 );
|
|
int size = 0;
|
|
int dist = 0;
|
|
// read side set ids
|
|
int error = ex_get_side_set_ids( this->CurrentHandle, &sideSetId[0] );
|
|
if (error < 0)
|
|
{
|
|
vtkErrorMacro(<< "Error: " << error
|
|
<< " calling ex_get_side_set_ids " << this->FileName);
|
|
}
|
|
// read meta data for each side set
|
|
int i = 0;
|
|
for( i = 0; i < this->NumberOfSideSets; i++ )
|
|
{
|
|
error = ex_get_side_set_param( this->CurrentHandle, sideSetId[i], &size, &dist );
|
|
if (error < 0)
|
|
{
|
|
vtkErrorMacro(<< "Error: " << error
|
|
<< " calling ex_get_side_set_param " << this->FileName);
|
|
}
|
|
// Add a side set's metadate to vtkExodusMetaData
|
|
// Store it's Exodus Id, size, and number of distribution factors
|
|
this->MetaData->AddSideSet( sideSetId[i], size, dist );
|
|
}
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
int vtkExodusReader::RequestData(
|
|
vtkInformation *vtkNotUsed(request),
|
|
vtkInformationVector **vtkNotUsed(inputVector),
|
|
vtkInformationVector *outputVector)
|
|
{
|
|
if ( this->OpenCurrentFile() != 1 )
|
|
{
|
|
vtkWarningMacro(<< "Can't open file");
|
|
return 0;
|
|
}
|
|
|
|
this->ActualTimeStep = this->TimeStep;
|
|
|
|
vtkInformation* outInfo = outputVector->GetInformationObject(0);
|
|
// get the ouptut
|
|
vtkUnstructuredGrid *output = vtkUnstructuredGrid::SafeDownCast(
|
|
outInfo->Get(vtkDataObject::DATA_OBJECT()));
|
|
|
|
// Check if a particular time was requested.
|
|
if(outInfo->Has(vtkStreamingDemandDrivenPipeline::UPDATE_TIME_INDEX()))
|
|
{
|
|
// Get the requested time step.
|
|
this->ActualTimeStep =
|
|
outInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_TIME_INDEX());
|
|
|
|
// Save the time value in the output data information.
|
|
int length =
|
|
outInfo->Length(vtkStreamingDemandDrivenPipeline::TIME_STEPS());
|
|
if(this->ActualTimeStep >= 0 && this->ActualTimeStep < length)
|
|
{
|
|
double* steps =
|
|
outInfo->Get(vtkStreamingDemandDrivenPipeline::TIME_STEPS());
|
|
output->GetInformation()->Set(vtkDataObject::DATA_TIME(),
|
|
steps[this->ActualTimeStep]);
|
|
}
|
|
else
|
|
{
|
|
vtkErrorMacro("Time index " << this->ActualTimeStep
|
|
<< " requested but there are "
|
|
<< length << " time steps.");
|
|
}
|
|
output->GetInformation()->Set(vtkDataObject::DATA_TIME_INDEX(),
|
|
this->ActualTimeStep);
|
|
}
|
|
// Force TimeStep into the "known good" range. Although this
|
|
// could be accomplished inside SetTimeStep(),
|
|
// - we'd rather not override a VTK macro-defined method
|
|
// because the macro might change
|
|
// - it might be good to allow out-of-range values in
|
|
// places
|
|
// CHANGE: It is generally not good practice to change ivar
|
|
// publicly accessible (through Set) in Execute(). This can
|
|
// easily make the user interface (for example server manager)
|
|
// in a state inconsistent with the reader. Therefore, clamp a
|
|
// protected variable and use that instead.
|
|
if ( this->ActualTimeStep < this->TimeStepRange[0] )
|
|
{
|
|
this->ActualTimeStep = this->TimeStepRange[0];
|
|
}
|
|
else if ( this->ActualTimeStep > this->TimeStepRange[1] )
|
|
{
|
|
this->ActualTimeStep = this->TimeStepRange[1];
|
|
}
|
|
|
|
// Okay because they may have changed which blocks are on/off
|
|
// we need to recompute the actual number of elements
|
|
int actualElements=0;
|
|
for (int i=0; i < this->MetaData->GetNumberOfBlocks(); ++i)
|
|
{
|
|
// Do we read this block?
|
|
if (this->MetaData->GetBlockStatus(i)==1)
|
|
actualElements += this->MetaData->GetNumElementsInBlock(i);
|
|
}
|
|
#if DEBUG
|
|
vtkWarningMacro(<< "NumElements: " << NumberOfElements
|
|
<< " actualElements: " << actualElements);
|
|
#endif
|
|
this->NumberOfUsedElements = actualElements;
|
|
|
|
|
|
// In general the geometry of an exodus file remains the same
|
|
// So often you can just read in new field array
|
|
// The 'RemakeDataCacheFlag' is set if you need to read
|
|
// in the geometry again for some reason (eg new file or a
|
|
// change which blocks get read in etc)
|
|
if ( RemakeDataCacheFlag )
|
|
{
|
|
this->ReadGeometry(this->CurrentHandle, output);
|
|
|
|
this->NewGeometryCount++;
|
|
|
|
// **KEN** Would it make sense to relase the DataCache data BEFORE
|
|
// reading the new geometry? That might reduce the amount of memory
|
|
// needed at one time.
|
|
|
|
// Make a shallowcopy to the my DataCache
|
|
this->DataCache->ReleaseData(); // FIXME Do I need this?
|
|
this->DataCache->ShallowCopy(output);
|
|
|
|
// Okay I don't need to do this again until someone
|
|
// says 'Hey you need to remake this mesh data!'
|
|
this->RemakeDataCacheFlag = 0;
|
|
|
|
#if DEBUG
|
|
vtkWarningMacro("Remade data cache");
|
|
#endif
|
|
}
|
|
else
|
|
{
|
|
// Just copy (shallow) the points and cells from the DataCache.
|
|
// The points and cell information is always the same for exodus
|
|
// Also copy the generated arrays which also stay the same
|
|
output->ShallowCopy(this->DataCache);
|
|
}
|
|
|
|
// Read in the arrays.
|
|
// If we are in the execution method then either the file, the time
|
|
// step or array selections changed. In all cases we have to reload arrays.
|
|
this->ReadArrays(this->CurrentHandle, output);
|
|
|
|
//begin USE_EXO_DSP_FILTERS
|
|
this->GetDSPOutputArrays(this->CurrentHandle, output);
|
|
//end USE_EXO_DSP_FILTERS
|
|
|
|
// If the user wants the apply displacements then add here
|
|
// TODO: This is recalled everytime a user changes arrays
|
|
// look into avoiding this if possible
|
|
if (ApplyDisplacements)
|
|
{
|
|
AddDisplacements(output);
|
|
}
|
|
|
|
// Generated arrays include block id, global node id, global element id
|
|
this->GenerateExtraArrays(output);
|
|
|
|
// This just makes sure the arrays are the same size as the number
|
|
// of nodes or cell
|
|
output->CheckAttributes();
|
|
|
|
// We may have some mem that can be condensed
|
|
output->Squeeze();
|
|
|
|
if (this->ExodusModel)
|
|
{
|
|
int rc = this->ExodusModel->SetLocalInformation(
|
|
output,
|
|
this->CurrentHandle, this->ActualTimeStep,
|
|
this->NewGeometryCount, this->ExodusIOWordSize);
|
|
|
|
if (rc)
|
|
{
|
|
vtkErrorMacro(<< "Can't create the local model information");
|
|
}
|
|
|
|
if (this->PackExodusModelOntoOutput)
|
|
{
|
|
// The metadata will be written to field arrays and added
|
|
// to the output.
|
|
|
|
this->ExodusModel->GetModelMetadata()->Pack(output);
|
|
}
|
|
}
|
|
|
|
// Close the exodus file
|
|
this->CloseCurrentFile();
|
|
|
|
return 1;
|
|
}
|
|
|
|
|
|
//----------------------------------------------------------------------------
|
|
void vtkExodusReader::ReadGeometry(int handle, vtkUnstructuredGrid* output)
|
|
{
|
|
// Reset the entire unstructured grid
|
|
output->Reset();
|
|
|
|
// Read in cell topology
|
|
this->ReadCells(handle, output);
|
|
|
|
// Read in node and side sets
|
|
this->ReadNodeAndSideSets(handle, output);
|
|
|
|
// Now read in the points
|
|
// Note: This should come after reading in
|
|
// the cells and node/side set so that
|
|
// we know which points should actually be
|
|
// stored and put in the output
|
|
this->ReadPoints(handle, output);
|
|
|
|
}
|
|
|
|
// Read in node and side set data
|
|
void vtkExodusReader::ReadNodeAndSideSets(int handle, vtkUnstructuredGrid* output)
|
|
{
|
|
int i, j, k;
|
|
int *indexPtr;
|
|
vtkIdList *cellIds=vtkIdList::New();
|
|
vtkIntArray *counts=vtkIntArray::New();
|
|
vtkIntArray *nodeIndexes=vtkIntArray::New();
|
|
int cellType;
|
|
int cellNumPoints;
|
|
|
|
|
|
// Read in all the node sets that are 'on'
|
|
for (i=0; i < this->GetNumberOfNodeSets(); ++i)
|
|
{
|
|
// Do we read this node set?
|
|
if (this->MetaData->GetNodeSetStatus(i))
|
|
{
|
|
|
|
// Allocate storage for node indexes
|
|
nodeIndexes->Reset();
|
|
nodeIndexes->SetNumberOfValues(this->MetaData->GetNodeSetSize(i));
|
|
|
|
// Get the node indexes
|
|
ex_get_node_set(handle, this->MetaData->GetNodeSetId(i), nodeIndexes->GetPointer(0));
|
|
|
|
|
|
// Okay now loop though the nodes indexes and insert into the output
|
|
for(j=0; j < this->MetaData->GetNodeSetSize(i); ++j)
|
|
{
|
|
cellIds->Reset();
|
|
cellIds->InsertNextId(GetPointMapIndex(nodeIndexes->GetValue(j)-1));
|
|
output->InsertNextCell(VTK_VERTEX, cellIds);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
// Read in all the side sets that are 'on'
|
|
for (i=0; i < this->GetNumberOfSideSets(); ++i)
|
|
{
|
|
// Do we read this side set?
|
|
if (this->MetaData->GetSideSetStatus(i))
|
|
{
|
|
|
|
// Allocate storage for 'counts' (element size) array and node indexes (connectivity)
|
|
// Assumption: Side set elements will not be more than 4 nodes :)
|
|
counts->Reset();
|
|
counts->SetNumberOfValues(this->MetaData->GetSideSetSize(i));
|
|
nodeIndexes->Reset();
|
|
nodeIndexes->SetNumberOfValues(this->MetaData->GetSideSetSize(i)*4);
|
|
|
|
// Get the counts (element size) array and the node indexes
|
|
ex_get_side_set_node_list(handle, this->MetaData->GetSideSetId(i), counts->GetPointer(0), nodeIndexes->GetPointer(0));
|
|
|
|
indexPtr = nodeIndexes->GetPointer(0);
|
|
|
|
// Okay now loop though for each element and set up the cells
|
|
for(j=0; j < this->MetaData->GetSideSetSize(i); ++j)
|
|
{
|
|
|
|
// What kind of cell do we have
|
|
cellNumPoints = counts->GetValue(j);
|
|
switch (cellNumPoints)
|
|
{
|
|
case 1:
|
|
cellType=VTK_VERTEX;
|
|
break;
|
|
case 2:
|
|
cellType=VTK_LINE;
|
|
break;
|
|
case 3:
|
|
cellType=VTK_TRIANGLE;
|
|
break;
|
|
case 4:
|
|
cellType=VTK_QUAD;
|
|
break;
|
|
default:
|
|
vtkErrorMacro("Unknown side side element with: " << counts->GetValue(j) << " nodes");
|
|
return;
|
|
}
|
|
|
|
// Now set up connectivity for cell
|
|
cellIds->Reset();
|
|
for (k=0; k<cellNumPoints; ++k)
|
|
{
|
|
cellIds->InsertNextId(GetPointMapIndex(indexPtr[k]-1));
|
|
}
|
|
indexPtr+=cellNumPoints;
|
|
|
|
// Now insert the cell
|
|
output->InsertNextCell(cellType, cellIds);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
// Delete any allocated stuff
|
|
cellIds->Delete();
|
|
counts->Delete();
|
|
nodeIndexes->Delete();
|
|
|
|
|
|
}
|
|
|
|
// Read in connectivity information
|
|
void vtkExodusReader::ReadCells(int handle, vtkUnstructuredGrid* output)
|
|
{
|
|
int i, j, k;
|
|
int num_elem_in_block;
|
|
int num_nodes_per_elem;
|
|
int num_attr;
|
|
char sm_elem_type[MAX_STR_LENGTH+1];
|
|
int *connect, *pConnect;
|
|
vtkIdList *cellIds=vtkIdList::New();
|
|
int cellType;
|
|
int cellNumPoints;
|
|
|
|
// Allocate memory in the output
|
|
output->Allocate(this->NumberOfUsedElements);
|
|
|
|
// **KEN** The point maps can be really big. Therefore, they should be
|
|
// deleted as soon as possible.
|
|
|
|
// Set up point map
|
|
this->SetUpPointMap(this->NumberOfNodesInFile);
|
|
|
|
// Initialize using the type of cells.
|
|
// A block contains only one type of cell.
|
|
for (i=0; i < this->MetaData->GetNumberOfBlocks(); ++i)
|
|
{
|
|
// Do we read this block?
|
|
if (this->MetaData->GetBlockStatus(i)==0)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
// Read in the metadata about this block
|
|
ex_get_elem_block(handle, this->MetaData->GetBlockId(i), sm_elem_type,
|
|
&num_elem_in_block, &num_nodes_per_elem, &num_attr);
|
|
|
|
// If for some weird reason the block has no elements go to next block
|
|
if (num_elem_in_block == 0)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
// Okay allocate memory for connectivity data
|
|
connect = new int [num_nodes_per_elem*num_elem_in_block];
|
|
ex_get_elem_conn (handle, this->MetaData->GetBlockId(i), connect);
|
|
|
|
// Grab the element type
|
|
char *elem_type = new char[MAX_STR_LENGTH];
|
|
this->StringUppercase(sm_elem_type, elem_type);
|
|
|
|
// Check for quadratic elements
|
|
if (!strncmp(elem_type,"TRI",3) && (num_nodes_per_elem==6))
|
|
{cellType=VTK_QUADRATIC_TRIANGLE; cellNumPoints=6;}
|
|
else if (!strncmp(elem_type,"SHE",3) && (num_nodes_per_elem==8))
|
|
{cellType=VTK_QUADRATIC_QUAD; cellNumPoints=8;}
|
|
else if (!strncmp(elem_type,"SHE",3) && (num_nodes_per_elem==9))
|
|
{cellType=VTK_QUADRATIC_QUAD; cellNumPoints=8;}
|
|
else if (!strncmp(elem_type,"TET",3) && (num_nodes_per_elem==10))
|
|
{cellType=VTK_QUADRATIC_TETRA; cellNumPoints=10;}
|
|
else if (!strncmp(elem_type,"TET",3) && (num_nodes_per_elem==11))
|
|
{cellType=VTK_QUADRATIC_TETRA; cellNumPoints=10;}
|
|
else if (!strncmp(elem_type,"HEX",3) && (num_nodes_per_elem==20))
|
|
{cellType=VTK_QUADRATIC_HEXAHEDRON; cellNumPoints=20;}
|
|
else if (!strncmp(elem_type,"HEX",3) && (num_nodes_per_elem==21))
|
|
{cellType=VTK_QUADRATIC_HEXAHEDRON; cellNumPoints=20;}
|
|
else if (!strncmp(elem_type,"HEX",3) && (num_nodes_per_elem==27))
|
|
{cellType=VTK_QUADRATIC_HEXAHEDRON; cellNumPoints=20;}
|
|
else if (!strncmp(elem_type,"QUA",3) && (num_nodes_per_elem==8))
|
|
{cellType=VTK_QUADRATIC_QUAD; cellNumPoints=8;}
|
|
else if (!strncmp(elem_type,"QUA",3) && (num_nodes_per_elem==9))
|
|
{cellType=VTK_QUADRATIC_QUAD; cellNumPoints=8;}
|
|
else if (!strncmp(elem_type,"TRU",3) && (num_nodes_per_elem==3))
|
|
{cellType=VTK_QUADRATIC_EDGE; cellNumPoints=3;}
|
|
else if (!strncmp(elem_type,"BEA",3) && (num_nodes_per_elem==3))
|
|
{cellType=VTK_QUADRATIC_EDGE; cellNumPoints=3;}
|
|
else if (!strncmp(elem_type,"BAR",3) && (num_nodes_per_elem==3))
|
|
{cellType=VTK_QUADRATIC_EDGE; cellNumPoints=3;}
|
|
else if (!strncmp(elem_type,"EDG",3) && (num_nodes_per_elem==3))
|
|
{cellType=VTK_QUADRATIC_EDGE; cellNumPoints=3;}
|
|
|
|
// Check for regular elements
|
|
else if (!strncmp(elem_type,"CIR",3)) {cellType=VTK_VERTEX; cellNumPoints=1;}
|
|
else if (!strncmp(elem_type,"SPH",3)) {cellType=VTK_VERTEX; cellNumPoints=1;}
|
|
else if (!strncmp(elem_type,"BAR",3)) {cellType=VTK_LINE; cellNumPoints=2;}
|
|
else if (!strncmp(elem_type,"TRU",3)) {cellType=VTK_LINE; cellNumPoints=2;}
|
|
else if (!strncmp(elem_type,"BEA",3)) {cellType=VTK_LINE; cellNumPoints=2;}
|
|
else if (!strncmp(elem_type,"EDG",3)) {cellType=VTK_LINE; cellNumPoints=2;}
|
|
else if (!strncmp(elem_type,"TRI",3)) {cellType=VTK_TRIANGLE; cellNumPoints=3;}
|
|
else if (!strncmp(elem_type,"QUA",3)) {cellType=VTK_QUAD; cellNumPoints=4;}
|
|
else if (!strncmp(elem_type,"TET",3)) {cellType=VTK_TETRA; cellNumPoints=4;}
|
|
else if (!strncmp(elem_type,"PYR",3)) {cellType=VTK_PYRAMID; cellNumPoints=5;}
|
|
else if (!strncmp(elem_type,"WED",3)) {cellType=VTK_WEDGE; cellNumPoints=6;}
|
|
else if (!strncmp(elem_type,"HEX",3)) {cellType=VTK_HEXAHEDRON; cellNumPoints=8;}
|
|
else if (!strncmp(elem_type,"SHE",3) && (num_nodes_per_elem==3)) {cellType=VTK_TRIANGLE; cellNumPoints=3;}
|
|
else if (!strncmp(elem_type,"SHE",3) && (num_nodes_per_elem==4)) {cellType=VTK_QUAD; cellNumPoints=4;}
|
|
else
|
|
{
|
|
vtkErrorMacro("Unsupported element type: " << elem_type);
|
|
delete [] connect;
|
|
continue;
|
|
}
|
|
delete []elem_type;
|
|
|
|
//cell types not currently handled
|
|
//quadratic wedge - 15,16 nodes
|
|
//quadratic pyramid - 13 nodes
|
|
|
|
// Now save the cells in a cell array.
|
|
pConnect = connect;
|
|
for (j = 0; j < num_elem_in_block; ++j)
|
|
{
|
|
cellIds->Reset();
|
|
|
|
// Build up a list of cell pt ids to insert in to the output data set.
|
|
// Note: The '-1' is because Exodus stores ids starting from 1 not 0.
|
|
|
|
// Special setup for quadratic hex because exodus node numbering
|
|
// for this cell type is different than vtk node numbering
|
|
if (cellType==VTK_QUADRATIC_HEXAHEDRON)
|
|
{
|
|
for (k=0; k<12; ++k)
|
|
cellIds->InsertNextId(GetPointMapIndex(pConnect[k]-1));
|
|
for (k=12; k<16; ++k)
|
|
cellIds->InsertNextId(GetPointMapIndex(pConnect[k+4]-1));
|
|
for (k=16; k<20; ++k)
|
|
cellIds->InsertNextId(GetPointMapIndex(pConnect[k-4]-1));
|
|
}
|
|
|
|
// All the rest of the cells have the same node numbering
|
|
else
|
|
{
|
|
for (k=0; k<cellNumPoints; ++k)
|
|
cellIds->InsertNextId(GetPointMapIndex(pConnect[k]-1));
|
|
}
|
|
|
|
// Skip to next element.
|
|
pConnect += num_nodes_per_elem;
|
|
|
|
// Insert cell into output.
|
|
output->InsertNextCell(cellType, cellIds);
|
|
}
|
|
|
|
delete [] connect;
|
|
connect = NULL;
|
|
}
|
|
|
|
cellIds->Delete();
|
|
cellIds = NULL;
|
|
}
|
|
|
|
|
|
|
|
void vtkExodusReader::ReadPoints(int handle, vtkUnstructuredGrid* output)
|
|
{
|
|
vtkPoints *newPoints;
|
|
int pointId, point_index;
|
|
|
|
// Sanity Check
|
|
if (this->NumberOfUsedNodes == 0)
|
|
{
|
|
#if DEBUG
|
|
vtkWarningMacro("The number of used nodes is zero\n");
|
|
#endif
|
|
return;
|
|
}
|
|
|
|
// Allocate point arrays
|
|
float *x = new float[this->NumberOfNodesInFile];
|
|
float *y = new float[this->NumberOfNodesInFile];
|
|
float *z = new float[this->NumberOfNodesInFile];
|
|
|
|
// Clear z values in case you don't really use them
|
|
memset(z,0,this->NumberOfNodesInFile*sizeof(float));
|
|
|
|
|
|
// Get node coordinates
|
|
ex_get_coord(handle, x, y, z);
|
|
|
|
// Create new points
|
|
newPoints = vtkPoints::New();
|
|
newPoints->SetNumberOfPoints(this->NumberOfUsedNodes);
|
|
|
|
// Set up points
|
|
for (pointId=0; pointId<this->NumberOfUsedNodes; ++pointId)
|
|
{
|
|
point_index = this->ReversePointMap->GetValue(pointId);
|
|
newPoints->InsertPoint(pointId, x[point_index], y[point_index], z[point_index]);
|
|
}
|
|
output->SetPoints(newPoints);
|
|
delete [] x;
|
|
delete [] y;
|
|
delete [] z;
|
|
newPoints->Delete();
|
|
newPoints = NULL;
|
|
|
|
// **KEN** I think this would be a good place to clear out the point
|
|
// map and squeeze the reverse map.
|
|
}
|
|
|
|
|
|
//----------------------------------------------------------------------------
|
|
void vtkExodusReader::ReadArrays(int handle, vtkUnstructuredGrid* output)
|
|
{
|
|
vtkDataArray *array;
|
|
int dim, arrayIdx, idx;
|
|
int haveArray, getArray;
|
|
char arrayName[MAX_STR_LENGTH];
|
|
char arrayNameUpper[MAX_STR_LENGTH];
|
|
|
|
// Read point arrays.
|
|
// The first vector array encounters is set to vectors,
|
|
// and the first array encountered is set to scalars.
|
|
arrayIdx = 0;
|
|
for (idx = 0; idx < this->GetNumberOfPointArrays(); ++idx)
|
|
{
|
|
// Get the name of the array
|
|
strcpy(arrayName,this->GetPointArrayName(idx));
|
|
|
|
// Do I already have this array?
|
|
if (output->GetPointData()->GetArray(arrayName) != NULL)
|
|
{
|
|
haveArray=1;
|
|
}
|
|
else
|
|
{
|
|
haveArray=0;
|
|
}
|
|
|
|
// Does user want displacements
|
|
this->StringUppercase(arrayName,arrayNameUpper);
|
|
if ((this->ApplyDisplacements || /* user wants displacement field */
|
|
this->ExodusModelMetadata) /* user may plan to write out file */
|
|
&&
|
|
!strncmp(arrayNameUpper,"DISP",4))
|
|
{
|
|
// Add it to the arrays I want
|
|
SetPointArrayStatus(idx, 1);
|
|
}
|
|
|
|
// Does the user want this array?
|
|
getArray = this->GetPointArrayStatus(idx);
|
|
|
|
// If I have the array and the user DOESN'T want it
|
|
// then remove the array from the output
|
|
if (haveArray && !getArray)
|
|
{
|
|
output->GetPointData()->RemoveArray(arrayName);
|
|
|
|
if (this->ExodusModel)
|
|
{
|
|
this->ExodusModel->RemoveUGridNodeVariable(arrayName);
|
|
}
|
|
}
|
|
|
|
// If the user wants this array AND I don't already have it
|
|
// then read in the data
|
|
else if (getArray && !haveArray)
|
|
{
|
|
|
|
// How many dimensions is this array
|
|
dim = this->GetPointArrayNumberOfComponents(idx);
|
|
|
|
if (dim == 1)
|
|
array = this->ReadPointArray(handle, arrayIdx);
|
|
else
|
|
array = this->ReadPointVector(handle, arrayIdx, dim);
|
|
|
|
// Opps some sort of problem
|
|
if (array == NULL)
|
|
{
|
|
vtkErrorMacro("Problem reading node array " << this->GetPointArrayName(idx));
|
|
// Do not try loading this again
|
|
this->MetaData->SetPointArrayStatus(idx,0);
|
|
}
|
|
else
|
|
{
|
|
array->SetName(this->GetPointArrayName(idx));
|
|
output->GetPointData()->AddArray(array);
|
|
|
|
// Delete array memory (FIXME this seems inefficient)
|
|
array->Delete();
|
|
array = NULL;
|
|
|
|
if (this->ExodusModel)
|
|
{
|
|
// So ExodusIIWriter can map names in UGrid back to names in
|
|
// Exodus II file.
|
|
|
|
char *origName =
|
|
vtkExodusReader::StrDupWithNew(
|
|
this->MetaData->GetPointArrayOriginalName(arrayIdx));
|
|
char *newName =
|
|
vtkExodusReader::StrDupWithNew(this->GetPointArrayName(idx));
|
|
|
|
this->ExodusModel->AddUGridNodeVariable(newName, origName, dim);
|
|
}
|
|
}
|
|
}
|
|
|
|
// The array index needs to be incremented by the dimension
|
|
dim = this->GetPointArrayNumberOfComponents(idx);
|
|
arrayIdx += dim;
|
|
}
|
|
|
|
// Read cell arrays.
|
|
arrayIdx = 0;
|
|
for (idx = 0; idx < this->GetNumberOfCellArrays(); ++idx)
|
|
{
|
|
|
|
// Get the name of the array
|
|
strcpy(arrayName,this->GetCellArrayName(idx));
|
|
|
|
// Do I already have this array?
|
|
if (output->GetCellData()->GetArray(arrayName) != NULL)
|
|
haveArray=1;
|
|
else
|
|
haveArray=0;
|
|
|
|
// Does the user want this array?
|
|
getArray = this->GetCellArrayStatus(idx);
|
|
|
|
// If I have the array and the user DOESN'T want it
|
|
// then remove the array from the output
|
|
if (haveArray && !getArray)
|
|
{
|
|
output->GetCellData()->RemoveArray(arrayName);
|
|
|
|
if (this->ExodusModel)
|
|
{
|
|
this->ExodusModel->RemoveUGridElementVariable(arrayName);
|
|
}
|
|
}
|
|
// If the user wants this array AND I don't already have it
|
|
// then read in the data
|
|
else if (getArray && !haveArray)
|
|
{
|
|
// How many dimensions is this array
|
|
dim = this->GetCellArrayNumberOfComponents(idx);
|
|
if (dim == 1)
|
|
array = this->ReadCellArray(handle, arrayIdx);
|
|
else
|
|
array = this->ReadCellVector(handle, arrayIdx, dim);
|
|
|
|
// Opps some sort of problem
|
|
if (array == NULL)
|
|
{
|
|
vtkErrorMacro("Problem reading cell array " << this->GetCellArrayName(idx));
|
|
// Do not try loading this again
|
|
this->MetaData->SetCellArrayStatus(idx, 0);
|
|
|
|
}
|
|
else
|
|
{
|
|
array->SetName(this->GetCellArrayName(idx));
|
|
output->GetCellData()->AddArray(array);
|
|
|
|
array->Delete();
|
|
array = NULL;
|
|
|
|
if (this->ExodusModel)
|
|
{
|
|
// So ExodusIIWriter can map names in UGrid back to names in
|
|
// Exodus II file.
|
|
|
|
char *origName =
|
|
vtkExodusReader::StrDupWithNew(
|
|
this->MetaData->GetCellArrayOriginalName(arrayIdx));
|
|
char *newName =
|
|
vtkExodusReader::StrDupWithNew(this->GetCellArrayName(idx));
|
|
|
|
this->ExodusModel->AddUGridElementVariable(newName, origName, dim);
|
|
}
|
|
}
|
|
}
|
|
// The array index needs to be incremented by the dimension
|
|
dim = this->GetCellArrayNumberOfComponents(idx);
|
|
arrayIdx += dim;
|
|
}
|
|
|
|
}
|
|
|
|
void vtkExodusReader::AddDisplacements(vtkUnstructuredGrid* output)
|
|
{
|
|
char arrayName[MAX_STR_LENGTH];
|
|
char arrayNameUpper[MAX_STR_LENGTH];
|
|
int FOUND = 0;
|
|
|
|
// Now find the displacement array
|
|
strcpy(arrayName, "None");
|
|
for (int idx = 0; idx < this->GetNumberOfPointArrays(); ++idx)
|
|
{
|
|
// Is this array displacement?
|
|
strcpy(arrayName, this->GetPointArrayName(idx));
|
|
this->StringUppercase(arrayName,arrayNameUpper);
|
|
if (!strncmp(arrayNameUpper,"DISP",4))
|
|
{
|
|
FOUND = 1;
|
|
break;
|
|
}
|
|
}
|
|
|
|
// If I did not find displacements then just return
|
|
if (!FOUND) return;
|
|
|
|
// Create warp vector filter
|
|
vtkWarpVector *warp = vtkWarpVector::New();
|
|
|
|
vtkUnstructuredGrid *geom = vtkUnstructuredGrid::New();
|
|
geom->ShallowCopy(output);
|
|
|
|
warp->SetInput(geom);
|
|
warp->SetInputArrayToProcess(
|
|
0, 0, 0, vtkDataObject::FIELD_ASSOCIATION_POINTS, arrayName);
|
|
warp->SetScaleFactor(DisplacementMagnitude);
|
|
warp->Update();
|
|
|
|
geom->Delete();
|
|
|
|
// Copy warped mesh and cell/point data to my output
|
|
|
|
output->CopyStructure(warp->GetUnstructuredGridOutput());
|
|
output->GetCellData()->PassData(warp->GetUnstructuredGridOutput()->GetCellData());
|
|
output->GetPointData()->PassData(warp->GetUnstructuredGridOutput()->GetPointData());
|
|
|
|
// Delete warp filter
|
|
warp->Delete();
|
|
|
|
// Remove displacement field if it's possible the dataset will be
|
|
// written out to a new Exodus file later on. Since we've just
|
|
// applied displacements to the points, maintaining the displacement array
|
|
// will yield incorrect geometry when the output file is read in.
|
|
|
|
if (this->ExodusModelMetadata){
|
|
output->GetPointData()->RemoveArray(arrayName);
|
|
}
|
|
}
|
|
|
|
|
|
vtkDataArray *vtkExodusReader::ReadPointVector(int handle, int varIndex, int dim)
|
|
{
|
|
// Sanity check
|
|
if (dim !=2 && dim!=3)
|
|
{
|
|
vtkErrorMacro("Error: Only support 2 or 3 dim vectors var_index:" \
|
|
<< varIndex << " dim:" << dim<< " file: " << this->FileName);
|
|
return NULL;
|
|
}
|
|
|
|
// Create vector array
|
|
vtkFloatArray *vectors = vtkFloatArray::New();
|
|
vectors->SetNumberOfComponents(3);
|
|
vectors->SetNumberOfTuples(this->NumberOfUsedNodes);
|
|
|
|
// Grab first two arrays
|
|
vtkFloatArray *dim1 = (vtkFloatArray*)ReadPointArray(handle,varIndex);
|
|
vtkFloatArray *dim2 = (vtkFloatArray*)ReadPointArray(handle,varIndex+1);
|
|
|
|
// Do they need a third
|
|
vtkFloatArray *dim3 = NULL;
|
|
if (dim == 3)
|
|
dim3 = (vtkFloatArray*)ReadPointArray(handle,varIndex+2);
|
|
|
|
// Okay now set up memory pointers
|
|
float *vector_ptr = vectors->GetPointer(0);
|
|
float *dim1_ptr = dim1->GetPointer(0);
|
|
float *dim2_ptr = dim2->GetPointer(0);
|
|
float *dim3_ptr = NULL; if(dim==3) dim3_ptr = dim3->GetPointer(0);
|
|
|
|
// Okay now swizzle into vector array
|
|
if (dim==2)
|
|
{
|
|
for(int i=0; i<this->NumberOfUsedNodes; ++i)
|
|
{
|
|
*vector_ptr++ = *dim1_ptr++;
|
|
*vector_ptr++ = *dim2_ptr++;
|
|
*vector_ptr++ = 0;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
for(int i=0; i<this->NumberOfUsedNodes; ++i)
|
|
{
|
|
*vector_ptr++ = *dim1_ptr++;
|
|
*vector_ptr++ = *dim2_ptr++;
|
|
*vector_ptr++ = *dim3_ptr++;
|
|
}
|
|
}
|
|
|
|
dim1->Delete();
|
|
dim2->Delete();
|
|
if ( dim3 )
|
|
{
|
|
dim3->Delete();
|
|
}
|
|
|
|
// Okay all done
|
|
return vectors;
|
|
}
|
|
|
|
vtkDataArray *vtkExodusReader::ReadPointArray(int handle, int varIndex)
|
|
{
|
|
// Temp float array
|
|
float *exo_array_data;
|
|
exo_array_data = new float[this->NumberOfNodesInFile];
|
|
|
|
// Create data array
|
|
vtkFloatArray *array = vtkFloatArray::New();
|
|
array->SetNumberOfValues(this->NumberOfUsedNodes);
|
|
|
|
// Read in data into temp array (note that Exodus is 1 based)
|
|
int error = ex_get_nodal_var (handle,
|
|
this->ActualTimeStep+1,
|
|
varIndex+1,
|
|
this->NumberOfNodesInFile,
|
|
exo_array_data);
|
|
|
|
// Opps something bad happened
|
|
if (error < 0)
|
|
{
|
|
vtkErrorMacro("Error: " << error << " ex_get_nodal_var timestep:"
|
|
<< this->ActualTimeStep << " var_index: " << varIndex
|
|
<< " file: " << this->FileName);
|
|
return NULL;
|
|
}
|
|
|
|
// Okay copy the points that are actually used into the vtk array
|
|
int point_index;
|
|
for(int i=0; i<this->NumberOfUsedNodes; i++)
|
|
{
|
|
point_index = this->ReversePointMap->GetValue(i);
|
|
array->SetValue(i, exo_array_data[point_index]);
|
|
}
|
|
|
|
// Clean up temp float array
|
|
delete [] exo_array_data;
|
|
|
|
|
|
return array;
|
|
}
|
|
|
|
vtkDataArray *vtkExodusReader::ReadCellVector(int handle, int varIndex, int dim)
|
|
{
|
|
// Sanity check
|
|
if (dim !=2 && dim!=3)
|
|
{
|
|
vtkErrorMacro("Error: Only support 2 or 3 dim vectors var_index:" \
|
|
<< varIndex << " dim:" << dim<< " file: " << this->FileName);
|
|
return NULL;
|
|
}
|
|
|
|
// Create vector array
|
|
vtkFloatArray *vectors = vtkFloatArray::New();
|
|
vectors->SetNumberOfComponents(3);
|
|
vectors->SetNumberOfTuples(this->NumberOfUsedElements);
|
|
|
|
// Grab first two arrays
|
|
vtkFloatArray *dim1 = (vtkFloatArray*)ReadCellArray(handle,varIndex);
|
|
vtkFloatArray *dim2 = (vtkFloatArray*)ReadCellArray(handle,varIndex+1);
|
|
|
|
// Do they need a third
|
|
vtkFloatArray *dim3 = NULL;
|
|
if (dim == 3)
|
|
dim3 = (vtkFloatArray*)ReadCellArray(handle,varIndex+2);
|
|
|
|
// Okay now set up memory pointers
|
|
float *vector_ptr = vectors->GetPointer(0);
|
|
float *dim1_ptr = dim1->GetPointer(0);
|
|
float *dim2_ptr = dim2->GetPointer(0);
|
|
float *dim3_ptr = NULL; if(dim==3) dim3_ptr = dim3->GetPointer(0);
|
|
|
|
// Okay now swizzle into vector array
|
|
if (dim==2)
|
|
{
|
|
for(int i=0; i<this->NumberOfUsedElements; ++i)
|
|
{
|
|
*vector_ptr++ = *dim1_ptr++;
|
|
*vector_ptr++ = *dim2_ptr++;
|
|
*vector_ptr++ = 0;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
for(int i=0; i<this->NumberOfUsedElements; ++i)
|
|
{
|
|
*vector_ptr++ = *dim1_ptr++;
|
|
*vector_ptr++ = *dim2_ptr++;
|
|
*vector_ptr++ = *dim3_ptr++;
|
|
}
|
|
}
|
|
|
|
dim1->Delete();
|
|
dim2->Delete();
|
|
if ( dim3 )
|
|
{
|
|
dim3->Delete();
|
|
}
|
|
|
|
// Okay all done
|
|
return vectors;
|
|
}
|
|
|
|
void vtkExodusReader::FixMetadataTruthTable(int *table, int len)
|
|
{
|
|
if (this->ExodusModelMetadata && this->ExodusModel)
|
|
{
|
|
// vtkModelMetadata will free table when it is destroyed
|
|
|
|
int *newtable = new int [len];
|
|
memcpy(newtable, table, len * sizeof(int));
|
|
|
|
this->ExodusModel->GetModelMetadata()->SetElementVariableTruthTable(newtable);
|
|
}
|
|
}
|
|
|
|
// Read in the cell array specified by index 'varIndex'
|
|
vtkDataArray *vtkExodusReader::ReadCellArray(int handle, int varIndex)
|
|
{
|
|
int i;
|
|
int error;
|
|
int blockIdx;
|
|
|
|
// Create the data array
|
|
vtkFloatArray *array = vtkFloatArray::New();
|
|
array->SetNumberOfValues(this->NumberOfUsedElements);
|
|
float *arrayPtr = array->GetPointer(0);
|
|
int nblocks = this->MetaData->GetNumberOfBlocks();
|
|
|
|
// Loop through the blocks.
|
|
for (blockIdx=0; blockIdx < nblocks; ++blockIdx)
|
|
{
|
|
// Do we read this block?
|
|
if (this->MetaData->GetBlockStatus(blockIdx)==0)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
// Get number of elements in block
|
|
int numBlockElements = this->MetaData->GetNumElementsInBlock(blockIdx);
|
|
|
|
// Truth Table may say no variables on this block for this variable
|
|
int cell_arrays = this->MetaData->GetOriginalNumberOfCellArrays();
|
|
int truthTableIdx =
|
|
this->MetaData->GetSortedOrder(blockIdx)*cell_arrays + varIndex;
|
|
|
|
if (this->CellVarTruthTable->GetValue(truthTableIdx) == 1)
|
|
{
|
|
error =
|
|
ex_get_elem_var (handle, this->ActualTimeStep+1, varIndex+1,
|
|
this->MetaData->GetBlockId(blockIdx), numBlockElements,
|
|
arrayPtr);
|
|
|
|
if (error < 0)
|
|
{
|
|
vtkWarningMacro("Warning: Truth Table indicated that cell variable " <<
|
|
this->GetCellArrayName(varIndex) <<
|
|
" appears in block " << this->MetaData->GetBlockId(blockIdx) <<
|
|
",\nhowever it is not there. "
|
|
"Truth table has been modified (in VTK memory only).");
|
|
|
|
// Assume the truth table is wrong. (Because we have seen this occur.)
|
|
// Change our table and change the one saved in the metadata.
|
|
this->CellVarTruthTable->SetValue(truthTableIdx, 0);
|
|
this->FixMetadataTruthTable(this->CellVarTruthTable->GetPointer(0),
|
|
nblocks * cell_arrays);
|
|
}
|
|
}
|
|
|
|
if (this->CellVarTruthTable->GetValue(truthTableIdx) == 0)
|
|
{
|
|
for(i=0; i<numBlockElements; ++i)
|
|
{
|
|
arrayPtr[i] = 0;
|
|
}
|
|
}
|
|
|
|
arrayPtr += numBlockElements;
|
|
}
|
|
|
|
// Padding cell arrays to have 'some' value for the addition
|
|
// of nodesets and sidesets
|
|
for(i=0;i<GetExtraCellCountForNodeSideSets();++i)
|
|
{
|
|
array->InsertNextValue(0);
|
|
}
|
|
|
|
|
|
// AOK so return array
|
|
return array;
|
|
}
|
|
|
|
|
|
int vtkExodusReader::GetExtraCellCountForNodeSideSets()
|
|
{
|
|
int i;
|
|
int count=0;
|
|
|
|
// Count number of additional 'cells' for nodesets
|
|
for (i=0; i < this->GetNumberOfNodeSets(); ++i)
|
|
{
|
|
// Do we read this node set?
|
|
if (this->MetaData->GetNodeSetStatus(i))
|
|
{
|
|
count += this->MetaData->GetNodeSetSize(i);
|
|
}
|
|
}
|
|
|
|
// Count number of additional 'cells' for sidesets
|
|
for (i=0; i < this->GetNumberOfSideSets(); ++i)
|
|
{
|
|
// Do we read this node set?
|
|
if (this->MetaData->GetSideSetStatus(i))
|
|
{
|
|
count += this->MetaData->GetSideSetSize(i);
|
|
}
|
|
}
|
|
|
|
|
|
// Return number of additional cell values needed
|
|
// to accommodate scalar fields count
|
|
return count;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
void vtkExodusReader::GenerateExtraArrays(vtkUnstructuredGrid* output)
|
|
{
|
|
vtkIntArray *array;
|
|
int count;
|
|
int blockId;
|
|
int i, j, numBlockElem;
|
|
int haveArray, getArray;
|
|
|
|
///////////////////////////////////////
|
|
// Get block array
|
|
///////////////////////////////////////
|
|
|
|
// Do I already have this array?
|
|
if (output->GetPointData()->GetArray( this->GetBlockIdArrayName() ) != NULL)
|
|
haveArray=1;
|
|
else
|
|
haveArray=0;
|
|
|
|
// Does the user want this array?
|
|
getArray = this->GenerateBlockIdCellArray;
|
|
|
|
// If I have the array and the user DOESN'T want it
|
|
// then remove the array from the output
|
|
if (haveArray && !getArray)
|
|
{
|
|
output->GetPointData()->RemoveArray( this->GetBlockIdArrayName() );
|
|
}
|
|
// If the user wants this array AND I don't already have it
|
|
// then read in the data
|
|
else if (getArray && !haveArray)
|
|
{
|
|
array = vtkIntArray::New();
|
|
array->SetNumberOfValues(this->NumberOfUsedElements);
|
|
count = 0;
|
|
for (i=0; i < this->MetaData->GetNumberOfBlocks(); ++i)
|
|
{
|
|
// Do we read this block?
|
|
if (this->MetaData->GetBlockStatus(i)==0)
|
|
continue;
|
|
|
|
numBlockElem = this->MetaData->GetNumElementsInBlock(i);
|
|
blockId = this->MetaData->GetBlockId(i);
|
|
for (j = 0; j < numBlockElem; ++j)
|
|
{
|
|
array->SetValue(count++,blockId);
|
|
}
|
|
}
|
|
// Padding cell arrays to have 'some' value for the addition
|
|
// of nodesets and sidesets
|
|
for(i=0;i<GetExtraCellCountForNodeSideSets();++i)
|
|
{
|
|
array->InsertNextValue(0);
|
|
}
|
|
array->SetName( this->GetBlockIdArrayName() );
|
|
output->GetCellData()->AddArray(array);
|
|
|
|
// Block IDs will be the default cell data
|
|
output->GetCellData()->SetScalars(array);
|
|
array->Delete();
|
|
array = NULL;
|
|
}
|
|
|
|
///////////////////////////////////////
|
|
// Get node id array
|
|
///////////////////////////////////////
|
|
|
|
// Do I already have this array?
|
|
if ( output->GetPointData()->GetArray(
|
|
this->GetGlobalNodeIdArrayName() ) != NULL)
|
|
{
|
|
haveArray = 1;
|
|
}
|
|
else
|
|
{
|
|
haveArray = 0;
|
|
}
|
|
|
|
// Does the user want this array?
|
|
getArray = this->GenerateGlobalNodeIdArray;
|
|
|
|
// If I have the array and the user DOESN'T want it
|
|
// then remove the array from the output
|
|
if (haveArray && !getArray)
|
|
{
|
|
output->GetPointData()->RemoveArray( this->GetGlobalNodeIdArrayName() );
|
|
}
|
|
// If the user wants this array AND I don't already have it
|
|
// then read in the data
|
|
else if (getArray && !haveArray)
|
|
{
|
|
// Temp int array
|
|
int *exo_array_data;
|
|
exo_array_data = new int[this->NumberOfNodesInFile];
|
|
|
|
// Temp vtk array
|
|
array = vtkIntArray::New();
|
|
array->SetNumberOfValues(this->NumberOfUsedNodes);
|
|
|
|
// Get the data into the temp int array
|
|
ex_get_node_num_map(this->CurrentHandle, exo_array_data);
|
|
|
|
// Okay copy the points that are actually used into the vtk array
|
|
int point_index;
|
|
for (i=0; i<this->NumberOfUsedNodes; i++)
|
|
{
|
|
point_index = this->ReversePointMap->GetValue(i);
|
|
array->SetValue(i, exo_array_data[point_index]);
|
|
}
|
|
|
|
// Clean up temp int array
|
|
delete [] exo_array_data;
|
|
|
|
// Set up array and 'give' to output
|
|
array->SetName( this->GetGlobalNodeIdArrayName() );
|
|
output->GetPointData()->AddArray(array);
|
|
|
|
// Delete my copy of the array
|
|
array->Delete();
|
|
array = NULL;
|
|
}
|
|
|
|
///////////////////////////////////////
|
|
// Get element id array
|
|
///////////////////////////////////////
|
|
|
|
// Do I already have this array?
|
|
if (output->GetPointData()->GetArray(
|
|
this->GetGlobalElementIdArrayName() ) != NULL)
|
|
{
|
|
haveArray=1;
|
|
}
|
|
else
|
|
{
|
|
haveArray=0;
|
|
}
|
|
|
|
// Does the user want this array?
|
|
getArray = this->GenerateGlobalElementIdArray;
|
|
|
|
// If I have the array and the user DOESN'T want it
|
|
// then remove the array from the output
|
|
if (haveArray && !getArray)
|
|
{
|
|
output->GetPointData()->RemoveArray( this->GetGlobalElementIdArrayName() );
|
|
}
|
|
// If the user wants this array AND I don't already have it
|
|
// then read in the data
|
|
else if (getArray && !haveArray)
|
|
{
|
|
int nblocks = this->GetNumberOfBlockArrays();
|
|
int nblocksUsed = 0;
|
|
|
|
for (i=0; i<nblocks; i++)
|
|
{
|
|
if (this->GetBlockArrayStatus(i) == 1)
|
|
{
|
|
nblocksUsed++;
|
|
}
|
|
}
|
|
if (!this->GlobalElementIdCache)
|
|
{
|
|
int *tmp = new int [this->NumberOfElementsInFile];
|
|
ex_get_elem_num_map(this->CurrentHandle, tmp);
|
|
this->GlobalElementIdCache = tmp;
|
|
}
|
|
|
|
int *idList = new int [this->NumberOfUsedElements];
|
|
|
|
if (nblocksUsed < nblocks)
|
|
{
|
|
int *from = this->GlobalElementIdCache;
|
|
int *to = idList;
|
|
|
|
for (i=0; i<nblocks; i++)
|
|
{
|
|
int used = this->GetBlockArrayStatus(i);
|
|
int bsize = this->GetNumberOfElementsInBlock(i);
|
|
|
|
if (used)
|
|
{
|
|
memcpy(to, from, bsize * sizeof(int));
|
|
to += bsize;
|
|
}
|
|
from += bsize;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
memcpy(idList, this->GlobalElementIdCache,
|
|
this->NumberOfUsedElements * sizeof(int));
|
|
}
|
|
|
|
array = vtkIntArray::New();
|
|
array->SetArray(idList, this->NumberOfUsedElements, 0);
|
|
array->SetName( this->GetGlobalElementIdArrayName() );
|
|
|
|
// Padding cell arrays to have 'some' value for the addition
|
|
// of nodesets and sidesets
|
|
for(i=0;i<GetExtraCellCountForNodeSideSets();++i)
|
|
{
|
|
array->InsertNextValue(0);
|
|
}
|
|
|
|
output->GetCellData()->AddArray(array);
|
|
array->Delete();
|
|
array = NULL;
|
|
}
|
|
// **KEN** I think we should be done with the ReversePointMap. Should we
|
|
// delete it here?
|
|
}
|
|
|
|
|
|
|
|
//----------------------------------------------------------------------------
|
|
void vtkExodusReader::PrintSelf(ostream& os, vtkIndent indent)
|
|
{
|
|
int idx;
|
|
|
|
this->Superclass::PrintSelf(os,indent);
|
|
|
|
if (this->GenerateBlockIdCellArray)
|
|
{
|
|
os << indent << "GenerateBlockIdCellArray: On\n";
|
|
}
|
|
else
|
|
{
|
|
os << indent << "GenerateBlockIdCellArray: Off\n";
|
|
}
|
|
|
|
if (this->GenerateGlobalElementIdArray)
|
|
{
|
|
os << indent << "GenerateGlobalElementIdArray: On\n";
|
|
}
|
|
else
|
|
{
|
|
os << indent << "GenerateGlobalElementIdArray: Off\n";
|
|
}
|
|
|
|
if (this->GenerateGlobalNodeIdArray)
|
|
{
|
|
os << indent << "GenerateGlobalNodeIdArray: On\n";
|
|
}
|
|
else
|
|
{
|
|
os << indent << "GenerateGlobalNodeIdArray: Off\n";
|
|
}
|
|
|
|
if (this->PackExodusModelOntoOutput )
|
|
{
|
|
os << indent << "PackExodusModelOntoOutput: On\n";
|
|
}
|
|
else
|
|
{
|
|
os << indent << "PackExodusModelOntoOutput: Off\n";
|
|
}
|
|
|
|
if (this->ApplyDisplacements)
|
|
{
|
|
os << indent << "ApplyDisplacements: On\n";
|
|
}
|
|
else
|
|
{
|
|
os << indent << "ApplyDisplacements: Off\n";
|
|
}
|
|
|
|
if (this->ExodusModelMetadata)
|
|
{
|
|
os << indent << "ExodusModelMetadata: On\n";
|
|
}
|
|
else
|
|
{
|
|
os << indent << "ExodusModelMetadata: Off\n";
|
|
}
|
|
|
|
os << indent << "File Name: "
|
|
<< (this->FileName ? this->FileName : "(none)") << "\n";
|
|
os << indent << "XML File Name: "
|
|
<< (this->XMLFileName ? this->XMLFileName : "(none)") << "\n";
|
|
os << indent << "Title: "
|
|
<< (this->Title ? this->Title : "(none)") << "\n";
|
|
os << indent << "Dimensionality: " << this->Dimensionality << "\n";
|
|
os << indent << "NumberOfUsedNodes: " << this->NumberOfUsedNodes << "\n";
|
|
os << indent << "NumberOfNodesInFile: " << this->NumberOfNodesInFile << "\n";
|
|
os << indent << "NumberOfUsedElements: " << this->NumberOfUsedElements << "\n";
|
|
os << indent << "NumberOfElementsInFile: " << this->NumberOfElementsInFile << "\n";
|
|
os << indent << "NumberOfBlocks: " << this->NumberOfBlocks << "\n";
|
|
for (idx = 0; idx < this->NumberOfBlocks; ++idx)
|
|
{
|
|
os << indent << " " << this->MetaData->GetNumElementsInBlock(idx)
|
|
<< " elements in block " << this->MetaData->GetBlockId(idx) << "\n";
|
|
}
|
|
os << indent << "NumberOfTimeSteps: " << this->NumberOfTimeSteps << "\n";
|
|
os << indent << "NumberOfPointArrays: " << this->GetNumberOfPointArrays() << "\n";
|
|
for (idx = 0; idx < this->GetNumberOfPointArrays(); ++idx)
|
|
{
|
|
os << indent << " " << this->GetPointArrayName(idx);
|
|
if (this->GetPointArrayNumberOfComponents(idx) != 1)
|
|
{
|
|
os << " " << this->GetPointArrayNumberOfComponents(idx) << " components";
|
|
}
|
|
if (this->GetPointArrayStatus(idx) == 0)
|
|
{
|
|
os << " do not load";
|
|
}
|
|
os << endl;
|
|
}
|
|
os << indent << "NumberOfCellArrays: " << this->GetNumberOfCellArrays() << "\n";
|
|
for (idx = 0; idx < this->GetNumberOfCellArrays(); ++idx)
|
|
{
|
|
os << indent << " " << this->GetCellArrayName(idx);
|
|
if (this->GetCellArrayNumberOfComponents(idx) != 1)
|
|
{
|
|
os << " " << this->GetCellArrayNumberOfComponents(idx) << " components";
|
|
}
|
|
if (this->GetCellArrayStatus(idx) == 0)
|
|
{
|
|
os << " do not load";
|
|
}
|
|
os << endl;
|
|
}
|
|
os << indent << "NumberOfSideSets: " << this->NumberOfSideSets << "\n";
|
|
os << indent << "NumberOfNodeSets: " << this->NumberOfNodeSets << "\n";
|
|
os << indent << "TimeStep: " << this->TimeStep << endl;
|
|
os << indent << "TimeStepRange: " << this->TimeStepRange[0] << " " << this->TimeStepRange[1] << endl;
|
|
os << indent << "DisplacementMagnitude: " << this->DisplacementMagnitude << "\n";
|
|
os << indent << "DisplayType: " << this->DisplayType << "\n";
|
|
}
|
|
|
|
|
|
void vtkExodusReader::CloseCurrentFile()
|
|
{
|
|
int error;
|
|
error = ex_close(this->CurrentHandle);
|
|
if (error < 0)
|
|
{
|
|
vtkErrorMacro("Error: " << error << " calling ex_close " << this->FileName);
|
|
}
|
|
this->CurrentHandle = -1;
|
|
}
|
|
|
|
int vtkExodusReader::StringsEqual(const char* s1, char* s2)
|
|
{
|
|
int same = 0;
|
|
|
|
if ((s1 == NULL) && (s2 == NULL))
|
|
{
|
|
same = 1;
|
|
}
|
|
else if (s1 && s2 && (strcmp(s1, s2) == 0))
|
|
{
|
|
same = 1;
|
|
}
|
|
|
|
return same;
|
|
}
|
|
|
|
void vtkExodusReader::StringUppercase(const char* str, char* upperstr)
|
|
{
|
|
int len = 0;
|
|
if ( str )
|
|
{
|
|
len = strlen(str);
|
|
for (int i=0; i<len; i++)
|
|
upperstr[i] = toupper(str[i]);
|
|
}
|
|
else
|
|
{
|
|
upperstr = NULL;
|
|
}
|
|
|
|
// Add string terminator
|
|
upperstr[len] = '\0';
|
|
}
|
|
|
|
void vtkExodusReader::SetUpPointMap(int num_points)
|
|
{
|
|
// Allocate and set to -1
|
|
this->PointMap->SetNumberOfValues(num_points);
|
|
for(int i=0; i<num_points; i++)
|
|
{
|
|
this->PointMap->SetValue(i, -1);
|
|
}
|
|
|
|
// I have used zero nodes at this time
|
|
this->NumberOfUsedNodes = 0;
|
|
|
|
// Also allocate the reverse point map
|
|
this->ReversePointMap->SetNumberOfValues(num_points);
|
|
}
|
|
|
|
int vtkExodusReader::GetPointMapIndex(int point_id)
|
|
{
|
|
// We may not have this point
|
|
if (this->PointMap->GetValue(point_id) == -1)
|
|
{
|
|
this->PointMap->SetValue(point_id, this->NumberOfUsedNodes);
|
|
|
|
// Store reverse lookup
|
|
this->ReversePointMap->SetValue(this->NumberOfUsedNodes, point_id);
|
|
|
|
// Increment the number of used nodes
|
|
this->NumberOfUsedNodes++;
|
|
|
|
// Return the value of the stored index
|
|
return this->NumberOfUsedNodes-1;
|
|
}
|
|
|
|
// We have the point so return it's mapped value
|
|
return this->PointMap->GetValue(point_id);
|
|
}
|
|
|
|
void vtkExodusReader::SetAllAssemblyArrayStatus( int status )
|
|
{
|
|
this->MetaData->SetArrayStatusInitValue( vtkExodusReader::ASSEMBLY, status );
|
|
int numVars = this->GetNumberOfAssemblyArrays();
|
|
for ( int id=0;id<numVars;id++ )
|
|
{
|
|
SetAssemblyArrayStatus( id, status );
|
|
}
|
|
}
|
|
|
|
void vtkExodusReader::SetAllBlockArrayStatus( int status )
|
|
{
|
|
this->MetaData->SetArrayStatusInitValue( vtkExodusReader::BLOCK, status );
|
|
int numVars = this->GetNumberOfBlockArrays();
|
|
for ( int id=0;id<numVars;id++ )
|
|
{
|
|
SetBlockArrayStatus( id, status );
|
|
}
|
|
}
|
|
|
|
void vtkExodusReader::SetAllCellArrayStatus( int status )
|
|
{
|
|
this->MetaData->SetArrayStatusInitValue( vtkExodusReader::CELL, status );
|
|
int numVars = this->GetNumberOfCellArrays();
|
|
for ( int id=0;id<numVars;id++ )
|
|
{
|
|
SetCellArrayStatus( id, status );
|
|
}
|
|
}
|
|
|
|
void vtkExodusReader::SetAllHierarchyArrayStatus( int status )
|
|
{
|
|
this->MetaData->SetArrayStatusInitValue( vtkExodusReader::HIERARCHY, status );
|
|
int numVars = this->GetNumberOfHierarchyArrays();
|
|
for ( int id=0;id<numVars;id++ )
|
|
{
|
|
SetHierarchyArrayStatus( id, status );
|
|
}
|
|
}
|
|
|
|
void vtkExodusReader::SetAllMaterialArrayStatus( int status )
|
|
{
|
|
this->MetaData->SetArrayStatusInitValue( vtkExodusReader::MATERIAL, status );
|
|
int numVars = this->GetNumberOfMaterialArrays();
|
|
for ( int id=0;id<numVars;id++ )
|
|
{
|
|
this->SetMaterialArrayStatus( id, status );
|
|
}
|
|
}
|
|
|
|
void vtkExodusReader::SetAllPartArrayStatus( int status )
|
|
{
|
|
this->MetaData->SetArrayStatusInitValue( vtkExodusReader::PART, status );
|
|
int numVars = this->GetNumberOfPartArrays();
|
|
for ( int id=0;id<numVars;id++ )
|
|
{
|
|
this->SetPartArrayStatus( id, status );
|
|
}
|
|
}
|
|
|
|
void vtkExodusReader::SetAllPointArrayStatus( int status )
|
|
{
|
|
this->MetaData->SetArrayStatusInitValue( vtkExodusReader::POINT, status );
|
|
int numVars = this->GetNumberOfPointArrays();
|
|
for ( int id=0;id<numVars;id++ )
|
|
{
|
|
this->SetPointArrayStatus( id, status );
|
|
}
|
|
}
|
|
|
|
char *vtkExodusReader::StrDupWithNew(const char *s)
|
|
{
|
|
char *newstr = NULL;
|
|
|
|
if (s)
|
|
{
|
|
int len = strlen(s);
|
|
if (len == 0)
|
|
{
|
|
newstr = new char [1];
|
|
newstr[0] = '\0';
|
|
}
|
|
else
|
|
{
|
|
newstr = new char [len + 1];
|
|
strcpy(newstr, s);
|
|
}
|
|
}
|
|
|
|
return newstr;
|
|
}
|
|
|
|
void vtkExodusReader::SetArrayStatus ( vtkExodusReader::ArrayType type,
|
|
const char *name, int flag )
|
|
{
|
|
switch (type)
|
|
{
|
|
case vtkExodusReader::CELL:
|
|
this->SetCellArrayStatus( name, flag );
|
|
break;
|
|
case vtkExodusReader::POINT:
|
|
this->SetPointArrayStatus( name, flag );
|
|
break;
|
|
case vtkExodusReader::BLOCK:
|
|
this->SetBlockArrayStatus( name, flag );
|
|
break;
|
|
case vtkExodusReader::PART:
|
|
this->SetPartArrayStatus( name, flag );
|
|
break;
|
|
case vtkExodusReader::MATERIAL:
|
|
this->SetMaterialArrayStatus( name, flag );
|
|
break;
|
|
case vtkExodusReader::ASSEMBLY:
|
|
this->SetAssemblyArrayStatus( name, flag );
|
|
break;
|
|
case vtkExodusReader::HIERARCHY:
|
|
this->SetHierarchyArrayStatus( name, flag );
|
|
break;
|
|
case vtkExodusReader::NUM_ARRAY_TYPES:
|
|
case vtkExodusReader::UNKNOWN_TYPE:
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
void vtkExodusReader::SetAllArrayStatus ( vtkExodusReader::ArrayType type,
|
|
int flag )
|
|
{
|
|
switch (type)
|
|
{
|
|
case vtkExodusReader::CELL:
|
|
this->SetAllCellArrayStatus( flag );
|
|
break;
|
|
case vtkExodusReader::POINT:
|
|
this->SetAllPointArrayStatus( flag );
|
|
break;
|
|
case vtkExodusReader::BLOCK:
|
|
this->SetAllBlockArrayStatus( flag );
|
|
break;
|
|
case vtkExodusReader::PART:
|
|
this->SetAllPartArrayStatus( flag );
|
|
break;
|
|
case vtkExodusReader::MATERIAL:
|
|
this->SetAllMaterialArrayStatus( flag );
|
|
break;
|
|
case vtkExodusReader::ASSEMBLY:
|
|
this->SetAllAssemblyArrayStatus( flag );
|
|
break;
|
|
case vtkExodusReader::HIERARCHY:
|
|
this->SetAllHierarchyArrayStatus( flag );
|
|
break;
|
|
case vtkExodusReader::NUM_ARRAY_TYPES:
|
|
case vtkExodusReader::UNKNOWN_TYPE:
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
int vtkExodusReader::GetArrayStatus ( vtkExodusReader::ArrayType type,
|
|
const char *name )
|
|
{
|
|
switch (type)
|
|
{
|
|
case vtkExodusReader::CELL:
|
|
return this->GetCellArrayStatus( name );
|
|
break;
|
|
case vtkExodusReader::POINT:
|
|
return this->GetPointArrayStatus( name );
|
|
break;
|
|
case vtkExodusReader::BLOCK:
|
|
return this->GetBlockArrayStatus( name );
|
|
break;
|
|
case vtkExodusReader::PART:
|
|
return this->GetPartArrayStatus( name );
|
|
break;
|
|
case vtkExodusReader::MATERIAL:
|
|
return this->GetMaterialArrayStatus( name );
|
|
break;
|
|
case vtkExodusReader::ASSEMBLY:
|
|
return this->GetAssemblyArrayStatus( name );
|
|
break;
|
|
case vtkExodusReader::HIERARCHY:
|
|
return this->GetHierarchyArrayStatus( name );
|
|
break;
|
|
case vtkExodusReader::NUM_ARRAY_TYPES:
|
|
case vtkExodusReader::UNKNOWN_TYPE:
|
|
default:
|
|
return 0;
|
|
break;
|
|
}
|
|
}
|
|
|
|
int vtkExodusReader::GetNumberOfArrays ( vtkExodusReader::ArrayType type )
|
|
{
|
|
switch (type)
|
|
{
|
|
case vtkExodusReader::CELL:
|
|
return this->GetNumberOfCellArrays();
|
|
break;
|
|
case vtkExodusReader::POINT:
|
|
return this->GetNumberOfPointArrays();
|
|
break;
|
|
case vtkExodusReader::BLOCK:
|
|
return this->GetNumberOfBlockArrays();
|
|
break;
|
|
case vtkExodusReader::PART:
|
|
return this->GetNumberOfPartArrays();
|
|
break;
|
|
case vtkExodusReader::MATERIAL:
|
|
return this->GetNumberOfMaterialArrays();
|
|
break;
|
|
case vtkExodusReader::ASSEMBLY:
|
|
return this->GetNumberOfAssemblyArrays();
|
|
break;
|
|
case vtkExodusReader::HIERARCHY:
|
|
return this->GetNumberOfHierarchyArrays();
|
|
break;
|
|
case vtkExodusReader::NUM_ARRAY_TYPES:
|
|
case vtkExodusReader::UNKNOWN_TYPE:
|
|
default:
|
|
return 0;
|
|
break;
|
|
}
|
|
}
|
|
|
|
const char*vtkExodusReader::GetArrayName ( vtkExodusReader::ArrayType type,
|
|
int id )
|
|
{
|
|
switch (type)
|
|
{
|
|
case vtkExodusReader::CELL:
|
|
return this->GetCellArrayName( id );
|
|
break;
|
|
case vtkExodusReader::POINT:
|
|
return this->GetPointArrayName( id );
|
|
break;
|
|
case vtkExodusReader::BLOCK:
|
|
return this->GetBlockArrayName( id );
|
|
break;
|
|
case vtkExodusReader::PART:
|
|
return this->GetPartArrayName( id );
|
|
break;
|
|
case vtkExodusReader::MATERIAL:
|
|
return this->GetMaterialArrayName( id );
|
|
break;
|
|
case vtkExodusReader::ASSEMBLY:
|
|
return this->GetAssemblyArrayName( id );
|
|
break;
|
|
case vtkExodusReader::HIERARCHY:
|
|
return this->GetHierarchyArrayName( id );
|
|
break;
|
|
case vtkExodusReader::NUM_ARRAY_TYPES:
|
|
case vtkExodusReader::UNKNOWN_TYPE:
|
|
default:
|
|
return NULL;
|
|
break;
|
|
}
|
|
}
|
|
|
|
void vtkExodusReader::SetXMLFileName(const char *filename)
|
|
{
|
|
// NULL or "" then just return
|
|
if (!filename || !strcmp(filename,""))
|
|
{
|
|
return;
|
|
}
|
|
else
|
|
{
|
|
XMLFileName = StrDupWithNew(filename); // Memory leak :)
|
|
}
|
|
|
|
this->Modified();
|
|
//cout << "Exodus XML file set to " << XMLFileName << endl;
|
|
}
|
|
|
|
// Had to add this because displacement vector names had spaces
|
|
// following them (dispx{space}, dispy{space}, dispz{space}). They
|
|
// didn't get made into a vector, so displacement was garbage.
|
|
|
|
void vtkExodusReader::RemoveBeginningAndTrailingSpaces(char **names, int len)
|
|
{
|
|
int i, j;
|
|
|
|
for (i=0; i<len; i++)
|
|
{
|
|
char *c = names[i];
|
|
int nmlen = strlen(c);
|
|
|
|
char *cbegin = c;
|
|
char *cend = c + nmlen - 1;
|
|
|
|
// remove spaces or non-printing character from start and end
|
|
|
|
for (j=0; j<nmlen; j++)
|
|
{
|
|
if (!isgraph(*cbegin)) cbegin++;
|
|
else break;
|
|
}
|
|
|
|
for (j=0; j<nmlen; j++)
|
|
{
|
|
if (!isgraph(*cend)) cend--;
|
|
else break;
|
|
}
|
|
|
|
if (cend < cbegin)
|
|
{
|
|
sprintf(names[i], "null_%d", i);
|
|
continue;
|
|
}
|
|
|
|
int newlen = cend - cbegin + 1;
|
|
|
|
if (newlen < nmlen)
|
|
{
|
|
for (j=0; j<newlen; j++)
|
|
{
|
|
*c++ = *cbegin++;
|
|
}
|
|
*c = '\0';
|
|
}
|
|
}
|
|
}
|
|
|
|
int vtkExodusReader::GetTimeSeriesData( int itemID, const char *vName,
|
|
const char *vType, vtkFloatArray *result )
|
|
{
|
|
int retVal = 0;
|
|
|
|
if ( this->OpenCurrentFile() )
|
|
{
|
|
int numTimesteps = this->GetNumberOfTimeSteps();
|
|
result->SetNumberOfComponents( 1 );
|
|
result->SetNumberOfTuples( numTimesteps );
|
|
// result->Initialize();
|
|
result->SetName( vName );
|
|
float *memory = result->GetPointer( 0 );
|
|
|
|
if ((strcmp(vType, "CELL") == 0) || (strcmp(vType, "cell") == 0) )
|
|
{
|
|
int varid = GetCellArrayID( vName );
|
|
ex_get_elem_var_time( this->CurrentHandle, varid, itemID, 1,
|
|
numTimesteps, memory );
|
|
retVal = 1;
|
|
}
|
|
else if ((strcmp(vType, "POINT") == 0) || (strcmp(vType, "point") == 0) )
|
|
{
|
|
int varid = GetPointArrayID( vName );
|
|
ex_get_nodal_var_time( this->CurrentHandle, varid, itemID, 1,
|
|
numTimesteps, memory );
|
|
retVal = 1;
|
|
}
|
|
else
|
|
{
|
|
}
|
|
this->CloseCurrentFile();
|
|
}
|
|
|
|
if ( retVal == 0 )
|
|
{
|
|
// in case there was a problem, we initialize the return data, because
|
|
// the result is expected to reflect the data we got
|
|
result->Initialize();
|
|
result->SetName( vName );
|
|
}
|
|
|
|
return retVal;
|
|
}
|
|
|
|
void vtkExodusReader::GetAllTimes(vtkInformationVector *outputVector)
|
|
{
|
|
vtkInformation* outInfo = outputVector->GetInformationObject(0);
|
|
|
|
int numTimesteps = this->GetNumberOfTimeSteps();
|
|
if (numTimesteps == 0)
|
|
{
|
|
return;
|
|
}
|
|
float* ftimeSteps = new float[numTimesteps];
|
|
ex_get_all_times( this->CurrentHandle, ftimeSteps );
|
|
double* timeSteps = new double[numTimesteps];
|
|
for (int i=0; i<numTimesteps; i++)
|
|
{
|
|
timeSteps[i] = ftimeSteps[i];
|
|
}
|
|
outInfo->Set(vtkStreamingDemandDrivenPipeline::TIME_STEPS(),
|
|
timeSteps,
|
|
numTimesteps);
|
|
delete[] timeSteps;
|
|
delete[] ftimeSteps;
|
|
}
|
|
|
|
int vtkExodusReader::GetPointArrayID( const char *name )
|
|
{
|
|
int numArrays = this->GetNumberOfPointArrays();
|
|
for ( int i=0;i<numArrays;i++ )
|
|
{
|
|
if ( strcmp( name, this->GetPointArrayName( i ) ) == 0 )
|
|
{
|
|
return i;
|
|
}
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
int vtkExodusReader::GetCellArrayID( const char *name )
|
|
{
|
|
int numArrays = this->GetNumberOfCellArrays();
|
|
for ( int i=0;i<numArrays;i++ )
|
|
{
|
|
if ( strcmp( name, this->GetCellArrayName( i ) ) == 0 )
|
|
{
|
|
return i;
|
|
}
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
int vtkExodusReader::GetBlockArrayID( const char *name )
|
|
{
|
|
int numArrays = this->GetNumberOfBlockArrays();
|
|
for ( int i=0;i<numArrays;i++ )
|
|
{
|
|
if ( strcmp( name, this->GetBlockArrayName( i ) ) == 0 )
|
|
{
|
|
return i;
|
|
}
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
int vtkExodusReader::GetPartArrayID( const char *name )
|
|
{
|
|
int numArrays = this->GetNumberOfPartArrays();
|
|
for ( int i=0;i<numArrays;i++ )
|
|
{
|
|
if ( strcmp( name, this->GetPartArrayName( i ) ) == 0 )
|
|
{
|
|
return i;
|
|
}
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
int vtkExodusReader::GetMaterialArrayID( const char *name )
|
|
{
|
|
int numArrays = this->GetNumberOfMaterialArrays();
|
|
for ( int i=0;i<numArrays;i++ )
|
|
{
|
|
if ( strcmp( name, this->GetMaterialArrayName( i ) ) == 0 )
|
|
{
|
|
return i;
|
|
}
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
int vtkExodusReader::OpenCurrentFile()
|
|
{
|
|
int result = 0;
|
|
|
|
// is there a file open now?
|
|
if ( this->CurrentHandle == -1 && this->FileName )
|
|
{
|
|
this->CurrentHandle = ex_open( this->FileName, EX_READ,
|
|
&(this->ExodusCPUWordSize),
|
|
&(this->ExodusIOWordSize),
|
|
&(this->ExodusVersion)
|
|
);
|
|
|
|
// Problem opening the file
|
|
if (this->CurrentHandle < 0)
|
|
{
|
|
vtkErrorMacro("Problem with the ex_open function for file " <<
|
|
this->FileName);
|
|
this->SetTitle( 0 );
|
|
this->SetCurrentFileName( NULL );
|
|
}
|
|
else
|
|
{
|
|
this->SetCurrentFileName( this->GetFileName() );
|
|
result = 1;
|
|
}
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
//begin USE_EXO_DSP_FILTERS
|
|
|
|
int vtkExodusReader::GetNumberOfVariableArrays()
|
|
{
|
|
return( GetNumberOfPointArrays()+GetNumberOfCellArrays() );
|
|
};
|
|
|
|
const char *vtkExodusReader::GetVariableArrayName(int a_which)
|
|
{
|
|
if(a_which<GetNumberOfCellArrays())
|
|
{
|
|
return(GetCellArrayName(a_which));
|
|
}
|
|
else
|
|
{
|
|
return(GetPointArrayName(a_which-GetNumberOfCellArrays()));
|
|
}
|
|
}
|
|
|
|
void vtkExodusReader::EnableDSPFiltering()
|
|
{
|
|
this->DSPFilteringIsEnabled=1;
|
|
if(!this->DSPFilters && this->GetNumberOfBlockArrays() )
|
|
{
|
|
this->DSPFilters = new vtkDSPFilterGroup*[this->GetNumberOfBlockArrays()];
|
|
for(int i=0;i<this->GetNumberOfBlockArrays();i++)
|
|
{
|
|
this->DSPFilters[i] = vtkDSPFilterGroup::New();
|
|
}
|
|
}
|
|
};
|
|
|
|
void vtkExodusReader::AddFilter(vtkDSPFilterDefinition *a_filter)
|
|
{
|
|
//printf("vtkExodusReader(%p)::addFilter %s -> %s numDSPFilters=%d GetNumberOfBlockArrays()=%d\n",this,
|
|
// a_filter->GetInputVariableName(),a_filter->GetOutputVariableName(),
|
|
// this->DSPFilters[0]->GetNumFilters(), this->GetNumberOfBlockArrays() );
|
|
|
|
this->DSPFilteringIsEnabled = 1;//Is this var necessary any more?
|
|
|
|
//allocate if necessary.....is this necessary?
|
|
if(!this->DSPFilters && this->GetNumberOfBlockArrays())
|
|
{
|
|
this->DSPFilters = new vtkDSPFilterGroup*[this->GetNumberOfBlockArrays()];
|
|
for(int i=0;i<this->GetNumberOfBlockArrays();i++)
|
|
{
|
|
this->DSPFilters[i] = vtkDSPFilterGroup::New();
|
|
}
|
|
}
|
|
if(!this->DSPFilters) return;
|
|
|
|
for(int i=0;i<this->GetNumberOfBlockArrays();i++)
|
|
{
|
|
this->DSPFilters[i]->AddFilter(a_filter);
|
|
}
|
|
|
|
//printf("after vtkExodusReader(%p)::addFilter %s -> %s numDSPFilters=%d GetNumberOfBlockArrays()=%d\n",this,
|
|
//a_filter->GetInputVariableName(),a_filter->GetOutputVariableName(),
|
|
//this->DSPFilters[0]->GetNumFilters(), this->GetNumberOfBlockArrays() );
|
|
|
|
this->Modified();//need to do this to cause the new filter to be calculated
|
|
};
|
|
|
|
//----------------------------------------------------------------------------
|
|
void vtkExodusReader::RemoveFilter(char *a_outputVariableName)
|
|
{
|
|
//allocate if necessary.....is this necessary?
|
|
if(!this->DSPFilters && this->GetNumberOfBlockArrays())
|
|
{
|
|
this->DSPFilters = new vtkDSPFilterGroup*[this->GetNumberOfBlockArrays()];
|
|
for(int i=0;i<this->GetNumberOfBlockArrays();i++)
|
|
{
|
|
this->DSPFilters[i] = vtkDSPFilterGroup::New();
|
|
}
|
|
}
|
|
if(!this->DSPFilters) return;
|
|
|
|
for(int i=0;i<this->GetNumberOfBlockArrays();i++)
|
|
{
|
|
this->DSPFilters[i]->RemoveFilter(a_outputVariableName);
|
|
}
|
|
|
|
this->Modified();//need to do this to cause the old filter to be removed
|
|
}
|
|
|
|
void vtkExodusReader::StartAddingFilter()
|
|
{
|
|
this->AddingFilter->Clear();
|
|
}
|
|
void vtkExodusReader::AddFilterInputVar(char *name)
|
|
{
|
|
this->AddingFilter->SetInputVariableName( name );
|
|
}
|
|
void vtkExodusReader::AddFilterOutputVar(char *name)
|
|
{
|
|
this->AddingFilter->SetOutputVariableName( name );
|
|
}
|
|
void vtkExodusReader::AddFilterNumeratorWeight(double weight)
|
|
{
|
|
this->AddingFilter->PushBackNumeratorWeight(weight);
|
|
}
|
|
void vtkExodusReader::AddFilterForwardNumeratorWeight(double weight)
|
|
{
|
|
this->AddingFilter->PushBackForwardNumeratorWeight(weight);
|
|
}
|
|
void vtkExodusReader::AddFilterDenominatorWeight(double weight)
|
|
{
|
|
this->AddingFilter->PushBackDenominatorWeight(weight);
|
|
}
|
|
void vtkExodusReader::FinishAddingFilter()
|
|
{
|
|
this->AddFilter(AddingFilter);
|
|
}
|
|
|
|
vtkExodusReader::ArrayType vtkExodusReader::GetArrayTypeID( const char *type )
|
|
{
|
|
if ( strcmp( type, "CELL" ) == 0 )
|
|
{
|
|
return vtkExodusReader::CELL;
|
|
}
|
|
else if ( strcmp( type, "POINT" ) == 0 )
|
|
{
|
|
return vtkExodusReader::POINT;
|
|
}
|
|
else if ( strcmp( type, "BLOCK" ) == 0 )
|
|
{
|
|
return vtkExodusReader::BLOCK;
|
|
}
|
|
else if ( strcmp( type, "PART" ) == 0 )
|
|
{
|
|
return vtkExodusReader::PART;
|
|
}
|
|
else if ( strcmp( type, "MATERIAL" ) == 0 )
|
|
{
|
|
return vtkExodusReader::MATERIAL;
|
|
}
|
|
else if ( strcmp( type, "ASSEMBLY" ) == 0 )
|
|
{
|
|
return vtkExodusReader::ASSEMBLY;
|
|
}
|
|
else if ( strcmp( type, "HIERARCHY" ) == 0 )
|
|
{
|
|
return vtkExodusReader::HIERARCHY;
|
|
}
|
|
else
|
|
{
|
|
return vtkExodusReader::UNKNOWN_TYPE;
|
|
}
|
|
}
|
|
|
|
void vtkExodusReader::GetDSPOutputArrays(int handle, vtkUnstructuredGrid* output)
|
|
{
|
|
|
|
//printf("\nvtkExodusReader(%p)::GetDSPOutputArrays numDSPFilters=%d numblocks=%d isenabled=%d numvars=%d num pt arrays=%d num cell arrays=%d\n\n",
|
|
// this,this->DSPFilters[0]->GetNumFilters(),this->GetNumberOfBlockArrays(),
|
|
// this->DSPFilteringIsEnabled,this->GetNumberOfVariableArrays(),
|
|
// this->GetOutput()->GetPointData()->GetNumberOfArrays(), this->GetOutput()->GetCellData()->GetNumberOfArrays() );
|
|
|
|
//allocate if necessary.....is this necessary?
|
|
if(!this->DSPFilters && this->GetNumberOfBlockArrays())
|
|
{
|
|
this->DSPFilters = new vtkDSPFilterGroup*[this->GetNumberOfBlockArrays()];
|
|
for(int i=0;i<this->GetNumberOfBlockArrays();i++)
|
|
{
|
|
this->DSPFilters[i] = vtkDSPFilterGroup::New();
|
|
}
|
|
}
|
|
|
|
if(this->DSPFilteringIsEnabled && this->DSPFilters)
|
|
{
|
|
//printf("in vtkExodusReader::GetDSPOutputArrays DSPFilters IS allocated\n");
|
|
|
|
int l_numPointVarInstancesLoaded=0;
|
|
int l_numCellVarInstancesLoaded=0;
|
|
int i,j;
|
|
|
|
//GET ALL THE INPUTS
|
|
//This is a brute force approach, but will never be problem-sized
|
|
for(int l_whichVar=0;
|
|
l_whichVar<this->GetNumberOfVariableArrays();
|
|
l_whichVar++)
|
|
{
|
|
const char *l_name = this->GetVariableArrayName(l_whichVar);
|
|
for(int l_whichTime=0;
|
|
l_whichTime<this->GetNumberOfTimeSteps();
|
|
l_whichTime++)
|
|
{
|
|
//assuming all blocks' filters have same needs
|
|
int l_needed =
|
|
this->DSPFilters[0]->IsThisInputVariableInstanceNeeded(
|
|
l_name,l_whichTime,this->ActualTimeStep);
|
|
if(l_needed)
|
|
{
|
|
//cannot assume all blocks' filters have the same cache,
|
|
//because a block may have been turned off before
|
|
for(i=0;i<this->GetNumberOfBlockArrays();i++)
|
|
{
|
|
//XXX STILL NEED TO HANDLE TRUTH TABLES FOR SHIP.EXO
|
|
if( this->GetBlockArrayStatus(i) )
|
|
{
|
|
int l_cached =
|
|
this->DSPFilters[i]->IsThisInputVariableInstanceCached(
|
|
l_name,l_whichTime);
|
|
if(!l_cached)
|
|
{
|
|
//Get the type of var, and the index of var
|
|
int l_varIndex=-1;
|
|
int l_pointArrayIndex=0, l_cellArrayIndex=0;//this is confusing
|
|
int l_isPointArray=0;
|
|
for(j=0;j<this->GetNumberOfPointArrays();j++)
|
|
{
|
|
if(!strcmp(this->GetPointArrayName(j),l_name))
|
|
{
|
|
l_varIndex=j;
|
|
l_isPointArray=1;
|
|
break;
|
|
}
|
|
l_pointArrayIndex += this->GetPointArrayNumberOfComponents(j);
|
|
}
|
|
for(j=0;j<this->GetNumberOfCellArrays();j++)
|
|
{
|
|
if(!strcmp(this->GetCellArrayName(j),l_name))
|
|
{
|
|
if(l_varIndex>=0)
|
|
{
|
|
vtkErrorMacro(
|
|
"Apparently there are cell and point vars with same name: "
|
|
<< l_name);
|
|
break;
|
|
}
|
|
l_varIndex=j;
|
|
l_isPointArray=0;
|
|
break;
|
|
}
|
|
l_cellArrayIndex += this->GetCellArrayNumberOfComponents(j);
|
|
}
|
|
if(l_varIndex<0)
|
|
{
|
|
vtkErrorMacro(
|
|
"Cant find cell or point vars with name: " << l_name);
|
|
break;
|
|
}
|
|
|
|
|
|
|
|
if(l_isPointArray)
|
|
{
|
|
//Cant use l_varIndex here, because the output's
|
|
// 'Point Data' may
|
|
//not have all the vars that the actual input Point Data has
|
|
vtkDataArray *l_array=output->GetPointData()->GetArray(l_name);
|
|
|
|
if(!l_array)
|
|
{
|
|
int l_dim =
|
|
this->GetPointArrayNumberOfComponents(l_varIndex);
|
|
|
|
if (l_dim == 1)
|
|
l_array = this->ReadPointArray(handle, l_pointArrayIndex);
|
|
else
|
|
l_array = this->ReadPointVector(
|
|
handle, l_pointArrayIndex, l_dim);
|
|
}
|
|
if(!l_array)
|
|
{
|
|
vtkErrorMacro("Cant get point array: " << l_name);
|
|
break;
|
|
}
|
|
|
|
if(!l_array->GetNumberOfComponents() ||
|
|
!l_array->GetNumberOfTuples())
|
|
{
|
|
vtkErrorMacro("Zero sized point array: " << l_name);
|
|
break;
|
|
}
|
|
|
|
|
|
int l_type = l_array->GetDataType();
|
|
if( l_type!=VTK_FLOAT)
|
|
{
|
|
printf("vtkExodusReader::GetDSPOutputArrays can only do "
|
|
"floats for now (type=%d)\n",l_type);
|
|
}
|
|
else
|
|
{
|
|
vtkFloatArray *l_floatArray =
|
|
static_cast<vtkFloatArray *> (l_array);
|
|
this->DSPFilters[i]->AddInputVariableInstance(
|
|
l_name,l_whichTime,l_floatArray);
|
|
|
|
l_numPointVarInstancesLoaded++;
|
|
}
|
|
|
|
|
|
//l_array->Delete(); //DONT DELETE HERE 26aug
|
|
|
|
/*END OF POINT ARRAY PART*/
|
|
}
|
|
else
|
|
{
|
|
//BEGIN CELL ARRAY PART
|
|
//Cant use l_varIndex here, because the output's 'Point Data' may
|
|
//not have all the vars that the actual input Point Data has
|
|
vtkDataArray *l_array =
|
|
output->GetCellData()->GetArray(l_name);
|
|
if(!l_array)
|
|
{
|
|
int l_dim = this->GetCellArrayNumberOfComponents(l_varIndex);
|
|
|
|
if (l_dim == 1)
|
|
l_array = this->ReadCellArray(handle, l_cellArrayIndex);
|
|
else
|
|
l_array =
|
|
this->ReadCellVector(handle, l_cellArrayIndex, l_dim);
|
|
}
|
|
if(!l_array)
|
|
{
|
|
vtkErrorMacro("Cant get cell array: " << l_name);
|
|
break;
|
|
}
|
|
|
|
if(!l_array->GetNumberOfComponents() ||
|
|
!l_array->GetNumberOfTuples())
|
|
{
|
|
vtkErrorMacro("Zero sized cell array: " << l_name);
|
|
break;
|
|
}
|
|
|
|
|
|
|
|
int l_type = l_array->GetDataType();
|
|
if( l_type!=VTK_FLOAT)
|
|
{
|
|
printf("vtkExodusReader::GetDSPOutputArrays can only "
|
|
"do floats for now (type=%d)\n",l_type);
|
|
}
|
|
else
|
|
{
|
|
vtkFloatArray *l_floatArray =
|
|
static_cast<vtkFloatArray *> (l_array);
|
|
this->DSPFilters[i]->AddInputVariableInstance(
|
|
l_name,l_whichTime,l_floatArray);
|
|
|
|
l_numCellVarInstancesLoaded++;
|
|
}
|
|
|
|
|
|
//l_array->Delete(); //DONT DELETE HERE 26aug
|
|
|
|
/*END OF CELL ARRAY PART*/
|
|
|
|
}
|
|
}
|
|
//else printf("...vtkExodusReader DSP FILTERING not loading time %d %s for block %d of %d ALREADY CACHED\n",l_whichTime,l_name,i,this->GetNumberOfBlockArrays());
|
|
|
|
}
|
|
//else printf("...vtkExodusReader DSP FILTERING time %d %s for block %d of %d HAS 0 STATUS\n",l_whichTime,l_name,i,this->GetNumberOfBlockArrays());
|
|
}
|
|
}
|
|
//else printf("...vtkExodusReader DSP FILTERING time %d %s NOT NEEDED\n",l_whichTime,l_name);
|
|
}
|
|
}
|
|
printf("vtkExodusReader::GetDSPOutputArrays() read %d dsp POINT "
|
|
"input variable instances\n",l_numPointVarInstancesLoaded);
|
|
printf("vtkExodusReader::GetDSPOutputArrays() read %d dsp CELL "
|
|
"input variable instances\n",l_numCellVarInstancesLoaded);
|
|
|
|
//CALCULATE THE OUTPUTS
|
|
int l_numCalculated=0;
|
|
int l_numFilters = (int) this->DSPFilters[0]->GetNumFilters();
|
|
for(i=0;i<this->GetNumberOfBlockArrays();i++)
|
|
{
|
|
for(j=0;j<l_numFilters;j++)
|
|
{
|
|
//Figure out whether the input (and therefore output) var
|
|
//is cell or point
|
|
int l_isCellVar=1;
|
|
int l_var=-1;
|
|
for(l_var=0;l_var<this->GetNumberOfPointArrays();l_var++)
|
|
{
|
|
if(!strcmp(this->GetPointArrayName(l_var),
|
|
this->DSPFilters[i]->GetInputVariableName(j) ))
|
|
{
|
|
l_isCellVar=0;
|
|
break;
|
|
}
|
|
}
|
|
|
|
vtkFloatArray *l_array=NULL;
|
|
if( this->GetBlockArrayStatus(i) )
|
|
{
|
|
l_array = this->DSPFilters[i]->GetOutput(
|
|
j, this->ActualTimeStep, l_numCalculated );
|
|
}
|
|
|
|
|
|
|
|
if(l_array)
|
|
{
|
|
|
|
|
|
#if 0 //get the min/max and print it out
|
|
int l_datatype = l_array->GetDataType();
|
|
if( l_datatype==VTK_FLOAT)
|
|
{
|
|
for(int l_comp=0;l_comp<l_array->GetNumberOfComponents();l_comp++)
|
|
{
|
|
float l_min,l_max;
|
|
float *l_data = (float *)l_array->GetVoidPointer(0);
|
|
|
|
for(int l_tup=0;l_tup<l_array->GetNumberOfTuples();l_tup++)
|
|
{
|
|
float l_val =
|
|
l_data[l_tup*l_array->GetNumberOfComponents()+l_comp];
|
|
if(!l_tup)
|
|
{
|
|
l_min=l_max=l_val;
|
|
}
|
|
else if(l_min>l_val)
|
|
{
|
|
l_min=l_val;
|
|
}
|
|
else if(l_max<l_val)
|
|
{
|
|
l_max=l_val;
|
|
}
|
|
}
|
|
printf("*****************comp=%d min=%f max=%f\n",l_comp,l_min,l_max);
|
|
}
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
if(!l_isCellVar)
|
|
{
|
|
output->GetPointData()->AddArray(l_array);
|
|
//printf("added dsp point var block %d\n",i);
|
|
}
|
|
else
|
|
{
|
|
output->GetCellData()->AddArray(l_array);
|
|
//printf("added dsp cell var block %d\n",i);
|
|
}
|
|
}
|
|
|
|
//printf("block %d AFTER DSP num pt arrays = %d, num cell arrays = %d num pts=%d num cells=%d\n", i,
|
|
// output->GetPointData()->GetNumberOfArrays(), output->GetCellData()->GetNumberOfArrays(),
|
|
// output->GetPoints()->GetNumberOfPoints(), output->GetNumberOfCells() );
|
|
|
|
|
|
|
|
|
|
}
|
|
}
|
|
|
|
printf("---vtkExodusReader::GetDSPOutputArrays() calculated %d dsp output "
|
|
"variable instances---\n",l_numCalculated);
|
|
|
|
}
|
|
|
|
|
|
}
|
|
//end USE_EXO_DSP_FILTERS
|
|
|
|
|
|
int vtkExodusReader::IsValidVariable( const char *type, const char *name )
|
|
{
|
|
if ( this->GetVariableID( type, name ) != -1 )
|
|
{
|
|
return 1;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
int vtkExodusReader::GetVariableID ( const char *type, const char *name )
|
|
{
|
|
ArrayType typeID = this->GetArrayTypeID( type );
|
|
|
|
switch ( typeID )
|
|
{
|
|
case vtkExodusReader::CELL:
|
|
return this->GetCellArrayID( name );
|
|
break;
|
|
case vtkExodusReader::POINT:
|
|
return this->GetPointArrayID( name );
|
|
break;
|
|
case vtkExodusReader::BLOCK:
|
|
return this->GetBlockArrayID( name );
|
|
break;
|
|
case vtkExodusReader::PART:
|
|
return this->GetPartArrayID( name );
|
|
break;
|
|
case vtkExodusReader::MATERIAL:
|
|
return this->GetMaterialArrayID( name );
|
|
break;
|
|
case vtkExodusReader::ASSEMBLY:
|
|
return this->GetAssemblyArrayID( name );
|
|
break;
|
|
case vtkExodusReader::HIERARCHY:
|
|
case vtkExodusReader::NUM_ARRAY_TYPES:
|
|
case vtkExodusReader::UNKNOWN_TYPE:
|
|
default:
|
|
return -1;
|
|
break;
|
|
}
|
|
}
|
|
|
|
int vtkExodusReader::GetGlobalElementID ( vtkDataSet *data, int localID )
|
|
{
|
|
return vtkExodusReader::GetIDHelper(
|
|
vtkExodusReader::GetGlobalElementIdArrayName(),
|
|
data, localID, vtkExodusReader::SEARCH_TYPE_ELEMENT );
|
|
}
|
|
|
|
int vtkExodusReader::GetGlobalElementID ( vtkDataSet *data, int localID,
|
|
int searchType )
|
|
{
|
|
return vtkExodusReader::GetGlobalID(
|
|
vtkExodusReader::GetGlobalElementIdArrayName(), data,
|
|
localID, searchType );
|
|
}
|
|
|
|
int vtkExodusReader::GetGlobalNodeID ( vtkDataSet *data, int localID )
|
|
{
|
|
return vtkExodusReader::GetIDHelper(
|
|
vtkExodusReader::GetGlobalNodeIdArrayName(),
|
|
data, localID, vtkExodusReader::SEARCH_TYPE_NODE );
|
|
}
|
|
|
|
int vtkExodusReader::GetGlobalNodeID ( vtkDataSet *data, int localID,
|
|
int searchType )
|
|
{
|
|
return vtkExodusReader::GetGlobalID(
|
|
vtkExodusReader::GetGlobalNodeIdArrayName(), data,
|
|
localID, searchType );
|
|
}
|
|
|
|
int vtkExodusReader::GetGlobalID ( const char *arrayName, vtkDataSet *data,
|
|
int localID, int searchType )
|
|
{
|
|
int newID = vtkExodusReader::ID_NOT_FOUND;
|
|
switch ( searchType )
|
|
{
|
|
case vtkExodusReader::SEARCH_TYPE_ELEMENT:
|
|
case vtkExodusReader::SEARCH_TYPE_NODE:
|
|
newID = vtkExodusReader::GetIDHelper( arrayName, data, localID, searchType );
|
|
break;
|
|
case vtkExodusReader::SEARCH_TYPE_ELEMENT_THEN_NODE:
|
|
// if this search fails ...
|
|
newID = vtkExodusReader::GetIDHelper( arrayName, data, localID,
|
|
vtkExodusReader::SEARCH_TYPE_ELEMENT );
|
|
if ( newID == vtkExodusReader::ID_NOT_FOUND )
|
|
{
|
|
// try this search
|
|
newID = vtkExodusReader::GetIDHelper( arrayName, data, localID,
|
|
vtkExodusReader::SEARCH_TYPE_NODE );
|
|
}
|
|
break;
|
|
case vtkExodusReader::SEARCH_TYPE_NODE_THEN_ELEMENT:
|
|
// if this search fails ...
|
|
newID = vtkExodusReader::GetIDHelper( arrayName, data, localID,
|
|
vtkExodusReader::SEARCH_TYPE_NODE );
|
|
if ( newID == vtkExodusReader::ID_NOT_FOUND )
|
|
{
|
|
// try this search
|
|
newID = vtkExodusReader::GetIDHelper( arrayName, data, localID,
|
|
vtkExodusReader::SEARCH_TYPE_ELEMENT );
|
|
}
|
|
break;
|
|
}
|
|
return newID;
|
|
}
|
|
|
|
int vtkExodusReader::GetIDHelper ( const char *arrayName, vtkDataSet *data,
|
|
int localID, int searchType )
|
|
{
|
|
int newID = vtkExodusReader::ID_NOT_FOUND;
|
|
if ( data )
|
|
{
|
|
vtkDataArray *IDs = NULL;
|
|
vtkCellData *cData = data->GetCellData();
|
|
vtkPointData *pData = data->GetPointData();
|
|
if ( searchType == vtkExodusReader::SEARCH_TYPE_ELEMENT )
|
|
{
|
|
IDs = cData->GetScalars( arrayName );
|
|
}
|
|
else if ( searchType == vtkExodusReader::SEARCH_TYPE_NODE )
|
|
{
|
|
IDs = pData->GetScalars( arrayName );
|
|
}
|
|
if ( IDs )
|
|
{
|
|
if ( ( localID >=0 ) && ( localID < IDs->GetNumberOfTuples() ) )
|
|
{
|
|
newID = (int)( IDs->GetTuple1( localID ) );
|
|
}
|
|
}
|
|
}
|
|
return newID;
|
|
}
|
|
|