Commit e16ec61f authored by Utkarsh Ayachit's avatar Utkarsh Ayachit
Browse files

Adding an endpoint for posthoc io.

This currently only supports VTK-XML files.
parent 36bc67f1
Pipeline #10699 skipped
......@@ -55,7 +55,9 @@ cmake_dependent_option(
ENABLE_LIBSIM "Enable analysis methods that use Libsim" OFF "ENABLE_SENSEI" OFF)
#------------------------------------------------------------------------------
option(ENABLE_VTK_XMLP "Enable use of vtk parallel I/O" OFF)
# Enable reader/writers that use VTK XML file formats.
cmake_dependent_option(
ENABLE_VTK_XMLP "Enable use of vtk parallel I/O" OFF "ENABLE_SENSEI" OFF)
#------------------------------------------------------------------------------
include(mpi)
......
if (ENABLE_ADIOS)
if(ENABLE_ADIOS)
#------------------------------------------------------------------------------
add_executable(ADIOSAnalysisEndPoint ADIOSAnalysisEndPoint.cxx)
target_link_libraries(ADIOSAnalysisEndPoint PRIVATE opts mpi adios sensei timer)
#------------------------------------------------------------------------------
endif()
if(ENABLE_VTK_XMLP)
#------------------------------------------------------------------------------
add_executable(PosthocIOEndPoint PosthocIOEndPoint.cxx)
target_link_libraries(PosthocIOEndPoint PRIVATE opts mpi sensei timer)
#------------------------------------------------------------------------------
endif()
/*!
* This program is designed to be a posthoc endpoint to read datasets written out using sensei::PosthocIO.
*/
#include <opts/opts.h>
#include <mpi.h>
#include <iostream>
#include <sensei/vtk/DataAdaptor.h>
#include <sensei/ConfigurableAnalysis.h>
#include <timer/Timer.h>
#include <vtkDataSet.h>
#include <vtkNew.h>
#include <vtkSmartPointer.h>
#include <vtkXMLMultiBlockDataReader.h>
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_pattern;
std::string config_file;
int count=1, begin=0, step=1;
opts::Options ops(argc, argv);
ops >> opts::Option('f', "config", config_file, "Sensei analysis configuration xml (required).")
>> opts::Option('p', "pattern", input_pattern, "Filename pattern (sprintf) for *.vtmb files (required).")
>> opts::Option('c', "count", count, "Number of timesteps to read.")
>> opts::Option('b', "begin", begin, "Start timestep.")
>> opts::Option('s', "step", step, "Step size i.e. number of timesteps to skip (>=1).");
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");
if (ops >> opts::Present('h', "help", "show help") ||
input_pattern.empty() || config_file.empty() ||
count <= 0 || step < 1)
{
if (rank == 0)
{
cout << "Usage: " << argv[0] << " [OPTIONS]\n\n" << ops;
}
MPI_Barrier(comm);
MPI_Finalize();
return 1;
}
timer::SetLogging(log || shortlog);
timer::SetTrackSummariesOverTime(shortlog);
vtkSmartPointer<sensei::ConfigurableAnalysis> analysis =
vtkSmartPointer<sensei::ConfigurableAnalysis>::New();
analysis->Initialize(comm, config_file);
size_t fname_length = input_pattern.size() + 128;
char *fname = new char[fname_length];
vtkNew<sensei::vtk::DataAdaptor> dataAdaptor;
for (int cc=0; cc < count; cc++)
{
int t_step = begin + cc * step;
double t = static_cast<double>(t_step);
timer::MarkStartTimeStep(t_step, t);
snprintf(fname, fname_length, input_pattern.c_str(), t_step);
if (true)
{
vtkNew<vtkXMLMultiBlockDataReader> reader;
reader->SetFileName(fname);
reader->ReadFromInputStringOn();
timer::MarkStartEvent("posthoc::pre-read");
// Since vtkXMLMultiBlockDataReader tries to read the XML meta-file on all ranks,
// we explicitly broadcast the xml file to all ranks.
if (rank == 0)
{
std::ifstream t(fname);
std::stringstream buffer;
buffer << t.rdbuf();
std::string data = buffer.str();
unsigned int length = static_cast<unsigned int>(data.size()) + 1;
MPI_Bcast(&length, 1, MPI_UNSIGNED, 0, comm);
MPI_Bcast(const_cast<char*>(data.c_str()), length, MPI_CHAR, 0, comm);
reader->SetInputString(data);
}
else
{
unsigned int length;
MPI_Bcast(&length, 1, MPI_UNSIGNED, 0, comm);
char* data = new char[length];
MPI_Bcast(data, length, MPI_CHAR, 0, comm);
reader->SetInputString(data);
delete [] data;
}
timer::MarkEndEvent("posthoc::pre-read");
timer::MarkStartEvent("posthoc::read");
#if VTK_MAJOR_VERSION > 7 || (VTK_MAJOR_VERSION == 7 && VTK_MINOR_VERSION >= 1)
// Use API added in 7.1
reader->UpdatePiece(rank, size, 0);
#else
// Using old API here since I'm not sure which VTK we'll have on our test
// runs.
reader->UpdateInformation();
reader->SetUpdateExtent(0, rank, size, 0);
reader->Update();
#endif
timer::MarkEndEvent("posthoc::read");
dataAdaptor->SetDataObject(reader->GetOutputDataObject(0));
}
timer::MarkStartEvent("adios::analysis");
analysis->Execute(dataAdaptor.GetPointer());
timer::MarkEndEvent("adios::analysis");
dataAdaptor->ReleaseData();
timer::MarkEndTimeStep();
}
delete [] fname;
timer::MarkStartEvent("adios::finalize");
analysis = NULL;
timer::MarkEndEvent("adios::finalize");
timer::PrintLog(std::cout, comm);
MPI_Finalize();
return 0;
}
......@@ -13,6 +13,12 @@ set (sources
PosthocIO.cxx
PosthocIO.h
)
if(ENABLE_VTK_XMLP)
list(APPEND sources
vtk/DataAdaptor.cxx
vtk/DataAdaptor.h
)
endif()
if(ENABLE_CATALYST)
list(APPEND sources
......
......@@ -111,7 +111,7 @@ public:
/// @brief convenience method to get full mesh will all arrays added to the
/// mesh.
vtkDataObject* GetCompleteMesh();
virtual vtkDataObject* GetCompleteMesh();
/// @brief Key to store the timestep index.
static vtkInformationIntegerKey* DATA_TIME_STEP_INDEX();
......
#include "DataAdaptor.h"
#include "vtkCompositeDataIterator.h"
#include "vtkCompositeDataSet.h"
#include "vtkDataSetAttributes.h"
#include "vtkObjectFactory.h"
namespace sensei
{
namespace vtk
{
vtkDataObject* vtkGetRepresentationDataObject(vtkDataObject* dobj)
{
if (vtkCompositeDataSet* cd = vtkCompositeDataSet::SafeDownCast(dobj))
{
vtkCompositeDataIterator* iter = cd->NewIterator();
for (iter->InitTraversal(); !iter->IsDoneWithTraversal(); iter->GoToNextItem())
{
dobj = iter->GetCurrentDataObject();
break;
}
iter->Delete();
}
return dobj;
}
vtkStandardNewMacro(DataAdaptor);
//----------------------------------------------------------------------------
DataAdaptor::DataAdaptor()
{
}
//----------------------------------------------------------------------------
DataAdaptor::~DataAdaptor()
{
}
//----------------------------------------------------------------------------
void DataAdaptor::SetDataObject(vtkDataObject* dobj)
{
this->DataObject = dobj;
}
//----------------------------------------------------------------------------
vtkDataObject* DataAdaptor::GetMesh(bool)
{
return this->DataObject;
}
//----------------------------------------------------------------------------
bool DataAdaptor::AddArray(vtkDataObject* mesh, int association, const std::string& arrayname)
{
vtkDataObject* dobj = vtkGetRepresentationDataObject(this->DataObject);
vtkFieldData* dsa = dobj? dobj->GetAttributesAsFieldData(association) : NULL;
return dsa? dsa->GetAbstractArray(arrayname.c_str()) : NULL;
}
//----------------------------------------------------------------------------
unsigned int DataAdaptor::GetNumberOfArrays(int association)
{
vtkDataObject* dobj = vtkGetRepresentationDataObject(this->DataObject);
vtkFieldData* dsa = dobj? dobj->GetAttributesAsFieldData(association) : NULL;
return dsa? static_cast<unsigned int>(dsa->GetNumberOfArrays()) : 0;
}
//----------------------------------------------------------------------------
std::string DataAdaptor::GetArrayName(int association, unsigned int index)
{
vtkDataObject* dobj = vtkGetRepresentationDataObject(this->DataObject);
vtkFieldData* dsa = dobj? dobj->GetAttributesAsFieldData(association) : NULL;
const char* aname = dsa? dsa->GetArrayName(index) : NULL;
return aname? std::string(aname) : std::string();
}
//----------------------------------------------------------------------------
void DataAdaptor::ReleaseData()
{
this->DataObject = NULL;
}
//----------------------------------------------------------------------------
vtkDataObject* DataAdaptor::GetCompleteMesh()
{
return this->DataObject;
}
} // vtk
} // sensei
#ifndef sensei_vtk_DataAdaptor_h
#define sensei_vtk_DataAdaptor_h
#include <sensei/DataAdaptor.h>
#include <vtkSmartPointer.h>
namespace sensei
{
namespace vtk
{
/// @brief DataAdaptor for a vtkDataObject.
///
/// sensei::vtk::DataAdaptor is a simple implementation of sensei::DataAdaptor
/// that provides the sensei::DataAdaptor on a vtkDataObject. To use this data
/// adaptor for codes that produce a vtkDataObject natively. Once simply passes
/// the vtkDataObject instance to this class and one then connect it to the
/// sensei::AnalysisAdators.
///
/// If the DataObject is a composite-dataset, the first non-null block on the
/// current rank is assumed to the representative block for answering all
/// queries.
class DataAdaptor : public sensei::DataAdaptor
{
public:
static DataAdaptor* New();
vtkTypeMacro(DataAdaptor, sensei::DataAdaptor);
/// @brief Set the data object for current timestep.
///
/// This method must be called to the set the data object for
/// the current timestep.
void SetDataObject(vtkDataObject* dobj);
virtual vtkDataObject* GetMesh(bool structure_only=false);
virtual bool AddArray(vtkDataObject* mesh, int association, const std::string& arrayname);
virtual unsigned int GetNumberOfArrays(int association);
virtual std::string GetArrayName(int association, unsigned int index);
virtual void ReleaseData();
virtual vtkDataObject* GetCompleteMesh();
protected:
DataAdaptor();
~DataAdaptor();
private:
DataAdaptor(const DataAdaptor&); // Not implemented.
void operator=(const DataAdaptor&); // Not implemented.
vtkSmartPointer<vtkDataObject> DataObject;
};
} // vtk
} // sensei
#endif
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