Commit 5cf2fc1c authored by Robert Maynard's avatar Robert Maynard

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(
${CMAKE_CURRENT_SOURCE_DIR}
${CMAKE_CURRENT_BINARY_DIR}
${AVT_DATABASE_SOURCE_DIR}/Database
${AVT_DATABASE_SOURCE_DIR}/Ghost
${AVT_DATABASE_SOURCE_DIR}/Formats
${VISIT_COMMON_INCLUDES}
${AVT_DBATTS_SOURCE_DIR}/MetaData
......@@ -30,5 +31,5 @@ ${VTK_INCLUDE_DIRS}
ADD_PARAVIEW_PLUGIN(AVTAlgorithms "1.0"
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.
#include "vtkInformationVector.h"
#include "vtkObjectFactory.h"
#include "vtkMultiBlockDataSetAlgorithm.h"
#include "vtkStreamingDemandDrivenPipeline.h"
#include "vtkAMRBox.h"
#include "vtkHierarchicalBoxDataSet.h"
#include "vtkMultiBlockDataSet.h"
#include "vtkPolyData.h"
#include "vtkRectilinearGrid.h"
#include "vtkStructuredGrid.h"
#include "vtkUniformGrid.h"
#include "vtkUnstructuredGrid.h"
#include "vtkFieldData.h"
......@@ -44,9 +50,12 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "vtkCellData.h"
#include "avtSTMDFileFormat.h"
#include "avtDomainNesting.h"
#include "avtDatabaseMetaData.h"
#include "avtVariableCache.h"
#include "avtScalarMetaData.h"
#include "avtVectorMetaData.h"
#include "TimingsManager.h"
vtkStandardNewMacro(vtkAvtSTMDFileFormatAlgorithm);
......@@ -58,6 +67,17 @@ vtkAvtSTMDFileFormatAlgorithm::vtkAvtSTMDFileFormatAlgorithm()
this->AvtFile = 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()
{
if ( this->AvtFile )
{
this->AvtFile->FreeUpResources();
delete this->AvtFile;
this->AvtFile = NULL;
}
......@@ -86,66 +107,293 @@ void vtkAvtSTMDFileFormatAlgorithm::CleanupAVTReader()
delete this->MetaData;
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())
{
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;
}
//-----------------------------------------------------------------------------
int vtkAvtSTMDFileFormatAlgorithm::RequestData(vtkInformation *request, vtkInformationVector **inputVector, vtkInformationVector *outputVector)
{
int vtkAvtSTMDFileFormatAlgorithm::RequestData(vtkInformation *request,
vtkInformationVector **inputVector, vtkInformationVector *outputVector)
{
if (!this->InitializeAVTReader())
{
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);
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();
output->SetNumberOfBlocks( size );
for ( int i=0; i < size; ++i)
return 1;
}
else if ( this->OutputType == VTK_MULTIBLOCK_DATA_SET )
{
const avtMeshMetaData meshMetaData = this->MetaData->GetMeshes( i );
int subBlockSize = meshMetaData.numBlocks;
vtkstd::string name = meshMetaData.name;
vtkMultiBlockDataSet *output = vtkMultiBlockDataSet::
SafeDownCast(outInfo->Get(vtkDataObject::DATA_OBJECT()));
int size = this->MetaData->GetNumMeshes();
output->SetNumberOfBlocks( size );
vtkMultiBlockDataSet *child = vtkMultiBlockDataSet::New();
child->SetNumberOfBlocks( subBlockSize );
for ( int j=0; j < subBlockSize; ++j )
vtkMultiBlockDataSet* tempMultiBlock = NULL;
for ( int i=0; i < size; ++i)
{
vtkDataSet *data = this->AvtFile->GetMesh( j, name.c_str() );
if ( data )
const avtMeshMetaData meshMetaData = this->MetaData->GetMeshes( i );
vtkstd::string name = meshMetaData.name;
switch(meshMetaData.meshType)
{
//place all the scalar&vector properties onto the data
this->AssignProperties(data,name,j);
child->SetBlock(j,data);
case AVT_AMR_MESH:
case AVT_RECTILINEAR_MESH:
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();
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,
......@@ -230,6 +478,71 @@ void vtkAvtSTMDFileFormatAlgorithm::AssignProperties( vtkDataSet *data,
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)
{
......
......@@ -33,23 +33,28 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef _vtkAvtSTMDFileFormatAlgorithm_h
#define _vtkAvtSTMDFileFormatAlgorithm_h
#include "vtkMultiBlockDataSetAlgorithm.h"
#include "vtkCompositeDataSetAlgorithm.h"
#include "vtkAvtAlgorithmsExport.h"
#include "vtkStdString.h"
#include "avtMeshMetaData.h"
class vtkDataSet;
class vtkDataSet;
class vtkDataArray;
class vtkHierarchicalBoxDataSet;
class vtkMultiBlockDataSet;
//BTX
class avtSTMDFileFormat;
class avtDatabaseMetaData;
class avtVariableCache;
//ETX
class AVTALGORITHMS_EXPORT vtkAvtSTMDFileFormatAlgorithm : public vtkMultiBlockDataSetAlgorithm
class AVTALGORITHMS_EXPORT vtkAvtSTMDFileFormatAlgorithm : public vtkCompositeDataSetAlgorithm
{
public:
static vtkAvtSTMDFileFormatAlgorithm *New();
vtkTypeMacro(vtkAvtSTMDFileFormatAlgorithm,vtkMultiBlockDataSetAlgorithm);
vtkTypeMacro(vtkAvtSTMDFileFormatAlgorithm,vtkCompositeDataSetAlgorithm);
void PrintSelf(ostream& os, vtkIndent indent);
protected:
......@@ -60,6 +65,11 @@ protected:
virtual bool InitializeAVTReader();
virtual void CleanupAVTReader();
//needed since we have to change the type we output
virtual int RequestDataObject(vtkInformation *, vtkInformationVector **,
vtkInformationVector *);
// convenience method
virtual int RequestInformation(vtkInformation* request,
vtkInformationVector** inputVector,
......@@ -72,17 +82,24 @@ protected:
vtkInformationVector** inputVector,
vtkInformationVector* outputVector);
//BTX
avtSTMDFileFormat *AvtFile;
avtDatabaseMetaData *MetaData;
//ETX
private:
virtual int FillOutputPortInformation(int, vtkInformation *info);
//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);
bool ValidAMR( const avtMeshMetaData &meshMetaData );
//ETX
bool IsEvenlySpacedDataArray(vtkDataArray *data);
avtSTMDFileFormat *AvtFile;
avtDatabaseMetaData *MetaData;
avtVariableCache *Cache;
int OutputType;
private:
vtkAvtSTMDFileFormatAlgorithm(const vtkAvtSTMDFileFormatAlgorithm&);
void operator = (const vtkAvtSTMDFileFormatAlgorithm&);
};
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment