Commit e9b0e9d9 authored by Burlen Loring's avatar Burlen Loring

Merge branch 'vtk_writer_improvements' into 'master'

vtk writer improvements

See merge request !143
parents c4e45f1c 7942bf96
......@@ -3,7 +3,7 @@ if (ENABLE_VTK_MPI)
list(APPEND SENSEI_VTK_COMPONENTS vtkParallelMPI)
endif()
if (ENABLE_VTK_IO)
list(APPEND SENSEI_VTK_COMPONENTS vtkIOXML)
list(APPEND SENSEI_VTK_COMPONENTS vtkIOXML vtkIOLegacy)
if (ENABLE_VTK_MPI)
list(APPEND SENSEI_VTK_COMPONENTS vtkIOParallelXML)
endif()
......
......@@ -759,21 +759,25 @@ int ConfigurableAnalysis::InternalsType::AddPosthocIO(pugi::xml_node node)
std::string outputDir = node.attribute("output_dir").as_string("./");
std::string fileName = node.attribute("file_name").as_string("data");
std::string mode = node.attribute("mode").as_string("visit");
std::string writer = node.attribute("writer").as_string("xml");
std::string ghostArrayName = node.attribute("ghost_array_name").as_string("");
auto adapter = vtkSmartPointer<VTKPosthocIO>::New();
auto adaptor = vtkSmartPointer<VTKPosthocIO>::New();
if (this->Comm != MPI_COMM_NULL)
adapter->SetCommunicator(this->Comm);
adaptor->SetCommunicator(this->Comm);
if (adapter->SetOutputDir(outputDir) || adapter->SetMode(mode) ||
adapter->SetDataRequirements(req))
adaptor->SetGhostArrayName(ghostArrayName);
if (adaptor->SetOutputDir(outputDir) || adaptor->SetMode(mode) ||
adaptor->SetWriter(writer) || adaptor->SetDataRequirements(req))
{
SENSEI_ERROR("Failed to initialize the VTKPosthocIO analysis")
return -1;
}
this->TimeInitialization(adapter);
this->Analyses.push_back(adapter.GetPointer());
this->TimeInitialization(adaptor);
this->Analyses.push_back(adaptor.GetPointer());
SENSEI_STATUS("Configured VTKPosthocIO")
......
This diff is collapsed.
......@@ -7,6 +7,7 @@
#include <vtkCellData.h>
#include <vtkCompositeDataIterator.h>
#include <vtkMultiBlockDataSet.h>
#include <vtkUniformGridAMR.h>
#include <vtkDataArray.h>
#include <vtkDataArrayTemplate.h>
#include <vtkDataObject.h>
......@@ -29,6 +30,7 @@
#include <vtkAlgorithm.h>
#include <vtkCompositeDataPipeline.h>
#include <vtkXMLDataSetWriter.h>
#include <vtkDataSetWriter.h>
#include <mpi.h>
......@@ -89,7 +91,8 @@ namespace sensei
senseiNewMacro(VTKPosthocIO);
//-----------------------------------------------------------------------------
VTKPosthocIO::VTKPosthocIO() : OutputDir("./"), Mode(MODE_PARAVIEW)
VTKPosthocIO::VTKPosthocIO() :
OutputDir("./"), Mode(MODE_PARAVIEW), Writer(WRITER_VTK_XML)
{}
//-----------------------------------------------------------------------------
......@@ -143,6 +146,67 @@ int VTKPosthocIO::SetMode(std::string modeStr)
return 0;
}
//-----------------------------------------------------------------------------
int VTKPosthocIO::SetWriter(int writer)
{
if (!(writer == VTKPosthocIO::WRITER_VTK_LEGACY) ||
(writer == VTKPosthocIO::WRITER_VTK_XML))
{
SENSEI_ERROR("Invalid writer " << writer)
return -1;
}
this->Writer = writer;
return 0;
}
//-----------------------------------------------------------------------------
int VTKPosthocIO::SetWriter(std::string writerStr)
{
unsigned int n = writerStr.size();
for (unsigned int i = 0; i < n; ++i)
writerStr[i] = tolower(writerStr[i]);
int writer = 0;
if (writerStr == "legacy")
{
writer = VTKPosthocIO::WRITER_VTK_LEGACY;
}
else if (writerStr == "xml")
{
writer = VTKPosthocIO::WRITER_VTK_XML;
}
else
{
SENSEI_ERROR("invalid writer \"" << writerStr << "\"")
return -1;
}
this->Writer = writer;
return 0;
}
//-----------------------------------------------------------------------------
void VTKPosthocIO::SetGhostArrayName(const std::string &name)
{
this->GhostArrayName = name;
}
//-----------------------------------------------------------------------------
std::string VTKPosthocIO::GetGhostArrayName()
{
if (this->GhostArrayName.empty())
{
if (this->Mode == VTKPosthocIO::MODE_VISIT)
return "avtGhostZones";
if (this->Mode == VTKPosthocIO::MODE_PARAVIEW)
return "vtkGhostType";
}
return this->GhostArrayName;
}
//-----------------------------------------------------------------------------
int VTKPosthocIO::SetDataRequirements(const DataRequirements &reqs)
{
......@@ -262,7 +326,8 @@ bool VTKPosthocIO::Execute(DataAdaptor* dataAdaptor)
if (!this->HaveBlockInfo[meshName])
{
if (!it->IsDoneWithTraversal())
this->BlockExt[meshName] = getBlockExtension(it->GetCurrentDataObject());
this->BlockExt[meshName] = this->Writer == VTKPosthocIO::WRITER_VTK_LEGACY ?
".vtk" : getBlockExtension(it->GetCurrentDataObject());
this->FileId[meshName] = 0;
this->HaveBlockInfo[meshName] = 1;
......@@ -275,24 +340,59 @@ bool VTKPosthocIO::Execute(DataAdaptor* dataAdaptor)
++nBlocks;
it->SetSkipEmptyNodes(1);
// amr meshes indices start from 0 while multiblock starts at 1
long bidShift = 1;
if (dynamic_cast<vtkUniformGridAMR*>(cd.GetPointer()))
bidShift = 0;
// write the blocks
vtkXMLDataSetWriter *writer = vtkXMLDataSetWriter::New();
for (it->InitTraversal(); !it->IsDoneWithTraversal(); it->GoToNextItem())
{
long blockId = std::max(0u, it->GetCurrentFlatIndex() - 1);
vtkDataSet *ds = dynamic_cast<vtkDataSet*>(it->GetCurrentDataObject());
if (!ds)
{
// this should never happen
SENSEI_ERROR("Block at " << it->GetCurrentFlatIndex() << " is null")
return false;
}
long blockId = it->GetCurrentFlatIndex() - bidShift;
if (blockId < 0)
{
// this should never happen
SENSEI_ERROR("Negative index! Dataset is " << cd->GetClassName())
return false;
}
std::string fileName =
getBlockFileName(this->OutputDir, meshName, blockId,
this->FileId[meshName], this->BlockExt[meshName]);
writer->SetInputData(it->GetCurrentDataObject());
writer->SetDataModeToAppended();
writer->EncodeAppendedDataOff();
writer->SetCompressorTypeToNone();
writer->SetFileName(fileName.c_str());
writer->Write();
vtkDataArray *ga = ds->GetCellData()->GetArray("vtkGhostType");
if (ga)
ga->SetName(this->GetGhostArrayName().c_str());
if (this->Writer == VTKPosthocIO::WRITER_VTK_LEGACY)
{
vtkDataSetWriter *writer = vtkDataSetWriter::New();
writer->SetInputData(ds);
writer->SetFileName(fileName.c_str());
writer->SetFileTypeToBinary();
writer->Write();
writer->Delete();
}
else
{
vtkXMLDataSetWriter *writer = vtkXMLDataSetWriter::New();
writer->SetInputData(ds);
writer->SetDataModeToAppended();
writer->EncodeAppendedDataOff();
writer->SetCompressorTypeToNone();
writer->SetFileName(fileName.c_str());
writer->Write();
writer->Delete();
}
}
writer->Delete();
this->FileId[meshName] += 1;
......@@ -368,7 +468,7 @@ int VTKPosthocIO::Finalize()
for (long j = 0; j < nBlocks; ++j)
{
std::string fileName =
getBlockFileName(this->OutputDir, meshName, j, i, blockExt);
getBlockFileName("./", meshName, j, i, blockExt);
pvdFile << "<DataSet timestep=\"" << times[i]
<< "\" group=\"\" part=\"" << j << "\" file=\"" << fileName
......@@ -383,35 +483,82 @@ int VTKPosthocIO::Finalize()
}
else if (this->Mode == VTKPosthocIO::MODE_VISIT)
{
std::string visitFileName = this->OutputDir + "/" + meshName + ".visit";
ofstream visitFile(visitFileName);
if (!visitFile)
{
SENSEI_ERROR("Failed to open " << visitFileName << " for writing")
return -1;
}
// TODO -- does .visit file support a changing number of blocks?
// does the number of blocks change?
// if so dump one visit file per timestep, otherwise one visit file for
// the series
int staticMesh = 1;
long nBlocks = numBlocks[0];
visitFile << "!NBLOCKS " << nBlocks << endl;
for (long i = 0; i < nSteps; ++i)
{
visitFile << "!TIME " << times[i] << endl;
if (numBlocks[i] != nBlocks)
{
staticMesh = 0;
break;
}
}
for (long i = 0; i < nSteps; ++i)
if (staticMesh)
{
for (long j = 0; j < nBlocks; ++j)
// write a single .visit file for the time series
std::string visitFileName = this->OutputDir + "/" + meshName + ".visit";
ofstream visitFile(visitFileName);
if (!visitFile)
{
std::string fileName =
getBlockFileName(this->OutputDir, meshName, j, i, blockExt);
SENSEI_ERROR("Failed to open " << visitFileName << " for writing")
return -1;
}
visitFile << fileName << endl;
visitFile << "!NBLOCKS " << nBlocks << std::endl;
for (long i = 0; i < nSteps; ++i)
visitFile << "!TIME " << times[i] << std::endl;
for (long i = 0; i < nSteps; ++i)
{
for (long j = 0; j < nBlocks; ++j)
{
std::string fileName =
getBlockFileName("./", meshName, j, i, blockExt);
visitFile << fileName << std::endl;
}
}
visitFile.close();
}
else
{
// write a .visit file per step
for (long i = 0; i < nSteps; ++i)
{
std::ostringstream oss;
oss << this->OutputDir << "/" << meshName << "_"
<< std::setw(5) << std::setfill('0') << i << ".visit";
std::string visitFileName = oss.str();
ofstream visitFile(visitFileName);
if (!visitFile)
{
SENSEI_ERROR("Failed to open " << visitFileName << " for writing")
return -1;
}
nBlocks = numBlocks[i];
visitFile << "!NBLOCKS " << nBlocks << std::endl;
visitFile << "!TIME " << times[i] << std::endl;
for (long j = 0; j < nBlocks; ++j)
{
std::string fileName = getBlockFileName("./", meshName, j, i, blockExt);
visitFile << fileName << std::endl;
}
visitFile.close();
}
}
}
else
{
......
......@@ -34,9 +34,19 @@ public:
enum {MODE_PARAVIEW=0, MODE_VISIT=1};
int SetMode(int mode);
int SetMode(std::string mode);
// sets the writer class. options are VTK legacy writer
// or the VTK XML writer.
enum {WRITER_VTK_LEGACY=0, WRITER_VTK_XML=1};
int SetWriter(int writer);
int SetWriter(std::string writer);
// if set this overrrides the default of vtkGhostType
// for ParaView and avtGhostZones for VisIt
void SetGhostArrayName(const std::string &name);
std::string GetGhostArrayName();
/// data requirements tell the adaptor what to push
/// if none are given then all data is pushed.
int SetDataRequirements(const DataRequirements &reqs);
......@@ -60,6 +70,8 @@ private:
std::string OutputDir;
DataRequirements Requirements;
int Mode;
int Writer;
std::string GhostArrayName;
template<typename T>
using NameMap = std::map<std::string, T>;
......
......@@ -5,7 +5,7 @@ SENSEI_CFLAGS=`echo ${SENSEI_INCLUDES} | sed -s 's/:/\n/g' | sed -s '/^[^/].*$/d
SENSEI_INCLUDES=`echo ${SENSEI_INCLUDES} | sed -s 's/:/\n/g' | sed -s '/^[^/].*$/d' | tr '\n' ' '`
SENSEI_LIBRARIES=@SENSEI_LIBRARIES@
SENSEI_LIBRARIES="-Wl,--start-group `echo ${SENSEI_LIBRARIES} | sed -s 's/:/\n/g' | sed -s '/^[^/].*$/d' | tr '\n' ' '` -Wl,--end-group"
SENSEI_LIBRARIES="-ldl -Wl,--start-group `echo ${SENSEI_LIBRARIES} | sed -s 's/:/\n/g' | sed -s '/^[^/].*$/d' | tr '\n' ' '` -Wl,--end-group"
if [[ $# > 0 ]]
then
......
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