Commit b2edee7a authored by George Zagaris's avatar George Zagaris
Browse files

ENH: Improvements for caching of AMR blocks

This commit introduces improvements to the AMR
reader infrastructure to better facilitate caching
needs. In particular, there are two new pure virtual
methods that are introduced to load block geometry
and data (field data) seperately.
parent b49705f6
......@@ -24,7 +24,11 @@
#include "vtkSmartPointer.h"
#include "vtkCompositeDataPipeline.h"
#include "vtkStreamingDemandDrivenPipeline.h"
#include "vtkAMRDataSetCache.h"
#include "vtkUniformGrid.h"
#include "vtkDataArray.h"
#include "vtkCellData.h"
#include "vtkPointData.h"
#include "vtkAMRUtilities.h"
......@@ -229,24 +233,14 @@ int vtkAMRBaseReader::RequestInformation(
}
//------------------------------------------------------------------------------
int vtkAMRBaseReader::RequestData(
vtkInformation* vtkNotUsed(request),
vtkInformationVector** vtkNotUsed(inputVector),
vtkInformationVector* outputVector )
void vtkAMRBaseReader::SetupBlockRequest( vtkInformation *outInf )
{
vtkInformation *outInf = outputVector->GetInformationObject( 0 );
vtkHierarchicalBoxDataSet *output =
vtkHierarchicalBoxDataSet::SafeDownCast(
outInf->Get( vtkDataObject::DATA_OBJECT() ) );
assert( "pre: output AMR dataset is NULL" && ( output != NULL ) );
assert( "pre: output information is NULL" && (outInf != NULL) );
if( outInf->Has(
vtkCompositeDataPipeline::UPDATE_COMPOSITE_INDICES() ) )
{
assert( "Metadata should not be null" && (this->metadata!=NULL) );
output->Clear();
this->ReadMetaData();
int size =
......@@ -268,6 +262,100 @@ int vtkAMRBaseReader::RequestData(
this->GenerateBlockMap();
}
}
//------------------------------------------------------------------------------
void vtkAMRBaseReader::GetAMRData(
const int blockIdx, vtkUniformGrid *block, const char *fieldName )
{
assert( "pre: AMR block is NULL" && (block != NULL) );
assert( "pre: field name is NULL" && (fieldName != NULL) );
// If caching is disabled load the data from file
if( !this->IsCachingEnabled() )
{
this->GetAMRGridData( blockIdx, block, fieldName );
return;
}
// Caching is enabled.
// Check the cache to see if the data has already been read.
// Otherwise, read it and cache it.
if( this->amrCache->HasAMRBlockCellData( blockIdx, fieldName ) )
{
vtkDataArray *data =
this->amrCache->GetAMRBlockCellData( blockIdx, fieldName );
assert( "pre: cached data is NULL!" && (data != NULL) );
block->GetCellData()->AddArray( data );
}
else
{
this->GetAMRGridData( blockIdx, block, fieldName );
std::cout << "Inserting data to cache....\n";
std::cout.flush();
this->amrCache->InsertAMRBlockCellData(
blockIdx, block->GetCellData()->GetArray( fieldName ) );
}
assert( "Code should never reach here!" && (false) );
}
//------------------------------------------------------------------------------
vtkUniformGrid* vtkAMRBaseReader::GetAMRBlock( const int blockIdx )
{
// If caching is disabled load the data from file
if( !this->IsCachingEnabled() )
{
vtkUniformGrid *gridPtr = this->GetAMRGrid( blockIdx );
assert( "pre: grid pointer is NULL" && (gridPtr != NULL) );
return( gridPtr );
}
// Caching is enabled.
// Check the cache to see if the block has already been read.
// Otherwise, read it and cache it.
if( this->amrCache->HasAMRBlock( blockIdx ) )
{
vtkUniformGrid *gridPtr = vtkUniformGrid::New();
vtkUniformGrid *cachedGrid = this->amrCache->GetAMRBlock( blockIdx );
gridPtr->CopyStructure( cachedGrid );
return( gridPtr );
}
else
{
vtkUniformGrid *cachedGrid = vtkUniformGrid::New();
vtkUniformGrid *gridPtr = this->GetAMRGrid( blockIdx );
assert( "pre: grid pointer is NULL" && (gridPtr != NULL) );
cachedGrid->CopyStructure( gridPtr );
std::cout << "Inserting block to cache...";
std::cout.flush();
this->amrCache->InsertAMRBlock( blockIdx, cachedGrid );
return( gridPtr );
}
assert( "Code should never reach here!" && (false) );
return NULL;
}
//------------------------------------------------------------------------------
int vtkAMRBaseReader::RequestData(
vtkInformation* vtkNotUsed(request),
vtkInformationVector** vtkNotUsed(inputVector),
vtkInformationVector* outputVector )
{
vtkInformation *outInf = outputVector->GetInformationObject( 0 );
vtkHierarchicalBoxDataSet *output =
vtkHierarchicalBoxDataSet::SafeDownCast(
outInf->Get( vtkDataObject::DATA_OBJECT() ) );
assert( "pre: output AMR dataset is NULL" && ( output != NULL ) );
// Setup the block request
this->SetupBlockRequest( outInf );
// Initialize counter of the number of blocks at each level.
// This counter is used to compute the block index w.r.t. the
// hierarchical box data-structure. Note that then number of blocks
......@@ -284,11 +372,42 @@ int vtkAMRBaseReader::RequestData(
for( int block=0; block < numBlocks; ++block )
{
int blockIdx = this->BlockMap[ block ];
int level = this->GetBlockLevel( blockIdx );
if( this->IsBlockMine(block) )
{
std::cout << "Loading block: " << this->BlockMap[ block ] << "\n";
std::cout.flush();
this->GetBlock( block, output, idxcounter );
// STEP 0: Get the AMR block
vtkUniformGrid *amrBlock = this->GetAMRBlock( blockIdx );
assert( "pre: AMR block is NULL" && (amrBlock != NULL) );
// STEP 2: Load any point-data
for( int i=0; i < this->GetNumberOfPointArrays(); ++i )
{
if( this->GetPointArrayStatus( this->GetPointArrayName(i) ) )
{
// TODO: load point data
}
}
// STEP 3: Load any cell-data
for( int i=0; i < this->GetNumberOfCellArrays(); ++i )
{
if( this->GetCellArrayStatus( this->GetCellArrayName( i ) ) )
{
this->GetAMRData(
blockIdx,amrBlock,this->GetCellArrayName( i ) );
}
}
output->SetDataSet( level,idxcounter[level],amrBlock );
idxcounter[level]++;
} // END if the block belongs to this process
else
{
output->SetDataSet( idxcounter[level],level,NULL );
idxcounter[level]++;
}
} // END for all blocks
......
......@@ -31,6 +31,9 @@ class vtkMultiProcessController;
class vtkDataArraySelection;
class vtkCallbackCommand;
class vtkIndent;
class vtkAMRDataSetCache;
class vtkUniformGrid;
class vtkDataArray;
class VTK_AMR_EXPORT vtkAMRBaseReader :
public vtkHierarchicalBoxDataSetAlgorithm
......@@ -49,6 +52,7 @@ class VTK_AMR_EXPORT vtkAMRBaseReader :
vtkSetMacro( EnableCaching, int );
vtkGetMacro( EnableCaching, int );
vtkBooleanMacro( EnableCaching, int );
inline bool IsCachingEnabled()const{return((EnableCaching)?true:false);};
// Description:
// Set/Get a multiprocess-controller for reading in parallel.
......@@ -113,6 +117,15 @@ class VTK_AMR_EXPORT vtkAMRBaseReader :
// the block index and total number of processes.
bool IsBlockMine( const int blockIdx );
// Description:
// TODO: implement this
vtkUniformGrid* GetAMRBlock( const int blockIdx );
// Description:
// TODO: implement this
void GetAMRData(
const int blockIdx, vtkUniformGrid *block, const char *fieldName );
// Description:
// Returns the block process ID for the block corresponding to the
// given block index. If this reader instance is serial, i.e., there
......@@ -122,6 +135,14 @@ class VTK_AMR_EXPORT vtkAMRBaseReader :
// processes.
int GetBlockProcessId( const int blockIdx );
// Description:
// Initializes the request of blocks to be loaded. This method checks
// if an upstream request has been issued from a downstream module which
// specifies which blocks are to be loaded, otherwise, it uses the max
// level associated with this reader instance to determine which blocks
// are to be loaded.
void SetupBlockRequest( vtkInformation *outputInfo );
// Description:
// Reads all the metadata from the file. Implemented by concrete classes.
virtual void ReadMetaData() = 0;
......@@ -156,9 +177,12 @@ class VTK_AMR_EXPORT vtkAMRBaseReader :
// Description:
// Loads the block according to the index w.r.t. the generated BlockMap.
virtual void GetBlock(
int index, vtkHierarchicalBoxDataSet *hbds,
vtkstd::vector< int > &idxcounter ) = 0;
virtual vtkUniformGrid* GetAMRGrid( const int blockIdx ) = 0;
// Description:
// Loads the block data
virtual void GetAMRGridData(
const int blockIdx, vtkUniformGrid *block, const char *field ) = 0;
// Description:
// Standard Pipeline methods, subclasses may override this method if needed.
......@@ -198,9 +222,12 @@ class VTK_AMR_EXPORT vtkAMRBaseReader :
vtkMultiProcessController *Controller;
int EnableCaching;
vtkAMRDataSetCache *amrCache;
vtkHierarchicalBoxDataSet *metadata;
//BTX
vtkstd::vector<int> BlockMap;
//ETX
......
......@@ -18,6 +18,7 @@
#include "vtkPointData.h"
#include "vtkCellData.h"
#include "vtkUniformGrid.h"
#include "vtkMultiBlockDataSet.h"
#include <cassert>
......@@ -26,19 +27,13 @@ vtkStandardNewMacro( vtkAMRDataSetCache );
vtkAMRDataSetCache::vtkAMRDataSetCache()
{
this->Size = 100; // Cache 100 blocks by default
this->Cache = vtkMultiBlockDataSet::New();
}
//------------------------------------------------------------------------------
vtkAMRDataSetCache::~vtkAMRDataSetCache()
{
vtkstd::map< int, vtkUniformGrid* >::iterator iter;
for( iter = this->Cache.begin(); iter != this->Cache.end(); ++iter )
{
if( iter->second != NULL )
iter->second->Delete();
}
this->Cache.clear();
this->Cache->Delete();
}
//------------------------------------------------------------------------------
......@@ -55,7 +50,8 @@ void vtkAMRDataSetCache::InsertAMRBlock(
if( !this->HasAMRBlock( compositeIdx ) )
{
this->Cache[ compositeIdx ] = amrGrid;
this->Cache->SetBlock( compositeIdx, amrGrid );
this->history.insert( compositeIdx );
}
}
......@@ -140,7 +136,10 @@ vtkDataArray* vtkAMRDataSetCache::GetAMRBlockPointData(
vtkUniformGrid* vtkAMRDataSetCache::GetAMRBlock( const int compositeIdx )
{
if( this->HasAMRBlock( compositeIdx ) )
return this->Cache[ compositeIdx ];
{
return( vtkUniformGrid::SafeDownCast(
this->Cache->GetBlock( compositeIdx ) ) );
}
return NULL;
}
......@@ -152,7 +151,10 @@ bool vtkAMRDataSetCache::HasAMRBlockCellData(
if( this->HasAMRBlock( compositeIdx ) )
{
vtkCellData *CD = this->Cache[ compositeIdx ]->GetCellData();
vtkUniformGrid *gridPtr = this->GetAMRBlock( compositeIdx );
assert( "pre: cachedk block is NULL!" && (gridPtr != NULL) );
vtkCellData *CD = gridPtr->GetCellData();
assert( "pre: cell data is NULL" && (CD != NULL) );
if( CD->HasArray( name ) )
......@@ -171,7 +173,10 @@ bool vtkAMRDataSetCache::HasAMRBlockPointData(
if( this->HasAMRBlock( compositeIdx ) )
{
vtkPointData *PD = this->Cache[ compositeIdx ]->GetPointData();
vtkUniformGrid *gridPtr = this->GetAMRBlock( compositeIdx );
assert( "pre: cachedk block is NULL!" && (gridPtr != NULL) );
vtkPointData *PD = gridPtr->GetPointData();
assert( "pre: point data is NULL" && (PD != NULL) );
if( PD->HasArray( name ) )
......@@ -185,7 +190,10 @@ bool vtkAMRDataSetCache::HasAMRBlockPointData(
//------------------------------------------------------------------------------
bool vtkAMRDataSetCache::HasAMRBlock(const int compositeIdx )
{
if( this->Cache.find( compositeIdx) != this->Cache.end() )
if( this->history.empty( ) )
return false;
if( this->history.find( compositeIdx) != this->history.end() )
return true;
return false;
}
......@@ -24,11 +24,12 @@
#define VTKAMRDATASETCACHE_H_
#include "vtkObject.h"
#include <vtkstd/map> // For STL map
#include <set> // For STL set
class vtkUniformGrid;
class vtkAMRBox;
class vtkDataArray;
class vtkMultiBlockDataSet;
class VTK_AMR_EXPORT vtkAMRDataSetCache : public vtkObject
{
......@@ -37,11 +38,6 @@ class VTK_AMR_EXPORT vtkAMRDataSetCache : public vtkObject
vtkTypeMacro( vtkAMRDataSetCache, vtkObject );
void PrintSelf( std::ostream &os, vtkIndent indent );
// Description:
// Set/Get Size of the cache.
vtkSetMacro( Size, int );
vtkGetMacro( Size, int );
// Description:
// Inserts an AMR block to the cache
void InsertAMRBlock(const int compositeIdx,vtkUniformGrid *amrGrid);
......@@ -95,8 +91,8 @@ class VTK_AMR_EXPORT vtkAMRDataSetCache : public vtkObject
vtkAMRDataSetCache();
virtual ~vtkAMRDataSetCache();
int Size;
vtkstd::map< int, vtkUniformGrid* > Cache;
vtkMultiBlockDataSet *Cache;
std::set< int > history;
private:
vtkAMRDataSetCache( const vtkAMRDataSetCache& ); // Not implemented
......
......@@ -368,84 +368,64 @@ int vtkAMREnzoReader::FillMetaData( )
}
//-----------------------------------------------------------------------------
void vtkAMREnzoReader::GetBlock(
int index, vtkHierarchicalBoxDataSet *hbds,
vtkstd::vector< int > &idxcounter)
vtkUniformGrid* vtkAMREnzoReader::GetAMRGrid( const int blockIdx )
{
assert( "pre: Internal Enzo Reader is NULL" && (this->Internal != NULL) );
assert( "pre: Output AMR dataset is NULL" && (hbds != NULL) );
this->Internal->ReadMetaData();
int blockIdx = this->BlockMap[ index ];
int N = this->Internal->Blocks.size();
assert( "block index out-of-bounds!" &&
(blockIdx+1 >= 0) && (blockIdx+1 < N ) );
// this->Internal->Blocks includes a pseudo block --- the root as block #0
vtkEnzoReaderBlock &theBlock = this->Internal->Blocks[ blockIdx+1 ];
int level = theBlock.Level;
double blockMin[3];
double blockMax[3];
double spacings[3];
for( int i=0; i < 3; ++i )
{
blockMin[i] = theBlock.MinBounds[i];
blockMax[i] = theBlock.MaxBounds[i];
spacings[i] = ( theBlock.BlockNodeDimensions[i] > 1 )?
(blockMax[i]-blockMin[i])/(theBlock.BlockNodeDimensions[i]-1.0) : 1.0;
blockMin[ i ] = theBlock.MinBounds[ i ];
blockMax[ i ] = theBlock.MaxBounds[ i ];
spacings[ i ] = (theBlock.BlockNodeDimensions[i] > 1)?
(blockMax[i]-blockMin[i])/(theBlock.BlockNodeDimensions[i]-1.0) : 1.0;
}
vtkUniformGrid *ug = vtkUniformGrid::New();
ug->SetDimensions( theBlock.BlockNodeDimensions );
ug->SetOrigin( blockMin[0],blockMin[1],blockMin[2] );
ug->SetSpacing( spacings[0],spacings[1],spacings[2] );
int numAttrs = static_cast< int >(this->Internal->BlockAttributeNames.size());
for( int i=0; i < numAttrs; ++i )
{
if(this->GetCellArrayStatus(
this->Internal->BlockAttributeNames[ i ].c_str()))
{
this->Internal->GetBlockAttribute(
this->Internal->BlockAttributeNames[ i ].c_str(),
blockIdx, ug );
if( this->ConvertToCGS == 1 )
{
double conversionFactor = this->GetConversionFactor(
this->Internal->BlockAttributeNames[ i ].c_str() );
if( conversionFactor != 1.0 )
{
vtkDataArray *data = ug->GetCellData()->GetArray(
this->Internal->BlockAttributeNames[ i ].c_str() );
vtkIdType numTuples = data->GetNumberOfTuples();
for( vtkIdType t=0; t < numTuples; ++t )
{
int numComp = data->GetNumberOfComponents();
for( int c=0; c < numComp; ++c )
{
double f = data->GetComponent( t, c );
data->SetComponent( t, c, f*conversionFactor );
} // END for all components
} // END for all tuples
}
} // END if convert to CGS
}
ug->SetOrigin( blockMin[0], blockMin[1], blockMin[2] );
ug->SetSpacing( spacings[0], spacings[1], spacings[2] );
return( ug );
}
}
//-----------------------------------------------------------------------------
void vtkAMREnzoReader::GetAMRGridData(
const int blockIdx, vtkUniformGrid *block, const char *field)
{
assert( "pre: AMR block is NULL" && (block != NULL));
hbds->SetDataSet(level,idxcounter[level],ug);
ug->Delete();
idxcounter[ level ]++;
this->Internal->GetBlockAttribute( field, blockIdx, block );
if( this->ConvertToCGS == 1 )
{
double conversionFactor = this->GetConversionFactor(field);
if( conversionFactor != 1.0 )
{
vtkDataArray *data = block->GetCellData()->GetArray( field );
assert( "pre: data array is NULL!" && (data != NULL) );
vtkIdType numTuples = data->GetNumberOfTuples();
for( vtkIdType t=0; t < numTuples; ++t )
{
int numComp = data->GetNumberOfComponents();
for( int c=0; c < numComp; ++c )
{
double f = data->GetComponent( t, c );
data->SetComponent( t, c, f*conversionFactor );
} // END for all components
} // END for all tuples
} // END if the conversion factor is not 1.0
} // END if conversion to CGS units is requested
}
//-----------------------------------------------------------------------------
void vtkAMREnzoReader::SetUpDataArraySelections()
{
......
......@@ -101,10 +101,13 @@ class VTK_AMR_EXPORT vtkAMREnzoReader : public vtkAMRBaseReader
int FillMetaData( );
// Description:
// See vtkAMRBaseReader::GetBlock
void GetBlock(
int index, vtkHierarchicalBoxDataSet *hbds,
vtkstd::vector< int > &idxcounter);
// See vtkAMRBaseReader::GetAMRGrid
vtkUniformGrid* GetAMRGrid( const int blockIdx );
// Description:
// See vtkAMRBaseReader::GetAMRGridData
void GetAMRGridData(
const int blockIdx, vtkUniformGrid *block, const char *field);
// Description:
// See vtkAMRBaseReader::SetUpDataArraySelections
......
......@@ -126,7 +126,7 @@ int vtkAMRFlashReader::GetBlockLevel( const int blockIdx )
vtkErrorMacro( "Block Index (" << blockIdx << ") is out-of-bounds!" );
return( -1 );
}
return( this->Internal->Blocks[ blockIdx ].Level );
return( this->Internal->Blocks[ blockIdx ].Level-1 );
}
//-----------------------------------------------------------------------------
......@@ -194,49 +194,35 @@ int vtkAMRFlashReader::FillMetaData( )
}
//-----------------------------------------------------------------------------
void vtkAMRFlashReader::GetBlock(
int index, vtkHierarchicalBoxDataSet *hbds,
vtkstd::vector< int > &idxcounter)
vtkUniformGrid* vtkAMRFlashReader::GetAMRGrid( const int blockIdx )
{
assert( "pre: Internal Flash Reader is NULL" && (this->Internal != NULL) );
assert( "pre: Output AMR dataset is NULL" && (hbds != NULL) );
this->Internal->ReadMetaData();
int blockIdx = this->BlockMap[ index ];
// Start numbering levels from 0!
int level = this->Internal->Blocks[ blockIdx ].Level-1;
double blockMin[3];
double blockMax[3];
double spacings[3];
for( int i=0; i < 3; ++i )
{
blockMin[i] = this->Internal->Blocks[ blockIdx ].MinBounds[i];
blockMax[i] = this->Internal->Blocks[ blockIdx ].MaxBounds[i];
spacings[i] = (this->Internal->BlockGridDimensions[i] > 1)?
(blockMax[i]-blockMin[i])/(this->Internal->BlockGridDimensions[i]-1.0):1.0;
blockMin[i] = this->Internal->Blocks[ blockIdx ].MinBounds[ i ];
blockMax[i] = this->Internal->Blocks[ blockIdx ].MaxBounds[ i ];
spacings[i] = (this->Internal->BlockGridDimensions[i]>1)?
(blockMax[i]-blockMin[i])/
(this->Internal->BlockGridDimensions[i]-1.0) : 1.0;
}
vtkUniformGrid *ug = vtkUniformGrid::New();
ug->SetDimensions( this->Internal->BlockGridDimensions );
ug->SetOrigin( blockMin[0], blockMin[1], blockMin[2] );
ug->SetSpacing( spacings );
return( ug );
}
int numAttrs = static_cast< int >( this->Internal->AttributeNames.size() );
for( int i=0; i < numAttrs; ++i )
{
if( this->GetCellArrayStatus(
this->Internal->AttributeNames[i].c_str() ) )
{
this->Internal->GetBlockAttribute(
this->Internal->AttributeNames[i].c_str(),blockIdx, ug );
}
}
hbds->SetDataSet(level,idxcounter[level],ug);
ug->Delete();
idxcounter[ level ]++;
//-----------------------------------------------------------------------------
void vtkAMRFlashReader::GetAMRGridData(
const int blockIdx, vtkUniformGrid *block, const char *field)
{
assert( "pre: AMR block is NULL" && (block != NULL) );
this->Internal->GetBlockAttribute( field, blockIdx, block );
}
//-----------------------------------------------------------------------------
......
......@@ -65,11 +65,20 @@ class VTK_AMR_EXPORT vtkAMRFlashReader : public vtkAMRBaseReader
// See vtkAMRBaseReader::FillMetaData
int FillMetaData( );
// Description:
// See vtkAMRBaseReader::GetAMRGrid
vtkUniformGrid* GetAMRGrid( const int blockIdx );
// Description:
// See vtkAMRBaseReader::GetAMRGridData
void GetAMRGridData(
const int blockIdx, vtkUniformGrid *block, const char *field);
// Description:
// See vtkAMRBaseReader::GetBlock