Commit 11622be6 authored by Robert Maynard's avatar Robert Maynard
Browse files

ENH: Added in support for AMR Datasets.

Currently we only convert files that have a single mesh to an AMR dataset. If we ever encounter a dataset with multiple AMR meshes we will have to revis this code.
parent 8e3eae36
...@@ -14,6 +14,7 @@ INCLUDE_DIRECTORIES( ...@@ -14,6 +14,7 @@ INCLUDE_DIRECTORIES(
${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}
${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_BINARY_DIR}
${AVT_DATABASE_SOURCE_DIR}/Database ${AVT_DATABASE_SOURCE_DIR}/Database
${AVT_DATABASE_SOURCE_DIR}/Ghost
${AVT_DATABASE_SOURCE_DIR}/Formats ${AVT_DATABASE_SOURCE_DIR}/Formats
${VISIT_COMMON_INCLUDES} ${VISIT_COMMON_INCLUDES}
${AVT_DBATTS_SOURCE_DIR}/MetaData ${AVT_DBATTS_SOURCE_DIR}/MetaData
...@@ -30,5 +31,5 @@ ${VTK_INCLUDE_DIRS} ...@@ -30,5 +31,5 @@ ${VTK_INCLUDE_DIRS}
ADD_PARAVIEW_PLUGIN(AVTAlgorithms "1.0" ADD_PARAVIEW_PLUGIN(AVTAlgorithms "1.0"
SERVER_MANAGER_SOURCES ${SOURCES} SERVER_MANAGER_SOURCES ${SOURCES}
) )
TARGET_LINK_LIBRARIES(AVTAlgorithms visitcommon avtdatabase_ser avtpipeline_ser visit_vtk) TARGET_LINK_LIBRARIES(AVTAlgorithms visitcommon avtdatabase_ser avtpipeline_ser visit_vtk)
...@@ -34,9 +34,15 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ...@@ -34,9 +34,15 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "vtkInformationVector.h" #include "vtkInformationVector.h"
#include "vtkObjectFactory.h" #include "vtkObjectFactory.h"
#include "vtkMultiBlockDataSetAlgorithm.h" #include "vtkMultiBlockDataSetAlgorithm.h"
#include "vtkStreamingDemandDrivenPipeline.h"
#include "vtkAMRBox.h"
#include "vtkHierarchicalBoxDataSet.h"
#include "vtkMultiBlockDataSet.h" #include "vtkMultiBlockDataSet.h"
#include "vtkPolyData.h" #include "vtkPolyData.h"
#include "vtkRectilinearGrid.h"
#include "vtkStructuredGrid.h"
#include "vtkUniformGrid.h"
#include "vtkUnstructuredGrid.h" #include "vtkUnstructuredGrid.h"
#include "vtkFieldData.h" #include "vtkFieldData.h"
...@@ -44,9 +50,12 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ...@@ -44,9 +50,12 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "vtkCellData.h" #include "vtkCellData.h"
#include "avtSTMDFileFormat.h" #include "avtSTMDFileFormat.h"
#include "avtDomainNesting.h"
#include "avtDatabaseMetaData.h" #include "avtDatabaseMetaData.h"
#include "avtVariableCache.h"
#include "avtScalarMetaData.h" #include "avtScalarMetaData.h"
#include "avtVectorMetaData.h" #include "avtVectorMetaData.h"
#include "TimingsManager.h"
vtkStandardNewMacro(vtkAvtSTMDFileFormatAlgorithm); vtkStandardNewMacro(vtkAvtSTMDFileFormatAlgorithm);
...@@ -58,6 +67,17 @@ vtkAvtSTMDFileFormatAlgorithm::vtkAvtSTMDFileFormatAlgorithm() ...@@ -58,6 +67,17 @@ vtkAvtSTMDFileFormatAlgorithm::vtkAvtSTMDFileFormatAlgorithm()
this->AvtFile = NULL; this->AvtFile = NULL;
this->MetaData = NULL; this->MetaData = NULL;
this->Cache = NULL;
this->OutputType = VTK_MULTIBLOCK_DATA_SET;
//visit has this horrible singelton timer that is called in all algorithms
//we need to initiailize it, and than disable it
if ( !visitTimer )
{
TimingsManager::Initialize("");
visitTimer->Disable();
}
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
...@@ -77,6 +97,7 @@ void vtkAvtSTMDFileFormatAlgorithm::CleanupAVTReader() ...@@ -77,6 +97,7 @@ void vtkAvtSTMDFileFormatAlgorithm::CleanupAVTReader()
{ {
if ( this->AvtFile ) if ( this->AvtFile )
{ {
this->AvtFile->FreeUpResources();
delete this->AvtFile; delete this->AvtFile;
this->AvtFile = NULL; this->AvtFile = NULL;
} }
...@@ -86,66 +107,293 @@ void vtkAvtSTMDFileFormatAlgorithm::CleanupAVTReader() ...@@ -86,66 +107,293 @@ void vtkAvtSTMDFileFormatAlgorithm::CleanupAVTReader()
delete this->MetaData; delete this->MetaData;
this->MetaData = NULL; this->MetaData = NULL;
} }
if ( this->Cache )
{
delete this->Cache;
this->Cache = NULL;
}
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
int vtkAvtSTMDFileFormatAlgorithm::RequestInformation(vtkInformation *request, vtkInformationVector **inputVector, vtkInformationVector *outputVector) int vtkAvtSTMDFileFormatAlgorithm::RequestDataObject(vtkInformation *,
{ vtkInformationVector** vtkNotUsed(inputVector),
vtkInformationVector* outputVector)
{
if (!this->InitializeAVTReader()) if (!this->InitializeAVTReader())
{ {
return 0; return 0;
} }
//grab image extents etc
int size = this->MetaData->GetNumMeshes();
//determine if this is an AMR mesh
this->OutputType = VTK_MULTIBLOCK_DATA_SET;
const avtMeshMetaData meshMetaData = this->MetaData->GetMeshes( 0 );
if ( size == 1 && meshMetaData.meshType == AVT_AMR_MESH)
{
//verify the mesh is correct
if ( this->ValidAMR( meshMetaData ) )
{
this->OutputType = VTK_HIERARCHICAL_BOX_DATA_SET;
}
}
vtkInformation* info = outputVector->GetInformationObject(0);
vtkCompositeDataSet *output = vtkCompositeDataSet::SafeDownCast(
info->Get(vtkDataObject::DATA_OBJECT()));
if ( output && output->GetDataObjectType() == this->OutputType )
{
return 1;
}
else if ( !output || output->GetDataObjectType() != this->OutputType )
{
switch( this->OutputType )
{
case VTK_HIERARCHICAL_BOX_DATA_SET:
output = vtkHierarchicalBoxDataSet::New();
break;
case VTK_MULTIBLOCK_DATA_SET:
default:
output = vtkMultiBlockDataSet::New();
break;
}
this->GetExecutive()->SetOutputData(0, output);
output->Delete();
}
return 1;
}
//-----------------------------------------------------------------------------
int vtkAvtSTMDFileFormatAlgorithm::RequestInformation(vtkInformation *request,
vtkInformationVector **inputVector, vtkInformationVector *outputVector)
{
if (!this->InitializeAVTReader())
{
return 0;
}
//grab image extents etc if needed
this->CleanupAVTReader();
return 1; return 1;
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
int vtkAvtSTMDFileFormatAlgorithm::RequestData(vtkInformation *request, vtkInformationVector **inputVector, vtkInformationVector *outputVector) int vtkAvtSTMDFileFormatAlgorithm::RequestData(vtkInformation *request,
{ vtkInformationVector **inputVector, vtkInformationVector *outputVector)
{
if (!this->InitializeAVTReader()) if (!this->InitializeAVTReader())
{ {
return 0; return 0;
} }
//we have to make sure the visit reader populates its cache
this->AvtFile->ActivateTimestep(); //only 1 time step in ST files
vtkInformation *outInfo = outputVector->GetInformationObject(0); vtkInformation *outInfo = outputVector->GetInformationObject(0);
vtkMultiBlockDataSet *output = vtkMultiBlockDataSet::SafeDownCast(
outInfo->Get(vtkDataObject::DATA_OBJECT()));
if ( this->OutputType == VTK_HIERARCHICAL_BOX_DATA_SET )
{
const avtMeshMetaData meshMetaData = this->MetaData->GetMeshes( 0 );
vtkHierarchicalBoxDataSet *output = vtkHierarchicalBoxDataSet::
SafeDownCast(outInfo->Get(vtkDataObject::DATA_OBJECT()));
this->FillAMR( output, meshMetaData, 0 );
int size = this->MetaData->GetNumMeshes(); return 1;
output->SetNumberOfBlocks( size ); }
for ( int i=0; i < size; ++i)
else if ( this->OutputType == VTK_MULTIBLOCK_DATA_SET )
{ {
const avtMeshMetaData meshMetaData = this->MetaData->GetMeshes( i ); vtkMultiBlockDataSet *output = vtkMultiBlockDataSet::
int subBlockSize = meshMetaData.numBlocks; SafeDownCast(outInfo->Get(vtkDataObject::DATA_OBJECT()));
vtkstd::string name = meshMetaData.name;
int size = this->MetaData->GetNumMeshes();
output->SetNumberOfBlocks( size );
vtkMultiBlockDataSet *child = vtkMultiBlockDataSet::New(); vtkMultiBlockDataSet* tempMultiBlock = NULL;
child->SetNumberOfBlocks( subBlockSize ); for ( int i=0; i < size; ++i)
for ( int j=0; j < subBlockSize; ++j )
{ {
vtkDataSet *data = this->AvtFile->GetMesh( j, name.c_str() ); const avtMeshMetaData meshMetaData = this->MetaData->GetMeshes( i );
if ( data ) vtkstd::string name = meshMetaData.name;
switch(meshMetaData.meshType)
{ {
//place all the scalar&vector properties onto the data case AVT_AMR_MESH:
this->AssignProperties(data,name,j); case AVT_RECTILINEAR_MESH:
child->SetBlock(j,data); case AVT_CURVILINEAR_MESH:
case AVT_UNSTRUCTURED_MESH:
case AVT_POINT_MESH:
case AVT_SURFACE_MESH:
case AVT_CSG_MESH:
default:
tempMultiBlock = vtkMultiBlockDataSet::New();
this->FillMultiBlock( tempMultiBlock, meshMetaData );
output->SetBlock(i,tempMultiBlock);
tempMultiBlock->Delete();
tempMultiBlock = NULL;
break;
} }
data->Delete(); output->GetMetaData(i)->Set(vtkCompositeDataSet::NAME(),name.c_str());
} }
output->GetMetaData(i)->Set(vtkCompositeDataSet::NAME(),name.c_str());
output->SetBlock(i,child);
child->Delete();
} }
this->CleanupAVTReader(); this->CleanupAVTReader();
return 1; return 1;
} }
//-----------------------------------------------------------------------------
int vtkAvtSTMDFileFormatAlgorithm::FillOutputPortInformation(int, vtkInformation *info)
{
info->Set(vtkDataObject::DATA_TYPE_NAME(), "vtkDataObject");
return 1;
}
//-----------------------------------------------------------------------------
int vtkAvtSTMDFileFormatAlgorithm::FillAMR(
vtkHierarchicalBoxDataSet *amr, const avtMeshMetaData &meshMetaData,
const int &domain)
{
//we first need to determine if this AMR can be safely converted to a
//ParaView AMR. What this means is that every dataset needs to have regular spacing
bool valid = this->ValidAMR( meshMetaData );
if ( !valid )
{
return 0;
}
//number of levels in the AMR
int numGroups = meshMetaData.numGroups;
amr->SetNumberOfLevels(numGroups);
//determine the ratio for each level
void_ref_ptr vr = this->Cache->GetVoidRef(meshMetaData.name.c_str(),
AUXILIARY_DATA_DOMAIN_NESTING_INFORMATION,
0, -1);
if (!(*vr))
{
vr = this->Cache->GetVoidRef("any_mesh",
AUXILIARY_DATA_DOMAIN_NESTING_INFORMATION,
0, -1);
}
if (!(*vr))
{
vtkErrorMacro("Unable to find cache for dataset");
return 0;
}
avtDomainNesting *domainNesting = reinterpret_cast<avtDomainNesting*>(*vr);
for ( int i=1; i < numGroups; ++i) //don't need a ratio for level 0
{
intVector ratios = domainNesting->GetRatiosForLevel(i,domain);
//Visit returns the ratio for each dimension and if it is a multiply or divide
//Currently we just presume the same ratio for each dimension
//TODO: verify this logic
if ( ratios[0] >= 2 )
{
amr->SetRefinementRatio(i, ratios[0] );
}
}
//determine the number of grids on each level of the AMR
intVector gids = meshMetaData.groupIds;
int *numDataSets = new int[ numGroups ];
for ( int i=0; i < numGroups; ++i)
{
numDataSets[i] = 0; //clear the array
}
//count the grids at each level
for ( int i=0; i < gids.size(); ++i )
{
++numDataSets[gids.at(i)];
}
//assign the info the the AMR, and create the uniform grids
vtkstd::string name = meshMetaData.name;
vtkRectilinearGrid *rgrid = NULL;
int meshIndex=0;
for ( int i=0; i < numGroups; ++i)
{
amr->SetNumberOfDataSets(i,numDataSets[i]);
for (int j=0; j < numDataSets[i]; ++j)
{
//get the rgrid from the VisIt reader
//so we have the origin/spacing/dims
rgrid = vtkRectilinearGrid::SafeDownCast(
this->AvtFile->GetMesh(meshIndex, name.c_str()));
double origin[3];
origin[0] = rgrid->GetXCoordinates()->GetTuple1(0);
origin[1] = rgrid->GetYCoordinates()->GetTuple1(0);
origin[2] = rgrid->GetZCoordinates()->GetTuple1(0);
double spacing[3];
spacing[0] = ( rgrid->GetXCoordinates()->GetNumberOfTuples() > 2 ) ?
fabs( rgrid->GetXCoordinates()->GetTuple1(1) -
rgrid->GetXCoordinates()->GetTuple1(0)): 1;
spacing[1] = ( rgrid->GetYCoordinates()->GetNumberOfTuples() > 2 ) ?
fabs( rgrid->GetYCoordinates()->GetTuple1(1) -
rgrid->GetYCoordinates()->GetTuple1(0)): 1;
spacing[2] = ( rgrid->GetZCoordinates()->GetNumberOfTuples() > 2 ) ?
fabs( rgrid->GetZCoordinates()->GetTuple1(1) -
rgrid->GetZCoordinates()->GetTuple1(0)): 1;
//set up the extents for the grid
int extents[6];
rgrid->GetExtent( extents );
int dims[3];
rgrid->GetDimensions( dims );
//don't need the rgrid anymoe
rgrid->Delete();
rgrid = NULL;
//create the dataset
vtkUniformGrid *grid = vtkUniformGrid::New();
grid->SetOrigin( origin );
grid->SetSpacing( spacing );
grid->SetDimensions( dims );
this->AssignProperties( grid, name, meshIndex );
//now create the AMR Box
vtkAMRBox box(extents);
amr->SetDataSet(i,j,box,grid);
grid->Delete();
++meshIndex;
}
}
delete[] numDataSets;
return 1;
}
//-----------------------------------------------------------------------------
void vtkAvtSTMDFileFormatAlgorithm::FillMultiBlock(
vtkMultiBlockDataSet *block, const avtMeshMetaData &meshMetaData )
{
vtkstd::string name = meshMetaData.name;
int subBlockSize = meshMetaData.numBlocks;
block->SetNumberOfBlocks( subBlockSize );
for ( int i=0; i < subBlockSize; ++i )
{
vtkDataSet *data = this->AvtFile->GetMesh( i, name.c_str() );
if ( data )
{
//place all the scalar&vector properties onto the data
this->AssignProperties(data,name,i);
block->SetBlock(i,data);
}
data->Delete();
}
}
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
void vtkAvtSTMDFileFormatAlgorithm::AssignProperties( vtkDataSet *data, void vtkAvtSTMDFileFormatAlgorithm::AssignProperties( vtkDataSet *data,
...@@ -230,6 +478,71 @@ void vtkAvtSTMDFileFormatAlgorithm::AssignProperties( vtkDataSet *data, ...@@ -230,6 +478,71 @@ void vtkAvtSTMDFileFormatAlgorithm::AssignProperties( vtkDataSet *data,
vector->Delete(); vector->Delete();
} }
} }
//-----------------------------------------------------------------------------
bool vtkAvtSTMDFileFormatAlgorithm::ValidAMR( const avtMeshMetaData &meshMetaData )
{
//I can't find an easy way to determine the type of a sub mesh
vtkstd::string name = meshMetaData.name;
vtkRectilinearGrid *rgrid = NULL;
for ( int i=0; i < meshMetaData.numBlocks; ++i )
{
//lets get the mesh for each amr box
rgrid = vtkRectilinearGrid::SafeDownCast(
this->AvtFile->GetMesh(i,name.c_str() ) );
if ( !rgrid )
{
//this is not an AMR that ParaView supports
rgrid->Delete();
return false;
}
//verify the spacing of the grid is uniform
if (!this->IsEvenlySpacedDataArray( rgrid->GetXCoordinates()) )
{
rgrid->Delete();
return false;
}
if (!this->IsEvenlySpacedDataArray( rgrid->GetYCoordinates()) )
{
rgrid->Delete();
return false;
}
if (!this->IsEvenlySpacedDataArray( rgrid->GetZCoordinates()) )
{
rgrid->Delete();
return false;
}
rgrid->Delete();
}
return true;
}
//-----------------------------------------------------------------------------
bool vtkAvtSTMDFileFormatAlgorithm::IsEvenlySpacedDataArray(vtkDataArray *data)
{
if ( !data )
{
return false;
}
//if we have less than 3 values it is evenly spaced
vtkIdType size = data->GetNumberOfTuples();
bool valid = true;
if ( size > 2 )
{
double spacing = data->GetTuple1(1)-data->GetTuple1(0);
double tolerance = 0.000001;
for (vtkIdType j = 2; j < data->GetNumberOfTuples() && valid; ++j )
{
double temp = data->GetTuple1(j) - data->GetTuple1(j-1);
valid = ( (temp - tolerance) <= spacing ) && ( (temp + tolerance) >= spacing ) ;
}
}
return valid;
}
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
void vtkAvtSTMDFileFormatAlgorithm::PrintSelf(ostream& os, vtkIndent indent) void vtkAvtSTMDFileFormatAlgorithm::PrintSelf(ostream& os, vtkIndent indent)
{ {
......
...@@ -33,23 +33,28 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ...@@ -33,23 +33,28 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef _vtkAvtSTMDFileFormatAlgorithm_h #ifndef _vtkAvtSTMDFileFormatAlgorithm_h
#define _vtkAvtSTMDFileFormatAlgorithm_h #define _vtkAvtSTMDFileFormatAlgorithm_h
#include "vtkMultiBlockDataSetAlgorithm.h" #include "vtkCompositeDataSetAlgorithm.h"
#include "vtkAvtAlgorithmsExport.h" #include "vtkAvtAlgorithmsExport.h"
#include "vtkStdString.h" #include "vtkStdString.h"
#include "avtMeshMetaData.h"
class vtkDataSet;
class vtkDataSet;
class vtkDataArray;
class vtkHierarchicalBoxDataSet;
class vtkMultiBlockDataSet;
//BTX //BTX
class avtSTMDFileFormat; class avtSTMDFileFormat;
class avtDatabaseMetaData; class avtDatabaseMetaData;
class avtVariableCache;
//ETX //ETX
class AVTALGORITHMS_EXPORT vtkAvtSTMDFileFormatAlgorithm : public vtkMultiBlockDataSetAlgorithm class AVTALGORITHMS_EXPORT vtkAvtSTMDFileFormatAlgorithm : public vtkCompositeDataSetAlgorithm
{ {
public: public:
static vtkAvtSTMDFileFormatAlgorithm *New(); static vtkAvtSTMDFileFormatAlgorithm *New();
vtkTypeMacro(vtkAvtSTMDFileFormatAlgorithm,vtkMultiBlockDataSetAlgorithm); vtkTypeMacro(vtkAvtSTMDFileFormatAlgorithm,vtkCompositeDataSetAlgorithm);
void PrintSelf(ostream& os, vtkIndent indent); void PrintSelf(ostream& os, vtkIndent indent);
protected: protected:
...@@ -60,6 +65,11 @@ protected: ...@@ -60,6 +65,11 @@ protected:
virtual bool InitializeAVTReader(); virtual bool InitializeAVTReader();
virtual void CleanupAVTReader(); virtual void CleanupAVTReader();
//needed since we have to change the type we output
virtual int RequestDataObject(vtkInformation *, vtkInformationVector **,
vtkInformationVector *);
// convenience method // convenience method
virtual int RequestInformation(vtkInformation* request, virtual int RequestInformation(vtkInformation* request,
vtkInformationVector** inputVector, vtkInformationVector** inputVector,
...@@ -72,17 +82,24 @@ protected: ...@@ -72,17 +82,24 @@ protected:
vtkInformationVector** inputVector, vtkInformationVector** inputVector,
vtkInformationVector* outputVector); vtkInformationVector* outputVector);
//BTX virtual int FillOutputPortInformation(int, vtkInformation *info);
avtSTMDFileFormat *AvtFile;
avtDatabaseMetaData *MetaData;
//ETX
private:
//BTX //BTX
int FillAMR( vtkHierarchicalBoxDataSet *amr, const avtMeshMetaData &meshMetaData,
const int &domain);
void FillMultiBlock( vtkMultiBlockDataSet *block, const avtMeshMetaData &meshMetaData );
void AssignProperties( vtkDataSet *data, const vtkStdString &meshName, const int &domain); void AssignProperties( vtkDataSet *data, const vtkStdString &meshName, const int &domain);