Commit 54f52ce1 authored by Joachim Pouderoux's avatar Joachim Pouderoux

Enhance and optimize Xdmf2 reader and writer to support static meshes.

Reader now caches previous timestep dataset geometry and topology and do not
read them again if new dataset use the same heavy datapath.

Writer has a new property MeshStaticOverTime to specify that the mesh
is static. If so, topology and geometry heavy data will be produced once at t=0
and will be reused for all time steps.
parent 922d08c0
......@@ -43,6 +43,8 @@
#include <deque>
#include <cassert>
#include <libxml/tree.h>
using namespace xdmf2;
static void vtkScaleExtents(int in_exts[6], int out_exts[6], int stride[3])
......@@ -137,7 +139,7 @@ vtkDataObject* vtkXdmfHeavyData::ReadData()
}
//----------------------------------------------------------------------------
vtkDataObject* vtkXdmfHeavyData::ReadData(XdmfGrid* xmfGrid)
vtkDataObject* vtkXdmfHeavyData::ReadData(XdmfGrid* xmfGrid, int blockId)
{
if (!xmfGrid || xmfGrid->GetGridType() == XDMF_GRID_UNSET)
{
......@@ -151,7 +153,7 @@ vtkDataObject* vtkXdmfHeavyData::ReadData(XdmfGrid* xmfGrid)
{
// grid is a temporal collection, pick the sub-grid with matching time and
// process that.
return this->ReadTemporalCollection(xmfGrid);
return this->ReadTemporalCollection(xmfGrid, blockId);
}
else if (gridType == XDMF_GRID_COLLECTION ||
gridType == XDMF_GRID_TREE)
......@@ -160,7 +162,7 @@ vtkDataObject* vtkXdmfHeavyData::ReadData(XdmfGrid* xmfGrid)
}
// grid is a primitive grid, so read the data.
return this->ReadUniformData(xmfGrid);
return this->ReadUniformData(xmfGrid, blockId);
}
//----------------------------------------------------------------------------
......@@ -189,7 +191,7 @@ vtkDataObject* vtkXdmfHeavyData::ReadComposite(XdmfGrid* xmfComposite)
if (!child_is_leaf || !distribute_leaf_nodes ||
(number_of_leaf_nodes % this->NumberOfPieces) == this->Piece)
{
vtkDataObject* childDO = this->ReadData(xmfChild);
vtkDataObject* childDO = this->ReadData(xmfChild, cc);
if (childDO)
{
multiBlock->SetBlock(cc, childDO);
......@@ -204,7 +206,7 @@ vtkDataObject* vtkXdmfHeavyData::ReadComposite(XdmfGrid* xmfComposite)
//----------------------------------------------------------------------------
vtkDataObject* vtkXdmfHeavyData::ReadTemporalCollection(
XdmfGrid* xmfTemporalCollection)
XdmfGrid* xmfTemporalCollection, int blockId)
{
assert(xmfTemporalCollection->GetGridType() & XDMF_GRID_COLLECTION &&
xmfTemporalCollection->GetCollectionType() == XDMF_GRID_COLLECTION_TEMPORAL
......@@ -254,7 +256,7 @@ vtkDataObject* vtkXdmfHeavyData::ReadTemporalCollection(
std::deque<XdmfGrid*>::iterator iter;
for (iter = valid_children.begin(); iter != valid_children.end(); ++iter)
{
vtkDataObject* childDO = this->ReadData(*iter);
vtkDataObject* childDO = this->ReadData(*iter, blockId);
if (childDO)
{
child_data_objects.push_back(childDO);
......@@ -286,7 +288,7 @@ vtkDataObject* vtkXdmfHeavyData::ReadTemporalCollection(
//----------------------------------------------------------------------------
// Read a non-composite grid. Note here uniform has nothing to do with
// vtkUniformGrid but to what Xdmf's GridType="Uniform".
vtkDataObject* vtkXdmfHeavyData::ReadUniformData(XdmfGrid* xmfGrid)
vtkDataObject* vtkXdmfHeavyData::ReadUniformData(XdmfGrid* xmfGrid, int blockId)
{
assert(xmfGrid->IsUniform() && "Input must be a uniform xdmf grid.");
......@@ -300,6 +302,79 @@ vtkDataObject* vtkXdmfHeavyData::ReadUniformData(XdmfGrid* xmfGrid)
// Read heavy data for grid geometry/topology. This does not read any
// data-arrays. They are read explicitly.
XdmfTopology* topo = xmfGrid->GetTopology();
XdmfGeometry* geom = xmfGrid->GetGeometry();
xmlChar* filePtr;
bool caching = true;
XdmfDOM* topoDom = topo->GetDOM();
XdmfXmlNode topoNode = topo->GetElement();
XdmfXmlNode topoNodeDataItem = topoDom->FindElement("DataItem", 0, topoNode);
std::string topoFilename = "NULL";
if (topoNodeDataItem && caching)
{
filePtr = topoNodeDataItem->children->content;
if (filePtr != NULL)
{
topoFilename = reinterpret_cast<char*>(filePtr);
}
else
{
vtkErrorWithObjectMacro(this->Reader, << "Cannot find DataItem element in topology xml, no caching possible");
caching = false;
}
}
else
{
caching = false;
}
XdmfDOM* geomDom = geom->GetDOM();
XdmfXmlNode geomNode = geom->GetElement();
XdmfXmlNode geomNodeDataItem = geomDom->FindElement("DataItem", 0, geomNode);
std::string geomFilename = "NULL";
if (geomNodeDataItem && caching)
{
filePtr = geomNodeDataItem->children->content;
if (filePtr != NULL)
{
geomFilename = reinterpret_cast<char*>(filePtr);
}
else
{
vtkErrorWithObjectMacro(this->Reader, << "Cannot find DataItem element in geometry xml, no caching possible");
caching = false;
}
}
else
{
caching = false;
}
vtkXdmfReader::XdmfReaderCachedData& cache =
vtkXdmfReader::SafeDownCast(this->Reader)->GetDataSetCache();
vtkXdmfReader::XdmfDataSetTopoGeoPath cachedData = cache[blockId];
if (caching &&
(cachedData.topologyPath == topoFilename) && (cachedData.geometryPath == geomFilename))
{
vtkDataSet* ds = vtkDataSet::SafeDownCast(
vtkDataObjectTypes::NewDataObject(cachedData.dataset->GetDataObjectType()));
ds->ShallowCopy(cachedData.dataset);
this->ReadAttributes(ds, xmfGrid);
return ds;
}
if (caching)
{
cachedData.topologyPath = topoFilename;
cachedData.geometryPath = geomFilename;
if (cache[blockId].dataset != NULL)
{
cache[blockId].dataset->Delete();
cache[blockId].dataset = NULL;
}
}
XdmfInt32 status = xmfGrid->Update();
if (status == XDMF_FAIL)
{
......@@ -310,31 +385,36 @@ vtkDataObject* vtkXdmfHeavyData::ReadUniformData(XdmfGrid* xmfGrid)
switch (vtk_data_type)
{
case VTK_UNIFORM_GRID:
dataObject = this->RequestImageData(xmfGrid, true);
break;
case VTK_UNIFORM_GRID:
dataObject = this->RequestImageData(xmfGrid, true);
break;
case VTK_IMAGE_DATA:
dataObject = this->RequestImageData(xmfGrid, false);
break;
case VTK_IMAGE_DATA:
dataObject = this->RequestImageData(xmfGrid, false);
break;
case VTK_STRUCTURED_GRID:
dataObject = this->RequestStructuredGrid(xmfGrid);
break;
case VTK_STRUCTURED_GRID:
dataObject = this->RequestStructuredGrid(xmfGrid);
break;
case VTK_RECTILINEAR_GRID:
dataObject = this->RequestRectilinearGrid(xmfGrid);
break;
case VTK_RECTILINEAR_GRID:
dataObject = this->RequestRectilinearGrid(xmfGrid);
break;
case VTK_UNSTRUCTURED_GRID:
dataObject = this->ReadUnstructuredGrid(xmfGrid);
break;
case VTK_UNSTRUCTURED_GRID:
dataObject = this->ReadUnstructuredGrid(xmfGrid);
break;
default:
// un-handled case.
return 0;
default:
// un-handled case.
return 0;
}
if (caching)
{
cache[blockId].dataset = vtkDataSet::SafeDownCast(dataObject);
dataObject->Register(0);
}
return dataObject;
}
......
......@@ -55,7 +55,7 @@ public:
~vtkXdmfHeavyData();
// Description:
vtkDataObject* ReadData(xdmf2::XdmfGrid* xmfGrid);
vtkDataObject* ReadData(xdmf2::XdmfGrid* xmfGrid, int blockId = -1);
// Description:
vtkDataObject* ReadData();
......@@ -70,10 +70,11 @@ public:
// of points possible.
static int GetNumberOfPointsPerCell(int vtk_cell_type);
private:
// Description:
// Read a temporal collection.
vtkDataObject* ReadTemporalCollection(xdmf2::XdmfGrid* xmfTemporalCollection);
vtkDataObject* ReadTemporalCollection(xdmf2::XdmfGrid* xmfTemporalCollection, int blockId);
// Description:
// Read a spatial-collection or a tree.
......@@ -82,7 +83,7 @@ private:
// Description:
// Read a non-composite grid. Note here uniform has nothing to do with
// vtkUniformGrid but to what Xdmf's GridType="Uniform".
vtkDataObject* ReadUniformData(xdmf2::XdmfGrid* xmfGrid);
vtkDataObject* ReadUniformData(xdmf2::XdmfGrid* xmfGrid, int blockId);
// Description:
// Reads the topology and geometry for an unstructured grid. Does not read any
......@@ -156,7 +157,6 @@ private:
// Creates a new dataset with egdes selected by the set, extracting them from
// the input dataset.
vtkDataSet* ExtractEdges(xdmf2::XdmfSet* xmfSet, vtkDataSet* dataSet);
};
#endif
......@@ -19,6 +19,7 @@
#include "vtkCharArray.h"
#include "vtkCompositeDataPipeline.h"
#include "vtkDataObjectTypes.h"
#include "vtkDataSet.h"
#include "vtkExtentTranslator.h"
#include "vtkInformation.h"
#include "vtkInformationVector.h"
......@@ -116,6 +117,8 @@ vtkXdmfReader::~vtkXdmfReader()
delete this->CellArraysCache;
delete this->GridsCache;
delete this->SetsCache;
this->ClearDataSetCache();
}
//----------------------------------------------------------------------------
......@@ -318,9 +321,15 @@ int vtkXdmfReader::RequestInformation(vtkInformation *, vtkInformationVector **,
// * Publish the SIL which provides information about the grid hierarchy.
outInfo->Set(vtkDataObject::SIL(), domain->GetSIL());
const std::map<int, XdmfFloat64>& ts = domain->GetTimeStepsRev();
std::vector<double> time_steps(ts.size());
std::map<int, XdmfFloat64>::const_iterator it = ts.begin();
for (int i = 0; it != ts.end(); i++, ++it)
time_steps[i] = it->second;
// * Publish time information.
std::vector<double> time_steps(domain->GetTimeSteps().begin(),
domain->GetTimeSteps().end());
/*std::vector<double> time_steps(domain->GetTimeSteps().begin(),
domain->GetTimeSteps().end());*/
if (time_steps.size() > 0)
{
......@@ -386,6 +395,10 @@ int vtkXdmfReader::RequestData(vtkInformation *, vtkInformationVector **,
}
this->LastTimeIndex = this->ChooseTimeStep(outInfo);
if (this->LastTimeIndex == 0)
{
this->ClearDataSetCache();
}
vtkXdmfHeavyData dataReader(this->XdmfDocument->GetActiveDomain(), this);
dataReader.Piece = updatePiece;
......@@ -615,3 +628,25 @@ vtkGraph* vtkXdmfReader::GetSIL()
}
return 0;
}
//----------------------------------------------------------------------------
void vtkXdmfReader::ClearDataSetCache()
{
XdmfReaderCachedData::iterator it = this->DataSetCache.begin();
while (it != this->DataSetCache.end())
{
if (it->second.dataset != NULL)
{
it->second.dataset->Delete();
}
++it;
}
this->DataSetCache.clear();
}
//----------------------------------------------------------------------------
vtkXdmfReader::XdmfReaderCachedData& vtkXdmfReader::GetDataSetCache()
{
return this->DataSetCache;
}
......@@ -35,6 +35,7 @@
#include "vtkIOXdmf2Module.h" // For export macro
#include "vtkDataReader.h"
#include <map> // for caching
class vtkXdmfArraySelection;
class vtkXdmfDocument;
......@@ -140,6 +141,21 @@ public:
virtual vtkGraph* GetSIL();
//BTX
class XdmfDataSetTopoGeoPath
{
public:
XdmfDataSetTopoGeoPath() : dataset(0), topologyPath(), geometryPath() {}
vtkDataSet* dataset;
std::string topologyPath;
std::string geometryPath;
};
typedef std::map<int, XdmfDataSetTopoGeoPath> XdmfReaderCachedData;
// Description
// Get the data set cache
XdmfReaderCachedData& GetDataSetCache();
protected:
vtkXdmfReader();
~vtkXdmfReader();
......@@ -182,11 +198,16 @@ protected:
vtkXdmfArraySelection* SetsCache;
int SILUpdateStamp;
XdmfReaderCachedData DataSetCache;
private:
// Description:
// Prepares the XdmfDocument.
bool PrepareDocument();
void ClearDataSetCache();
// Description:
// Returns the time-step index requested using the UPDATE_TIME_STEPS from the
// information.
......
......@@ -325,7 +325,13 @@ int vtkXdmfDomain::GetVTKDataType(XdmfGrid* xmfGrid)
//----------------------------------------------------------------------------
int vtkXdmfDomain::GetIndexForTime(double time)
{
std::set<XdmfFloat64>::iterator iter = this->TimeSteps.upper_bound(time);
std::map<XdmfFloat64, int>::const_iterator iter = this->TimeSteps.find(time);
if (iter != this->TimeSteps.end())
{
return iter->second;
}
iter = this->TimeSteps.upper_bound(time);
if (iter == this->TimeSteps.begin())
{
// The requested time step is before any available time. We will use it by
......@@ -337,7 +343,7 @@ int vtkXdmfDomain::GetIndexForTime(double time)
iter--;
}
std::set<XdmfFloat64>::iterator iter2 = this->TimeSteps.begin();
std::map<XdmfFloat64, int>::iterator iter2 = this->TimeSteps.begin();
int counter = 0;
while (iter2 != iter)
{
......@@ -641,7 +647,12 @@ void vtkXdmfDomain::CollectNonLeafMetaData(XdmfGrid* xmfGrid,
XdmfTime* xmfTime = xmfGrid->GetTime();
if (xmfTime && xmfTime->GetTimeType() != XDMF_TIME_UNSET)
{
this->TimeSteps.insert(xmfTime->GetValue());
int step = static_cast<int>(this->TimeSteps.size());
if (this->TimeSteps.find(xmfTime->GetValue()) == this->TimeSteps.end())
{
this->TimeSteps[xmfTime->GetValue()] = step;//this->TimeSteps.insert(xmfTime->GetValue());
this->TimeStepsRev[step] = xmfTime->GetValue();
}
}
}
}
......@@ -728,7 +739,12 @@ void vtkXdmfDomain::CollectLeafMetaData(XdmfGrid* xmfGrid, vtkIdType silParent)
XdmfTime* xmfTime = xmfGrid->GetTime();
if (xmfTime && xmfTime->GetTimeType() != XDMF_TIME_UNSET)
{
this->TimeSteps.insert(xmfTime->GetValue());
int step = static_cast<int>(this->TimeSteps.size());
if (this->TimeSteps.find(xmfTime->GetValue()) == this->TimeSteps.end())
{
this->TimeSteps[xmfTime->GetValue()] = step;//this->TimeSteps.insert(xmfTime->GetValue());
this->TimeStepsRev[step] = xmfTime->GetValue();
}
}
}
......
......@@ -203,8 +203,9 @@ private:
vtkXdmfArraySelection* CellArrays;
vtkXdmfArraySelection* Grids;
vtkXdmfArraySelection* Sets;
std::set<XdmfFloat64> TimeSteps; //< Only discrete timesteps are currently
std::map<XdmfFloat64, int> TimeSteps; //< Only discrete timesteps are currently
// supported.
std::map<int, XdmfFloat64> TimeStepsRev;
public:
//---------------------------------------------------------------------------
......@@ -244,8 +245,10 @@ public:
//---------------------------------------------------------------------------
// Description:
// Returns the timesteps.
const std::set<XdmfFloat64>& GetTimeSteps()
const std::map<XdmfFloat64, int>& GetTimeSteps()
{ return this->TimeSteps; }
const std::map<int,XdmfFloat64>& GetTimeStepsRev()
{ return this->TimeStepsRev; }
//---------------------------------------------------------------------------
// Description:
......@@ -257,8 +260,8 @@ public:
// Returns the time value at the given index.
XdmfFloat64 GetTimeForIndex(int index)
{
std::set<XdmfFloat64>::iterator iter;
int cc=0;
std::map<int, XdmfFloat64>::iterator iter = this->TimeStepsRev.find(index);
/*int cc=0;
for (iter = this->TimeSteps.begin(); iter != this->TimeSteps.end();
iter++, cc++)
{
......@@ -266,7 +269,9 @@ public:
{
return *iter;
}
}
}*/
if (iter != this->TimeStepsRev.end())
return iter->second;
// invalid index.
return 0.0;
}
......
This diff is collapsed.
......@@ -27,6 +27,8 @@
#include "vtkDataObjectAlgorithm.h"
#include <vector> // Needed for private members
class vtkExecutive;
class vtkCompositeDataSet;
......@@ -42,7 +44,10 @@ namespace xdmf2
{
class XdmfArray;
class XdmfDOM;
class XdmfElement;
class XdmfGrid;
class XdmfGeometry;
class XdmfTopology;
}
class VTKIOXDMF2_EXPORT vtkXdmfWriter : public vtkDataObjectAlgorithm
......@@ -82,6 +87,7 @@ public:
// Description:
// Topology Geometry and Attribute arrays smaller than this are written in line into the XML.
// Default is 100.
// Node: LightDataLimit is forced to 1 when MeshStaticOverTime is TRUE.
vtkSetMacro(LightDataLimit, int);
vtkGetMacro(LightDataLimit, int);
......@@ -93,6 +99,15 @@ public:
vtkGetMacro(WriteAllTimeSteps, int);
vtkBooleanMacro(WriteAllTimeSteps, int);
// Description:
// Set of get the flag that specify if input mesh is static over time.
// If so, the mesh topology and geometry heavy data will be written only once.
// Default if FALSE.
// Note: this mode requires that all data is dumped in the heavy data file.
vtkSetMacro(MeshStaticOverTime, bool);
vtkGetMacro(MeshStaticOverTime, bool);
vtkBooleanMacro(MeshStaticOverTime, bool);
// Description:
// Called in parallel runs to identify the portion this process is responsible for
// TODO: respect this
......@@ -143,24 +158,36 @@ protected:
vtkIdType rank, vtkIdType *dims,
int AllocStrategy, const char *heavyprefix);
virtual void SetupDataArrayXML(xdmf2::XdmfElement*, xdmf2::XdmfArray*) const;
char *FileName;
char *HeavyDataFileName;
char *HeavyDataGroupName;
std::string WorkingDirectory;
std::string BaseFileName;
int LightDataLimit;
int WriteAllTimeSteps;
int NumberOfTimeSteps;
double CurrentTime;
int CurrentTimeIndex;
int CurrentBlockIndex;
int UnlabelledDataArrayId;
int Piece;
int NumberOfPieces;
bool MeshStaticOverTime;
xdmf2::XdmfDOM *DOM;
xdmf2::XdmfGrid *TopTemporalGrid;
vtkXdmfWriterDomainMemoryHandler *DomainMemoryHandler;
std::vector<xdmf2::XdmfTopology*> TopologyAtT0;
std::vector<xdmf2::XdmfGeometry*> GeometryAtT0;
private:
vtkXdmfWriter(const vtkXdmfWriter&); // Not implemented
void operator=(const vtkXdmfWriter&); // Not implemented
......
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