Commit 039f2281 authored by Burlen Loring's avatar Burlen Loring

support multiple meshes

Adds mesh name (string) parameter to data access methods in the data
adaptor data API. Adds methods to query number of meshes and mesh names
by index to data adaptor metadata API. Updates data adptors, analysis
adaptors, and mini-apps too use the new API.
Co-Authored-By: 's avatarBrad Whitlock <bjw.ilight@gmail.com>
parent d80a0f86
......@@ -2,9 +2,9 @@
set enabled="1" on analyses you wish to enable -->
<sensei>
<!-- Custom Analyses -->
<analysis type="histogram" array="pressure" association="cell" bins="10" enabled="1" />
<analysis type="histogram" array="density" association="cell" bins="10" enabled="1" />
<analysis type="histogram" array="temperature" association="cell" bins="10" enabled="1" />
<analysis type="histogram" mesh="mesh" array="pressure" association="cell" bins="10" enabled="1" />
<analysis type="histogram" mesh="mesh" array="density" association="cell" bins="10" enabled="1" />
<analysis type="histogram" mesh="mesh" array="temperature" association="cell" bins="10" enabled="1" />
<!-- ADIOS Analyses -->
<analysis type="adios" filename="3D_Grid.bp" method="MPI" enabled ="0"/>
......
......@@ -2,8 +2,3 @@ if(ENABLE_ADIOS)
add_executable(ADIOSAnalysisEndPoint ADIOSAnalysisEndPoint.cxx)
target_link_libraries(ADIOSAnalysisEndPoint PRIVATE opts mpi adios sensei timer)
endif()
if(ENABLE_ADIOS AND ENABLE_VTK_XMLP AND NOT ENABLE_LIBSIM)
add_executable(PosthocIOEndPoint PosthocIOEndPoint.cxx)
target_link_libraries(PosthocIOEndPoint PRIVATE opts mpi adios sensei timer)
endif()
#include "dataadaptor.h"
#include "Error.h"
#include <vtkInformation.h>
#include <vtkFloatArray.h>
......@@ -24,7 +25,8 @@ struct DataAdaptor::DInternals
inline bool areBoundsValid(const diy::DiscreteBounds& bds)
{
return (bds.min[0] <= bds.max[0] && bds.min[1] <= bds.max[1] && bds.min[2] <= bds.max[2]);
return ((bds.min[0] <= bds.max[0]) && (bds.min[1] <= bds.max[1])
&& (bds.min[2] <= bds.max[2]));
}
//-----------------------------------------------------------------------------
......@@ -80,8 +82,8 @@ void DataAdaptor::SetBlockExtent(int gid,
//-----------------------------------------------------------------------------
void DataAdaptor::SetDataExtent(int ext[6])
{
// TODO -- this key holds a int**, it should copy the data
this->Internals->DataExtent.assign(ext, ext+6);
this->GetInformation()->Set(vtkDataObject::DATA_EXTENT(),
this->Internals->DataExtent.data(), 6);
}
......@@ -94,9 +96,20 @@ void DataAdaptor::SetBlockData(int gid, float* data)
}
//-----------------------------------------------------------------------------
vtkDataObject* DataAdaptor::GetMesh(bool vtkNotUsed(structure_only))
int DataAdaptor::GetMesh(const std::string &meshName, bool structureOnly,
vtkDataObject *&mesh)
{
(void)structureOnly;
if (meshName != "mesh")
{
SENSEI_ERROR("the miniapp provides a mesh named \"mesh\""
" you requested \"" << meshName << "\"")
return -1;
}
DInternals& internals = (*this->Internals);
if (!internals.Mesh)
{
internals.Mesh = vtkSmartPointer<vtkMultiBlockDataSet>::New();
......@@ -106,9 +119,10 @@ vtkDataObject* DataAdaptor::GetMesh(bool vtkNotUsed(structure_only))
internals.Mesh->SetBlock(static_cast<unsigned int>(cc), this->GetBlockMesh(cc));
}
}
this->AddArray(internals.Mesh,
vtkDataObject::FIELD_ASSOCIATION_CELLS, "data");
return internals.Mesh;
mesh = internals.Mesh;
return 0;
}
//-----------------------------------------------------------------------------
......@@ -129,19 +143,23 @@ vtkDataObject* DataAdaptor::GetBlockMesh(int gid)
}
//-----------------------------------------------------------------------------
bool DataAdaptor::AddArray(vtkDataObject* mesh, int association,
const std::string& arrayname)
int DataAdaptor::AddArray(vtkDataObject* mesh, const std::string &meshName,
int association, const std::string &arrayName)
{
#ifndef NDEBUG
if (association != vtkDataObject::FIELD_ASSOCIATION_CELLS ||
arrayname != "data")
if ((association != vtkDataObject::FIELD_ASSOCIATION_CELLS) ||
(arrayName != "data") || (meshName != "mesh"))
{
return false;
SENSEI_ERROR("the miniapp provides a cell centered array named \"data\" "
" on a mesh named \"mesh\"")
return 1;
}
#else
(void)meshName;
(void)association;
(void)arrayName;
#endif
bool retVal = false;
int retVal = 1;
DInternals& internals = (*this->Internals);
vtkMultiBlockDataSet* md = vtkMultiBlockDataSet::SafeDownCast(mesh);
for (unsigned int cc=0, max=md->GetNumberOfBlocks(); cc < max; ++cc)
......@@ -153,23 +171,70 @@ bool DataAdaptor::AddArray(vtkDataObject* mesh, int association,
vtkSmartPointer<vtkImageData>& blockMesh = internals.BlockMesh[cc];
if (vtkCellData* cd = (blockMesh? blockMesh->GetCellData(): NULL))
{
if (cd->GetArray(arrayname.c_str()) == NULL)
if (cd->GetArray(arrayName.c_str()) == NULL)
{
vtkFloatArray* fa = vtkFloatArray::New();
fa->SetName(arrayname.c_str());
fa->SetName(arrayName.c_str());
fa->SetArray(internals.Data[cc], blockMesh->GetNumberOfCells(), 1);
cd->SetScalars(fa);
cd->SetActiveScalars("data");
fa->FastDelete();
}
retVal = true;
retVal = 0;
}
}
return retVal;
}
//-----------------------------------------------------------------------------
void DataAdaptor::ReleaseData()
int DataAdaptor::GetNumberOfMeshes(unsigned int &numMeshes)
{
numMeshes = 1;
return 0;
}
//-----------------------------------------------------------------------------
int DataAdaptor::GetMeshName(unsigned int id, std::string &meshName)
{
if (id == 0)
{
meshName = "mesh";
return 0;
}
SENSEI_ERROR("Failed to get mesh name")
return -1;
}
//-----------------------------------------------------------------------------
int DataAdaptor::GetNumberOfArrays(const std::string &meshName, int association,
unsigned int &numberOfArrays)
{
if ((meshName == "mesh") && (association == vtkDataObject::CELL))
{
numberOfArrays = 1;
return 0;
}
return 0;
}
//-----------------------------------------------------------------------------
int DataAdaptor::GetArrayName(const std::string &meshName, int association,
unsigned int index, std::string &arrayName)
{
if ((meshName == "mesh") &&
(association == vtkDataObject::CELL) && (index == 0))
{
arrayName = "data";
return 0;
}
SENSEI_ERROR("Failed to get array name")
return -1;
}
//-----------------------------------------------------------------------------
int DataAdaptor::ReleaseData()
{
DInternals& internals = (*this->Internals);
internals.Mesh = NULL;
......@@ -183,6 +248,7 @@ void DataAdaptor::ReleaseData()
internals.Data[cc] = NULL;
internals.BlockMesh[cc] = NULL;
}
return 0;
}
}
......@@ -28,12 +28,24 @@ public:
/// Set data for a specific block.
void SetBlockData(int gid, float* data);
vtkDataObject* GetMesh(bool structure_only=false) override;
bool AddArray(vtkDataObject* mesh, int association, const std::string& arrayname) override;
unsigned int GetNumberOfArrays(int) override { return 1; }
std::string GetArrayName(int, unsigned int index) override
{ return index==0? "data" : std::string(); }
void ReleaseData() override;
// SENSEI API
int GetNumberOfMeshes(unsigned int &numMeshes) override;
int GetMeshName(unsigned int id, std::string &meshName) override;
int GetMesh(const std::string &meshName, bool structureOnly,
vtkDataObject *&mesh) override;
int AddArray(vtkDataObject* mesh, const std::string &meshName,
int association, const std::string &arrayName) override;
int GetNumberOfArrays(const std::string &meshName, int association,
unsigned int &numberOfArrays) override;
int GetArrayName(const std::string &meshName, int association,
unsigned int index, std::string &arrayName) override;
int ReleaseData() override;
protected:
DataAdaptor();
......
#include "DataAdaptor.h"
#include "Error.h"
#include "vtkCellData.h"
#include "vtkDataObject.h"
#include "vtkDoubleArray.h"
#include "vtkImageData.h"
#include "vtkInformation.h"
#include "vtkObjectFactory.h"
#include <vtkCellData.h>
#include <vtkDataObject.h>
#include <vtkDoubleArray.h>
#include <vtkImageData.h>
#include <vtkInformation.h>
#include <vtkObjectFactory.h>
#include <limits>
namespace parallel3d
{
......@@ -15,6 +18,19 @@ senseiNewMacro(DataAdaptor);
//-----------------------------------------------------------------------------
DataAdaptor::DataAdaptor()
{
this->CellExtent[0] = std::numeric_limits<int>::max();
this->CellExtent[1] = std::numeric_limits<int>::min();
this->CellExtent[2] = std::numeric_limits<int>::max();
this->CellExtent[3] = std::numeric_limits<int>::min();
this->CellExtent[4] = std::numeric_limits<int>::max();
this->CellExtent[5] = std::numeric_limits<int>::min();
this->WholeExtent[0] = std::numeric_limits<int>::max();
this->WholeExtent[1] = std::numeric_limits<int>::min();
this->WholeExtent[2] = std::numeric_limits<int>::max();
this->WholeExtent[3] = std::numeric_limits<int>::min();
this->WholeExtent[4] = std::numeric_limits<int>::max();
this->WholeExtent[5] = std::numeric_limits<int>::min();
}
//-----------------------------------------------------------------------------
......@@ -23,12 +39,10 @@ DataAdaptor::~DataAdaptor()
}
//-----------------------------------------------------------------------------
void DataAdaptor::Initialize(
int g_x, int g_y, int g_z,
int l_x, int l_y, int l_z,
void DataAdaptor::Initialize(int g_x, int g_y, int g_z, int l_x, int l_y, int l_z,
uint64_t start_extents_x, uint64_t start_extents_y, uint64_t start_extents_z,
int tot_blocks_x, int tot_blocks_y, int tot_blocks_z,
int block_id_x, int block_id_y, int block_id_z)
int tot_blocks_x, int tot_blocks_y, int tot_blocks_z, int block_id_x,
int block_id_y, int block_id_z)
{
(void)tot_blocks_x;
(void)tot_blocks_y;
......@@ -36,6 +50,7 @@ void DataAdaptor::Initialize(
(void)block_id_x;
(void)block_id_y;
(void)block_id_z;
// we only really need to save the local extents for our current example. So
// we'll just save that.
this->CellExtent[0] = start_extents_x;
......@@ -52,6 +67,7 @@ void DataAdaptor::Initialize(
this->WholeExtent[3] = g_y;
this->WholeExtent[4] = 0;
this->WholeExtent[5] = g_z;
this->GetInformation()->Set(vtkDataObject::DATA_EXTENT(),
this->WholeExtent, 6);
}
......@@ -74,85 +90,156 @@ void DataAdaptor::ClearArrays()
}
//-----------------------------------------------------------------------------
vtkDataObject* DataAdaptor::GetMesh(bool vtkNotUsed(structure_only))
int DataAdaptor::GetNumberOfArrays(const std::string &meshName,
int association, unsigned int &numberOfArrays)
{
if (!this->Mesh)
numberOfArrays = 0;
if (meshName != "mesh")
{
this->Mesh = vtkSmartPointer<vtkImageData>::New();
this->Mesh->SetExtent(
this->CellExtent[0], this->CellExtent[1] + 1,
this->CellExtent[2], this->CellExtent[3] + 1,
this->CellExtent[4], this->CellExtent[5] + 1);
SENSEI_ERROR("No mesh \"" << meshName << "\"")
return -1;
}
if (association == vtkDataObject::FIELD_ASSOCIATION_CELLS)
{
numberOfArrays = this->Variables.size();
}
return this->Mesh;
return 0;
}
//-----------------------------------------------------------------------------
bool DataAdaptor::AddArray(vtkDataObject* mesh, int association, const std::string& name)
int DataAdaptor::GetArrayName(const std::string &meshName, int association,
unsigned int index, std::string &arrayName)
{
if (association != vtkDataObject::FIELD_ASSOCIATION_CELLS || name.empty())
arrayName = "";
if (meshName != "mesh")
{
return false;
SENSEI_ERROR("No mesh \"" << meshName << "\"")
return -1;
}
VariablesType::iterator iterV = this->Variables.find(name);
if (iterV == this->Variables.end())
if (association != vtkDataObject::FIELD_ASSOCIATION_CELLS)
{
return false;
SENSEI_ERROR("No point data on mesh")
return -1;
}
if (index >= this->Variables.size())
{
SENSEI_ERROR("Index out of bounds")
return -1;
}
#ifndef NDEBUG
vtkImageData* image = vtkImageData::SafeDownCast(mesh);
#endif
assert(image != NULL);
ArraysType::iterator iterA = this->Arrays.find(iterV->first);
if (iterA == this->Arrays.end())
unsigned int count = 0;
VariablesType::iterator end = this->Variables.end();
VariablesType::iterator iter = this->Variables.begin();
for (; iter != end; ++iter, ++count)
{
vtkSmartPointer<vtkDoubleArray>& vtkarray = this->Arrays[iterV->first];
vtkarray = vtkSmartPointer<vtkDoubleArray>::New();
vtkarray->SetName(name.c_str());
const vtkIdType size = (this->CellExtent[1] - this->CellExtent[0] + 1) *
(this->CellExtent[3] - this->CellExtent[2] + 1) *
(this->CellExtent[5] - this->CellExtent[4] + 1);
assert(size == image->GetNumberOfCells());
vtkarray->SetArray(iterV->second, size, 1);
vtkImageData::SafeDownCast(mesh)->GetCellData()->AddArray(vtkarray);
return true;
if (count == index)
{
arrayName = iter->first;
return 0;
}
}
return true;
return 0;
}
//-----------------------------------------------------------------------------
unsigned int DataAdaptor::GetNumberOfArrays(int association)
int DataAdaptor::GetNumberOfMeshes(unsigned int &numMeshes)
{
return (association == vtkDataObject::FIELD_ASSOCIATION_CELLS)?
static_cast<unsigned int>(this->Variables.size()): 0;
numMeshes = 1;
return 0;
}
//-----------------------------------------------------------------------------
std::string DataAdaptor::GetArrayName(int association, unsigned int index)
int DataAdaptor::GetMeshName(unsigned int id, std::string &meshName)
{
if (id != 0)
{
SENSEI_ERROR("Mesh id is out of range. 1 mesh available.")
return -1;
}
meshName = "mesh";
return 0;
}
//-----------------------------------------------------------------------------
int DataAdaptor::GetMesh(const std::string &meshName, bool structureOnly,
vtkDataObject *&mesh)
{
(void)structureOnly;
if (meshName != "mesh")
{
SENSEI_ERROR("No mesh \"" << meshName << "\"")
return -1;
}
if (!this->Mesh)
{
this->Mesh = vtkSmartPointer<vtkImageData>::New();
this->Mesh->SetExtent(
this->CellExtent[0], this->CellExtent[1] + 1,
this->CellExtent[2], this->CellExtent[3] + 1,
this->CellExtent[4], this->CellExtent[5] + 1);
}
mesh = this->Mesh;
return 0;
}
//-----------------------------------------------------------------------------
int DataAdaptor::AddArray(vtkDataObject* mesh, const std::string &meshName,
int association, const std::string& arrayName)
{
if (meshName != "mesh")
{
SENSEI_ERROR("No mesh \"" << meshName << "\"")
return -1;
}
if (association != vtkDataObject::FIELD_ASSOCIATION_CELLS)
{
return std::string();
SENSEI_ERROR("No point data on mesh")
return -1;
}
unsigned int count = 0;
for (VariablesType::iterator iter=this->Variables.begin(), max=this->Variables.end();
iter != max; ++iter, ++count)
VariablesType::iterator iterV = this->Variables.find(arrayName);
if (iterV == this->Variables.end())
{
if (count==index)
{
return iter->first;
}
SENSEI_ERROR("no array named \"" << arrayName << "\"")
return -1;
}
return std::string();
vtkDoubleArrayPtr vtkarray = vtkDoubleArrayPtr::New();
vtkarray->SetName(arrayName.c_str());
const vtkIdType size =
(this->CellExtent[1] - this->CellExtent[0] + 1) *
(this->CellExtent[3] - this->CellExtent[2] + 1) *
(this->CellExtent[5] - this->CellExtent[4] + 1);
vtkarray->SetArray(iterV->second, size, 1);
vtkImageData* image = vtkImageData::SafeDownCast(mesh);
image->GetCellData()->AddArray(vtkarray);
assert(image);
assert(size == image->GetNumberOfCells());
return 0;
}
//-----------------------------------------------------------------------------
void DataAdaptor::ReleaseData()
int DataAdaptor::ReleaseData()
{
this->ClearArrays();
this->Mesh = NULL;
return 0;
}
}
#ifndef PARALLEL3D_DATAADAPTOR_H
#define PARALLEL3D_DATAADAPTOR_H
#include <sensei/DataAdaptor.h>
#include "vtkSmartPointer.h"
#include "sensei/DataAdaptor.h"
#include <vtkSmartPointer.h>
#include <map>
#include <string>
#include <cstdint>
......@@ -22,9 +23,7 @@ public:
senseiTypeMacro(DataAdaptor, sensei::DataAdaptor);
/// Initialize the data adaptor.
void Initialize(
int g_x, int g_y, int g_z,
int l_x, int l_y, int l_z,
void Initialize(int g_x, int g_y, int g_z, int l_x, int l_y, int l_z,
uint64_t start_extents_x, uint64_t start_extents_y, uint64_t start_extents_z,
int tot_blocks_x, int tot_blocks_y, int tot_blocks_z,
int block_id_x, int block_id_y, int block_id_z);
......@@ -35,28 +34,43 @@ public:
/// Clear all arrays.
void ClearArrays();
vtkDataObject* GetMesh(bool structure_only=false) override;
bool AddArray(vtkDataObject* mesh, int association, const std::string& arrayname) override;
unsigned int GetNumberOfArrays(int association) override;
std::string GetArrayName(int association, unsigned int index) override;
void ReleaseData() override;
// SENSEI API
int GetNumberOfMeshes(unsigned int &numMeshes) override;
int GetMeshName(unsigned int id, std::string &meshName) override;
int GetMesh(const std::string &meshName, bool structureOnly,
vtkDataObject *&mesh) override;
int AddArray(vtkDataObject* mesh, const std::string &meshName,
int association, const std::string &arrayName) override;
int GetNumberOfArrays(const std::string &meshName, int association,
unsigned int &numberOfArrays) override;
int GetArrayName(const std::string &meshName, int association,
unsigned int index, std::string &arrayName) override;
int ReleaseData() override;
protected:
DataAdaptor();
~DataAdaptor();
typedef std::map<std::string, double*> VariablesType;
VariablesType Variables;
using VariablesType = std::map<std::string, double*>;
using ArraysType = std::map<std::string, vtkSmartPointer<vtkDoubleArray>>;
using vtkImageDataPtr = vtkSmartPointer<vtkImageData>;
using vtkDoubleArrayPtr = vtkSmartPointer<vtkDoubleArray>;
typedef std::map<std::string, vtkSmartPointer<vtkDoubleArray> > ArraysType;
VariablesType Variables;
ArraysType Arrays;
vtkSmartPointer<vtkImageData> Mesh;
vtkImageDataPtr Mesh;
int CellExtent[6];
int WholeExtent[6];
private:
DataAdaptor(const DataAdaptor&); // not implemented.
void operator=(const DataAdaptor&); // not implemented.
DataAdaptor(const DataAdaptor&) = delete;
void operator=(const DataAdaptor&) = delete;
};
}
......
<
......@@ -2,6 +2,7 @@
#include "ADIOSSchema.h"
#include "DataAdaptor.h"
#include "VTKUtils.h"
#include "Timer.h"
#include "Error.h"
......@@ -40,7 +41,7 @@ senseiNewMacro(ADIOSAnalysisAdaptor);
//----------------------------------------------------------------------------
ADIOSAnalysisAdaptor::ADIOSAnalysisAdaptor() : Comm(MPI_COMM_WORLD),
Schema(nullptr), Method("MPI"), FileName("sensei.bp")
MaxBufferSize(500), Schema(nullptr), Method("MPI"), FileName("sensei.bp")
{
}
......@@ -49,57 +50,131 @@ ADIOSAnalysisAdaptor::~ADIOSAnalysisAdaptor()
{
}
//-----------------------------------------------------------------------------
int ADIOSAnalysisAdaptor::SetDataRequirements(const DataRequirements &reqs)
{
this->Requirements = reqs;
return 0;
}
//-----------------------------------------------------------------------------
int ADIOSAnalysisAdaptor::AddDataRequirement(const std::string &meshName,
int association, const std::vector<std::string> &arrays)
{
this->Requirements.AddRequirement(meshName, association, arrays);
return 0;
}
//----------------------------------------------------------------------------
bool ADIOSAnalysisAdaptor::Execute(DataAdaptor* data)
bool ADIOSAnalysisAdaptor::Execute(DataAdaptor* dataAdaptor)
{
timer::MarkEvent mark("ADIOSAnalysisAdaptor::Execute");
vtkDataObject* dobj = data->GetCompleteMesh();
unsigned long timeStep = data->GetDataTimeStep();
double time = data->GetDataTime();
// 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))
{
SENSEI_ERROR("Failed to initialze dataAdaptor description")
return -1;
}
SENSEI_WARNING("No subset specified. Writing all available data")
}
// collect the specified data objects
std::vector<vtkDataObject*> objects;
std::vector<std::string> objectNames;
this->InitializeADIOS(dobj);
this->WriteTimestep(timeStep, time, dobj);
MeshRequirementsIterator mit =
this->Requirements.GetMeshRequirementsIterator();
for (; mit; ++mit)
{
// get the mesh
vtkDataObject* dobj = nullptr;
if (dataAdaptor->GetMesh(mit.MeshName(), mit.StructureOnly(), dobj))
{
SENSEI_ERROR("Failed to get mesh \"" << mit.MeshName() << "\"")
return -1;
}
// add the required arrays
ArrayRequirementsIterator ait =
this->Requirements.GetArrayRequirementsIterator(mit.MeshName());
for (; ait; ++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 -1;
}
}
// add to the collection
objects.push_back(dobj);
objectNames.push_back(mit.MeshName());
}
unsigned long timeStep = dataAdaptor->GetDataTimeStep();
double time = dataAdaptor->GetDataTime();
if (this->InitializeADIOS(objectNames, objects) ||
this->WriteTimestep(timeStep, time, objectNames, objects))
return false;
return true;
}
//----------------------------------------------------------------------------
void ADIOSAnalysisAdaptor::InitializeADIOS(vtkDataObject *dobj)
int ADIOSAnalysisAdaptor::InitializeADIOS(
const std::vector<std::string> &objectNames,
const std::vector<vtkDataObject*> &objects)
{
if (this->Schema)
return;
timer::MarkEvent mark("ADIOSAnalysisAdaptor::IntializeADIOS");
if (!this->Schema)
{
timer::MarkEvent mark("ADIOSAnalysisAdaptor::IntializeADIOS");
// initialize adios
adios_init_noxml(this->Comm);
// initialize adios