...
 
Commits (2)
......@@ -31,6 +31,7 @@ set(ENABLE_CATALYST @ENABLE_CATALYST@)
set(ENABLE_CATALYST_PYTHON @ENABLE_CATALYST_PYTHON@)
set(ENABLE_LIBSIM @ENABLE_LIBSIM@)
set(ENABLE_ADIOS1 @ENABLE_ADIOS1@)
set(ENABLE_HDF5 @ENABLE_HDF5@)
set(ENABLE_CONDUIT @ENABLE_CONDUIT@)
set(ENABLE_VTK_GENERIC_ARRAYS @ENABLE_VTK_GENERIC_ARRAYS@)
set(ENABLE_VTK_ACCELERATORS @ENABLE_VTK_ACCELERATORS@)
......
if(ENABLE_HDF5 STREQUAL AUTO)
find_package(HDF5 COMPONENTS C)
elseif(ENABLE_HDF5)
find_package(HDF5 REQUIRED COMPONENTS C)
endif()
message(STATUS "HDF5 found? ${HDF5_FOUND} ${HDF5_INCLUDE_DIRS} ${HDF5_INCLUDE_DIR}")
if(HDF5_FOUND)
add_library(sDataElevator INTERFACE)
target_link_libraries(sDataElevator INTERFACE ${HDF5_LIBRARIES})
target_include_directories(sDataElevator SYSTEM INTERFACE ${HDF5_INCLUDE_DIRS})
install(TARGETS sDataElevator EXPORT sDataElevator)
install(EXPORT sDataElevator DESTINATION lib/cmake EXPORT_LINK_INTERFACE_LIBRARIES)
endif()
......@@ -20,6 +20,10 @@ cmake_dependent_option(ENABLE_ADIOS1
"Enable analysis methods that use ADIOS 1" OFF
"ENABLE_SENSEI" OFF)
cmake_dependent_option(ENABLE_HDF5
"Enable analysis methods that use HDF5" OFF
"ENABLE_SENSEI" OFF)
cmake_dependent_option(ENABLE_CONDUIT
"Enable analysis methods that use Conduit" OFF
"ENABLE_SENSEI" OFF)
......@@ -65,6 +69,7 @@ message(STATUS "ENABLE_VTK_GENERIC_ARRAYS=${ENABLE_VTK_GENERIC_ARRAYS}")
message(STATUS "ENABLE_CATALYST=${ENABLE_CATALYST}")
message(STATUS "ENABLE_CATALYST_PYTHON=${ENABLE_CATALYST}")
message(STATUS "ENABLE_ADIOS1=${ENABLE_ADIOS1}")
message(STATUS "ENABLE_HDF5=${ENABLE_HDF5}")
message(STATUS "ENABLE_CONDUIT=${ENABLE_CONDUIT}")
message(STATUS "ENABLE_LIBSIM=${ENABLE_LIBSIM}")
message(STATUS "ENABLE_VTK_IO=${ENABLE_VTK_IO}")
......
......@@ -9,6 +9,7 @@ include(build)
include(threads)
include(mpi)
include(adios)
include(hdf5)
include(vtk)
include(libsim)
include(catalyst)
......
......@@ -41,12 +41,14 @@ information see our [SC16 paper](http://dl.acm.org/citation.cfm?id=3015010).
| DataAdaptor | Base class declaring data adaptor API |
| VTKDataAdaptor | Implementation for use with VTK data sets. This adaptor can be used to pass VTK data sets from the simulation to the Analysis. |
| ADIOS1DataAdaptor | Implementation that serves up data from ADIOS 1. For use in an ADIOS 1 End point. |
| HDF5DataAdaptor | Implementation that serves up data from HDF5. For use in a HDF5 End point. |
#### AnalysisAdaptors
| Class | Description |
|-------------------------|-------------|
| AnalysisAdaptor | Base class declaring analysis adaptor API |
| ADIOS1AnalysisAdaptor | Implementation for using ADIOS 1 from your simulation. |
| ADIOS1AnalysisAdaptor | Implementation for using ADIOS 1 from your simulation. |
| HDF5AnalysisAdaptor | Implementation for using HDF5 from your simulation. |
| LibsimAnalysisAdaptor | Implementation for using Libsim from your simulation. |
| CatalystAnalysisAdaptor | Implementation for using Catalyst from your simulaiton. |
| Autocorrelation | Implementation that computes [autocorrelation](https://en.wikipedia.org/wiki/Autocorrelation) |
......@@ -110,6 +112,7 @@ $ make install
| `ENABLE_CATALYST` | OFF | Enables the Catalyst analysis adaptor. Depends on ParaView Catalyst. Set `ParaView_DIR`. |
| `ENABLE_CATALYST_PYTHON` | OFF | Enables Python features of the Catalyst analysis adaptor. |
| `ENABLE_ADIOS1` | OFF | Enables ADIOS 1 adaptors and endpoints. Set `ADIOS_DIR`. |
| `ENABLE_HDF5` | OFF | Enables HDF5 adaptors and endpoints. Set `HDF5_DIR`. |
| `ENABLE_LIBSIM` | OFF | Enables Libsim data and analysis adaptors. Requires Libsim. Set `VTK_DIR` and `LIBSIM_DIR`. |
| `ENABLE_VTK_IO` | OFF | Enables adaptors to write to VTK XML format. |
| `ENABLE_VTK_MPI` | OFF | Enables MPI parallel VTK filters, such as parallel I/O. |
......
......@@ -6,6 +6,14 @@ if(ENABLE_ADIOS1)
RUNTIME DESTINATION bin)
endif()
if(ENABLE_HDF5)
add_executable(HDF5EndPoint HDF5EndPoint.cpp)
target_link_libraries(HDF5EndPoint PRIVATE opts sensei timer sDataElevator sMPI)
install(TARGETS HDF5EndPoint
RUNTIME DESTINATION bin)
endif()
add_executable(ConfigurableEndPoint ConfigurableEndPoint.cxx)
target_link_libraries(ConfigurableEndPoint PRIVATE opts sensei timer pugixml sMPI)
......
#include "HDF5DataAdaptor.h"
#include "ConfigurableAnalysis.h"
#include "Timer.h"
#include "Error.h"
#include <opts/opts.h>
#include <mpi.h>
#include <iostream>
#include <vtkNew.h>
#include <vtkSmartPointer.h>
#include <vtkDataSet.h>
using DataAdaptorPtr = vtkSmartPointer<sensei::HDF5DataAdaptor>;
using AnalysisAdaptorPtr = vtkSmartPointer<sensei::ConfigurableAnalysis>;
/*!
* This program is designed to be an endpoint component in a scientific
* workflow. It can read a data-stream using HDF5. When enabled, this end point
* supports histogram and catalyst-slice analysis via the Sensei infrastructure.
*
* Usage:
* <exec> input-stream-name
*/
using std::cout;
using std::cerr;
using std::endl;
int main(int argc, char **argv)
{
int rank, size;
MPI_Comm comm = MPI_COMM_WORLD;
MPI_Init (&argc, &argv);
MPI_Comm_rank(comm, &rank);
MPI_Comm_size(comm, &size);
std::string input;
std::string readmethod("n"); // no-streaming
std::string config_file;
opts::Options ops(argc, argv);
ops >> opts::Option('r', "readmethod", readmethod, "specify read method: s(=streaming) n(=nostreaming)")
>> opts::Option('f', "config", config_file, "Sensei analysis configuration xml (required)");
bool log = ops >> opts::Present("log", "generate time and memory usage log");
bool shortlog = ops >> opts::Present("shortlog", "generate a summary time and memory usage log");
bool showHelp = ops >> opts::Present('h', "help", "show help");
bool haveInput = ops >> opts::PosOption(input);
bool doStreaming = ('s' == readmethod[0]);
bool doCollectiveTxf = ((readmethod.size() > 1) && ('c' == readmethod[1]));
if (!showHelp && !haveInput && (rank == 0))
SENSEI_ERROR("Missing HDF5 input stream");
if (!showHelp && config_file.empty() && (rank == 0))
SENSEI_ERROR("Missing XML analysis configuration");
if (showHelp || !haveInput || config_file.empty()) {
if (rank == 0) {
cerr << "Usage: " << argv[0] << "[OPTIONS] input-stream-name\n\n" << ops << endl;
}
MPI_Finalize();
return showHelp ? 0 : 1;
}
if (log | shortlog)
timer::Enable(shortlog);
timer::Initialize();
DataAdaptorPtr dataAdaptor = DataAdaptorPtr::New();
dataAdaptor->SetCommunicator(comm);
dataAdaptor->SetStreaming(doStreaming);
dataAdaptor->SetCollective(doCollectiveTxf);
if (dataAdaptor->Open(input)) {
SENSEI_ERROR("Failed to open \"" << input << "\"");
MPI_Abort(comm, 1);
}
// initlaize the analysis using the XML configurable adaptor
SENSEI_STATUS("Loading configurable analysis \"" << config_file << "\"");
if (rank == 0) {
SENSEI_STATUS("... streaming? "<<doStreaming);
}
AnalysisAdaptorPtr analysisAdaptor = AnalysisAdaptorPtr::New();
analysisAdaptor->SetCommunicator(comm);
if (analysisAdaptor->Initialize(config_file)) {
SENSEI_ERROR("Failed to initialize analysis");
MPI_Abort(comm, 1);
}
// read from the HDF5 stream until all steps have been
// processed
unsigned int nSteps = 0;
do
{
// gte the current simulation time and time step
long timeStep = dataAdaptor->GetDataTimeStep();
double time = dataAdaptor->GetDataTime();
nSteps += 1;
timer::MarkStartTimeStep(timeStep, time);
SENSEI_STATUS("Processing time step " << timeStep << " time " << time);
// execute the analysis
timer::MarkStartEvent("AnalysisAdaptor::Execute");
if (!analysisAdaptor->Execute(dataAdaptor.Get())) {
SENSEI_ERROR("Execute failed");
MPI_Abort(comm, 1);
}
timer::MarkEndEvent("AnalysisAdaptor::Execute");
// let the data adaptor release the mesh and data from this
// time step
dataAdaptor->ReleaseData();
timer::MarkEndTimeStep();
}
while (!dataAdaptor->Advance());
SENSEI_STATUS("Finished processing " << nSteps << " time steps")
// close the HDF5 stream
dataAdaptor->Close();
analysisAdaptor->Finalize();
// we must force these to be destroyed before mpi finalize
// some of the adaptors make MPI calls in the destructor
// noteabley Catalyst
dataAdaptor = nullptr;
analysisAdaptor = nullptr;
timer::Finalize();
MPI_Finalize();
return 0;
}
......@@ -35,6 +35,12 @@ if (ENABLE_SENSEI)
list(APPEND senseiCore_libs sADIOS1)
endif()
if (ENABLE_HDF5)
list(APPEND senseiCore_sources HDF5DataAdaptor.cxx HDF5AnalysisAdaptor.cxx
HDF5Schema.cxx)
list(APPEND senseiCore_libs sDataElevator)
endif()
if (ENABLE_VTK_ACCELERATORS)
list(APPEND senseiCore_sources VTKmContourAnalysis.cxx)
endif()
......
......@@ -35,6 +35,9 @@
#ifdef ENABLE_ADIOS1
#include "ADIOS1AnalysisAdaptor.h"
#endif
#ifdef ENABLE_HDF5
#include "HDF5AnalysisAdaptor.h"
#endif
#ifdef ENABLE_CATALYST
#include "CatalystAnalysisAdaptor.h"
#include "CatalystParticle.h"
......@@ -78,6 +81,7 @@ struct ConfigurableAnalysis::InternalsType
int AddVTKmVolumeReduction(pugi::xml_node node);
int AddVTKmCDF(pugi::xml_node node);
int AddAdios(pugi::xml_node node);
int AddHDF5(pugi::xml_node node);
int AddCatalyst(pugi::xml_node node);
int AddLibsim(pugi::xml_node node);
int AddAutoCorrelation(pugi::xml_node node);
......@@ -333,6 +337,50 @@ int ConfigurableAnalysis::InternalsType::AddAdios(pugi::xml_node node)
#endif
}
// --------------------------------------------------------------------------
int ConfigurableAnalysis::InternalsType::AddHDF5(pugi::xml_node node)
{
#ifndef ENABLE_HDF5
(void)node;
SENSEI_ERROR("HDF5 was requested but is disabled in this build");
return -1;
#else
auto dataE = vtkSmartPointer<HDF5AnalysisAdaptor>::New();
if (this->Comm != MPI_COMM_NULL)
dataE->SetCommunicator(this->Comm);
pugi::xml_attribute filename = node.attribute("filename");
pugi::xml_attribute methodAttr = node.attribute("method");
if (filename)
dataE->SetFileName(filename.value());
if (methodAttr) {
std::string method = methodAttr.value();
if (method.size() > 0) {
bool doStreaming = ('s' == method[0]);
bool doCollectiveTxf = ((method.size() > 1) && ('c' == method[1]));
dataE->SetStreaming(doStreaming);
dataE->SetCollective(doCollectiveTxf);
}
}
this->TimeInitialization(dataE);
this->Analyses.push_back(dataE.GetPointer());
SENSEI_STATUS("Configured HDF5 AnalysisAdaptor \"" << filename.value())
return 0;
#endif
}
// --------------------------------------------------------------------------
int ConfigurableAnalysis::InternalsType::AddCatalyst(pugi::xml_node node)
{
......@@ -874,6 +922,7 @@ int ConfigurableAnalysis::Initialize(const pugi::xml_node &root)
if (!(((type == "histogram") && !this->Internals->AddHistogram(node))
|| ((type == "autocorrelation") && !this->Internals->AddAutoCorrelation(node))
|| ((type == "adios") && !this->Internals->AddAdios(node))
|| ((type == "hdf5") && !this->Internals->AddHDF5(node))
|| ((type == "catalyst") && !this->Internals->AddCatalyst(node))
|| ((type == "libsim") && !this->Internals->AddLibsim(node))
|| ((type == "PosthocIO") && !this->Internals->AddPosthocIO(node))
......
#include "HDF5AnalysisAdaptor.h"
#include "HDF5Schema.h"
#include "DataAdaptor.h"
#include "MeshMetadataMap.h"
#include "VTKUtils.h"
#include "MPIUtils.h"
#include "Timer.h"
#include "Error.h"
#include <vtkCellTypes.h>
#include <vtkCellData.h>
#include <vtkCompositeDataIterator.h>
#include <vtkCompositeDataSet.h>
#include <vtkDataSetAttributes.h>
#include <vtkDoubleArray.h>
#include <vtkFloatArray.h>
#include <vtkIntArray.h>
#include <vtkUnsignedIntArray.h>
#include <vtkLongArray.h>
#include <vtkUnsignedLongArray.h>
#include <vtkCharArray.h>
#include <vtkUnsignedCharArray.h>
#include <vtkIdTypeArray.h>
#include <vtkCellArray.h>
#include <vtkUnstructuredGrid.h>
#include <vtkPolyData.h>
#include <vtkImageData.h>
#include <vtkInformation.h>
#include <vtkObjectFactory.h>
#include <vtkPointData.h>
#include <vtkSmartPointer.h>
#include <mpi.h>
#include <adios.h>
#include <vector>
namespace sensei
{
//----------------------------------------------------------------------------
senseiNewMacro(HDF5AnalysisAdaptor);
//----------------------------------------------------------------------------
HDF5AnalysisAdaptor::HDF5AnalysisAdaptor()
:m_FileName("no.file"), m_HDF5Writer(nullptr)
{}
//----------------------------------------------------------------------------
HDF5AnalysisAdaptor::~HDF5AnalysisAdaptor()
{
delete m_HDF5Writer;
}
//-----------------------------------------------------------------------------
int HDF5AnalysisAdaptor::SetDataRequirements(const DataRequirements &reqs)
{
this->Requirements = reqs;
return 0;
}
//-----------------------------------------------------------------------------
int HDF5AnalysisAdaptor::AddDataRequirement(const std::string &meshName,
int association, const std::vector<std::string> &arrays)
{
this->Requirements.AddRequirement(meshName, association, arrays);
return 0;
}
//----------------------------------------------------------------------------
bool HDF5AnalysisAdaptor::Execute(DataAdaptor* dataAdaptor)
{
timer::MarkEvent mark("HDF5AnalysisAdaptor::Execute");
// figure out what the simulation can provide
MeshMetadataFlags flags;
flags.SetBlockDecomp();
flags.SetBlockSize();
MeshMetadataMap mdm;
if (mdm.Initialize(dataAdaptor, flags)) {
SENSEI_ERROR("Failed to get metadata");
return false;
}
// if no dataAdaptor requirements are given, push all the data
// fill in the requirements with every thing
if (this->Requirements.Empty()) {
if (this->Requirements.Initialize(dataAdaptor, false)) {
SENSEI_ERROR("Failed to initialze dataAdaptor description");
return false;
}
SENSEI_WARNING("No subset specified. Writing all available data");
}
if (!this->InitializeHDF5())
return false;
unsigned long timeStep = dataAdaptor->GetDataTimeStep();
double time = dataAdaptor->GetDataTime();
if (!this->m_HDF5Writer->AdvanceTimeStep(timeStep, time))
return false;
//senseiHDF5::HDF5GroupGuard g(this->m_HDF5Writer->m_TimeStepGroupId);
// collect the specified data objects and metadata
//std::vector<vtkCompositeDataSet*> objects;
MeshRequirementsIterator mit = this->Requirements.GetMeshRequirementsIterator();
//unsigned int meshCounter = 0;
while (mit) {
// get metadata
MeshMetadataPtr md;
if (mdm.GetMeshMetadata(mit.MeshName(), md)) {
SENSEI_ERROR("Failed to get mesh metadata for mesh \""
<< mit.MeshName() << "\"");
return false;
}
// get the mesh
vtkCompositeDataSet *dobj = nullptr;
if (dataAdaptor->GetMesh(mit.MeshName(), mit.StructureOnly(), dobj)) {
SENSEI_ERROR("Failed to get mesh \"" << mit.MeshName() << "\"");
return false;
}
// add the ghost cell arrays to the mesh
if (md->NumGhostCells && dataAdaptor->AddGhostCellsArray(dobj, mit.MeshName())) {
SENSEI_ERROR("Failed to get ghost cells for mesh \"" << mit.MeshName() << "\"")
return false;
}
// add the ghost node arrays to the mesh
if (md->NumGhostNodes && dataAdaptor->AddGhostNodesArray(dobj, mit.MeshName())) {
SENSEI_ERROR("Failed to get ghost nodes for mesh \"" << mit.MeshName() << "\"");
return false;
}
// add the required arrays
ArrayRequirementsIterator ait = this->Requirements.GetArrayRequirementsIterator(mit.MeshName());
while (ait) {
if (dataAdaptor->AddArray(dobj, mit.MeshName(), ait.Association(), ait.Array()))
{
SENSEI_ERROR("Failed to add "
<< VTKUtils::GetAttributesName(ait.Association())
<< " data array \"" << ait.Array() << "\" to mesh \""
<< mit.MeshName() << "\"");
return false;
}
++ait;
}
// generate a global view of the metadata. everything we do from here
// on out depends on having the global view.
if (!md->GlobalView)
{
MPI_Comm comm = this->GetCommunicator();
sensei::MPIUtils::GlobalViewV(comm, md->BlockOwner);
sensei::MPIUtils::GlobalViewV(comm, md->BlockIds);
sensei::MPIUtils::GlobalViewV(comm, md->BlockNumPoints);
sensei::MPIUtils::GlobalViewV(comm, md->BlockNumCells);
sensei::MPIUtils::GlobalViewV(comm, md->BlockCellArraySize);
sensei::MPIUtils::GlobalViewV(comm, md->BlockExtents);
md->GlobalView = true;
}
this->m_HDF5Writer->WriteMesh(md, dobj);
dobj->Delete();
++mit;
}
return true;
}
//----------------------------------------------------------------------------
bool HDF5AnalysisAdaptor::InitializeHDF5()
{
timer::MarkEvent mark("HDF5AnalysisAdaptor::IntializeHDF5");
if (!this->m_HDF5Writer) {
this->m_HDF5Writer = new senseiHDF5::WriteStream(this->GetCommunicator(), m_DoStreaming);
if (!this->m_HDF5Writer->Init(this->m_FileName)) {
return -1;
}
}
return true;
}
//----------------------------------------------------------------------------
int HDF5AnalysisAdaptor::Finalize()
{
if (this->m_HDF5Writer)
delete this->m_HDF5Writer;
this->m_HDF5Writer = nullptr;
return 0;
}
/*
//----------------------------------------------------------------------------
bool HDF5AnalysisAdaptor::WriteTimestep(unsigned long timeStep, double time,
const std::vector<vtkCompositeDataSet*> &objects)
{
timer::MarkEvent mark("HDF5AnalysisAdaptor::WriteTimestep");
int ierr = 0;
timer::MarkEvent mark("HDF5AnalysisAdaptor::WriteTimestep");
this->m_HDF5Writer->AdvanceTimeStep(timestep, time);
if (this->m_HDF5Writer->Write(objects))
{
SENSEI_ERROR("Failed to write step " << timeStep
<< " to \"" << this->FileName << "\"");
return -1;
}
return ierr;
}
*/
//----------------------------------------------------------------------------
void HDF5AnalysisAdaptor::PrintSelf(ostream& os, vtkIndent indent)
{
this->Superclass::PrintSelf(os, indent);
}
} // name space
#ifndef HDF5AnalysisAdaptor_h
#define HDF5AnalysisAdaptor_h
#include "AnalysisAdaptor.h"
#include "DataRequirements.h"
#include "MeshMetadata.h"
#include <vector>
#include <string>
#include <mpi.h>
#include "hdf5.h"
#include "HDF5Schema.h"
//namespace senseiHDF5 { class DataObjectCollectionSchema; }
class vtkDataObject;
class vtkCompositeDataSet;
namespace sensei
{
/// The write side of the ADIOS 1 transport
class HDF5AnalysisAdaptor : public AnalysisAdaptor
{
public:
static HDF5AnalysisAdaptor* New();
senseiTypeMacro(HDF5AnalysisAdaptor, AnalysisAdaptor);
void PrintSelf(ostream& os, vtkIndent indent) override;
/// Sets the maximum buffer allocated by HDF5 in MB
/// takes affect on first Execute
void SetMaxBufferSize(unsigned int size)
{ this->MaxBufferSize = size; }
/// @brief Set the filename.
///
/// Default value is "sensei.bp"
void SetFileName(const std::string &filename)
{ this->m_FileName = filename; }
void SetStreaming(bool streamOption)
{ this ->m_DoStreaming = streamOption;}
void SetCollective(bool s) {m_Collective = s;}
std::string GetFileName() const
{ return this->m_FileName; }
/// data requirements tell the adaptor what to push
/// if none are given then all data is pushed.
int SetDataRequirements(const DataRequirements &reqs);
int AddDataRequirement(const std::string &meshName,
int association, const std::vector<std::string> &arrays);
// SENSEI AnalysisAdaptor API
bool Execute(DataAdaptor* data) override;
int Finalize() override;
protected:
HDF5AnalysisAdaptor();
~HDF5AnalysisAdaptor();
// intializes HDF5 in no-xml mode, allocate buffers, and declares a group
//bool InitializeHDF5(const std::vector<MeshMetadataPtr> &metadata);
bool InitializeHDF5();
// writes the data collection
/*
bool WriteTimestep(unsigned long timeStep, double time,
const std::vector<MeshMetadataPtr> &metadata,
const std::vector<vtkCompositeDataSet*> &dobjects);
*/
unsigned int MaxBufferSize;
sensei::DataRequirements Requirements;
std::string m_FileName;
bool m_DoStreaming = false;
bool m_Collective = false;
private:
senseiHDF5::WriteStream* m_HDF5Writer;
HDF5AnalysisAdaptor(const HDF5AnalysisAdaptor&) = delete;
void operator=(const HDF5AnalysisAdaptor&) = delete;
};
}
#endif
#include "HDF5DataAdaptor.h"
#include "Error.h"
#include "Timer.h"
#include "VTKUtils.h"
#include "MeshMetadata.h"
#include <vtkCompositeDataIterator.h>
#include <vtkDataSetAttributes.h>
#include <vtkInformation.h>
#include <vtkMultiBlockDataSet.h>
#include <vtkObjectFactory.h>
#include <vtkSmartPointer.h>
#include <vtkDataSet.h>
#include <sstream>
namespace sensei
{
//----------------------------------------------------------------------------
senseiNewMacro(HDF5DataAdaptor);
//----------------------------------------------------------------------------
HDF5DataAdaptor::HDF5DataAdaptor():m_HDF5Reader(nullptr)
{
}
//----------------------------------------------------------------------------
HDF5DataAdaptor::~HDF5DataAdaptor()
{
delete m_HDF5Reader;
}
//----------------------------------------------------------------------------
int HDF5DataAdaptor::Open(const std::string& fileName)
{
timer::MarkEvent mark("HDF5DataAdaptor::Open");
if (this->m_HDF5Reader == NULL) {
this->m_HDF5Reader = new senseiHDF5::ReadStream(this->GetCommunicator(), m_Streaming);
}
if (!this->m_HDF5Reader->Init(fileName)) {
SENSEI_ERROR("Failed to open \"" << fileName << "\"");
return -1;
}
// initialize the time step
if (this->UpdateTimeStep())
return -1;
return 0;
}
//----------------------------------------------------------------------------
int HDF5DataAdaptor::Close()
{
timer::MarkEvent mark("HDF5DataAdaptor::Close");
int m_Rank;
MPI_Comm_rank(GetCommunicator(), &m_Rank);
if (this->m_HDF5Reader != nullptr) {
delete this->m_HDF5Reader;
this->m_HDF5Reader = nullptr;
}
return 0;
}
//----------------------------------------------------------------------------
int HDF5DataAdaptor::Advance()
{
timer::MarkEvent mark("HDF5DataAdaptor::Advance");
return this->UpdateTimeStep();
}
//----------------------------------------------------------------------------
int HDF5DataAdaptor::UpdateTimeStep()
{
timer::MarkEvent mark("HDF5DataAdaptor::UpdateTimeStep");
// update data object time and time step
unsigned long timeStep = 0;
double time = 0.0;
if (!this->m_HDF5Reader->AdvanceTimeStep(timeStep, time))
{
//SENSEI_ERROR("Failed to update time step");
return -1;
}
this->SetDataTimeStep(timeStep);
this->SetDataTime(time);
// read metadata
unsigned int nMeshes = 0;
if (!this->m_HDF5Reader->ReadMetadata(nMeshes)) {
SENSEI_ERROR("Failed to read metadata at timestep: "<<timeStep);
return -1;
}
if (nMeshes == 0) {
SENSEI_ERROR("No Mesh at this timestep found");
return -1;
}
return 0;
}
//----------------------------------------------------------------------------
int HDF5DataAdaptor::GetNumberOfMeshes(unsigned int &numMeshes)
{
if (this->m_HDF5Reader) {
numMeshes = this->m_HDF5Reader->GetNumberOfMeshes();
return 0;
}
return -1;
}
//----------------------------------------------------------------------------
int HDF5DataAdaptor::GetMeshMetadata(unsigned int id, MeshMetadataPtr &metadata)
{
if (this->m_HDF5Reader->ReadMeshMetaData(id, metadata))
return 0;
else
{
SENSEI_ERROR("Failed to get metadata for object " << id);
return -1;
}
}
//----------------------------------------------------------------------------
int HDF5DataAdaptor::GetMesh(const std::string &meshName,
bool structureOnly, vtkDataObject *&mesh)
{
timer::MarkEvent mark("HDF5DataAdaptor::GetMesh");
mesh = nullptr;
// other wise we need to read the mesh at the current time step
if (!this->m_HDF5Reader->ReadMesh(meshName, mesh, structureOnly))
{
SENSEI_ERROR("Failed to read mesh \"" << meshName << "\"");
return -1;
}
return 0;
}
//----------------------------------------------------------------------------
int HDF5DataAdaptor::AddGhostNodesArray(vtkDataObject *mesh,
const std::string &meshName)
{
return AddArray(mesh, meshName, vtkDataObject::POINT, "vtkGhostType");
}
//----------------------------------------------------------------------------
int HDF5DataAdaptor::AddGhostCellsArray(vtkDataObject *mesh,
const std::string &meshName)
{
return AddArray(mesh, meshName, vtkDataObject::CELL, "vtkGhostType");
}
//----------------------------------------------------------------------------
int HDF5DataAdaptor::AddArray(vtkDataObject* mesh,
const std::string &meshName,
int association,
const std::string& arrayName)
{
timer::MarkEvent mark("HDF5DataAdaptor::AddArray");
// the mesh should never be null. there must have been an error
// upstream.
if (!mesh) {
SENSEI_ERROR("Invalid mesh object");
return -1;
}
if (!this->m_HDF5Reader->ReadInArray(meshName, association, arrayName, mesh))
{
SENSEI_ERROR("Failed to read " << VTKUtils::GetAttributesName(association)
<< " data array \"" << arrayName << "\" from mesh \"" << meshName << "\"");
return -1;
}
return 0;
}
//----------------------------------------------------------------------------
int HDF5DataAdaptor::ReleaseData()
{
timer::MarkEvent mark("HDF5DataAdaptor::ReleaseData");
return 0;
}
//----------------------------------------------------------------------------
void HDF5DataAdaptor::PrintSelf(ostream& os, vtkIndent indent)
{
this->sensei::DataAdaptor::PrintSelf(os, indent);
}
} // namespace
#ifndef HDF5_DataAdaptor_h
#define HDF5_DataAdaptor_h
#include "DataAdaptor.h"
#include <mpi.h>
#include <hdf5.h>
#include <map>
#include <string>
#include <vtkSmartPointer.h>
#include "HDF5Schema.h"
namespace sensei
{
//
// read from HDF and construct VTK object
//
class HDF5DataAdaptor : public DataAdaptor
{
public:
static HDF5DataAdaptor* New();
senseiTypeMacro(HDF5DataAdaptor, DataAdaptor);
void PrintSelf(ostream& os, vtkIndent indent) override;
int Open( const std::string& filename);
void SetStreaming(bool s) {m_Streaming = s;}
void SetCollective(bool s) {m_Collective = s;}
int Advance();
int Close();
/// SENSEI DataAdaptor API
int GetNumberOfMeshes(unsigned int &numMeshes) override;
int GetMeshMetadata(unsigned int id, MeshMetadataPtr &metadata) override;
int GetMesh(const std::string &meshName, bool structure_only,
vtkDataObject *&mesh) override;
int AddGhostNodesArray(vtkDataObject* mesh, const std::string &meshName) override;
int AddGhostCellsArray(vtkDataObject* mesh, const std::string &meshName) override;
int AddArray(vtkDataObject* mesh, const std::string &meshName,
int association, const std::string &arrayName) override;
int ReleaseData() override;
protected:
HDF5DataAdaptor();
~HDF5DataAdaptor();
// reads the current time step and time values from the stream
// stores them in the base class information object
int UpdateTimeStep();
private:
//struct InternalsType;
//InternalsType *Internals;
senseiHDF5::ReadStream* m_HDF5Reader;
bool m_Streaming = false;
bool m_Collective = false;
HDF5DataAdaptor(const HDF5DataAdaptor&) = delete;
void operator=(const HDF5DataAdaptor&) = delete;
};
}
#endif
This diff is collapsed.
This diff is collapsed.
......@@ -12,6 +12,7 @@
#cmakedefine ENABLE_CATALYST_PYTHON
#cmakedefine ENABLE_LIBSIM
#cmakedefine ENABLE_ADIOS1
#cmakedefine ENABLE_HDF5
#cmakedefine ENABLE_VTK_GENERIC_ARRAYS
#cmakedefine ENABLE_VTK_MPI
#cmakedefine ENABLE_VTK_IO
......