Commit 82f25ed1 authored by Corey Wetterer-Nelson's avatar Corey Wetterer-Nelson
Browse files

add vector variables to AMReXGridReader

This upgrade parses the variable names from an AMReX header file and
sorts out vector variables based on a configurable prefix (default:
amrexvec). Vector components read in are copied into a
VTKSOADataArrayTemplate.
parent f526b3e6
Pipeline #247567 waiting for manual action with stages
......@@ -343,9 +343,8 @@ void vtkAMReXGridReader::SetUpDataArraySelections()
{
return;
}
int numberOfVariables = this->Internal->Header->variableNamesSize;
for (int i = 0; i < numberOfVariables; ++i)
for (const auto& variable : this->Internal->Header->parsedVariableNames)
{
this->CellDataArraySelection->AddArray(this->Internal->Header->variableNames[i].c_str());
this->CellDataArraySelection->AddArray(variable.first.c_str());
}
}
......@@ -222,6 +222,55 @@ bool vtkAMReXGridHeader::Parse(const std::string& headerData)
return true;
}
void vtkAMReXGridHeader::SetVectorNamePrefix(const std::string& prefix)
{
this->vectorNamePrefix = prefix;
}
void vtkAMReXGridHeader::SetNameDelimiter(const char delim)
{
this->nameDelim = delim;
}
std::string vtkAMReXGridHeader::GetBaseVariableName(const std::string& name)
{
std::string baseName = name;
const std::size_t pos = baseName.find_first_of(this->nameDelim);
const std::string prefix = baseName.substr(0, pos);
if (prefix == this->vectorNamePrefix)
{
baseName = baseName.substr(pos + 1);
std::size_t posSuffix = baseName.find_last_of(this->nameDelim);
baseName = baseName.substr(0, posSuffix);
}
return baseName;
}
int vtkAMReXGridHeader::CheckComponent(const std::string& name)
{
const std::size_t pos = name.find_last_of(this->nameDelim);
// we expect to use the character just past pos
// so we don't want to accidentially jump outside the string
if (pos > name.size() - 1)
{
return -1;
}
const std::string suffix = name.substr(pos + 1);
if (suffix == "x")
{
return 0;
}
if (suffix == "y")
{
return 1;
}
if (suffix == "z")
{
return 2;
}
return -1;
}
bool vtkAMReXGridHeader::ParseGenericHeader(const std::string& headerData)
{
char c;
......@@ -237,6 +286,14 @@ bool vtkAMReXGridHeader::ParseGenericHeader(const std::string& headerData)
for (int cc = 0; cc < this->variableNamesSize; ++cc)
{
hstream >> this->variableNames[cc];
// build vector name map
std::string baseName = this->GetBaseVariableName(this->variableNames[cc]);
int component = this->CheckComponent(this->variableNames[cc]);
// resize variable map for scalar or vector
parsedVariableNames[baseName].resize(component < 0 ? 1 : 3);
component = (component < 0) ? 0 : component;
parsedVariableNames[baseName][component] = cc;
}
hstream >> this->dim;
if (this->dim != 1 && this->dim != 2 && this->dim != 3)
......@@ -853,7 +910,6 @@ void vtkAMReXGridReaderInternal::GetBlockAttribute(
// - Patrick O'Leary
//
int linefeed = is.tellg();
is.seekg((linefeed + 1) + (offsetOfAttribute * (numberOfPoints * ird->numBytes())));
if (debugReader)
{
......@@ -862,37 +918,41 @@ void vtkAMReXGridReaderInternal::GetBlockAttribute(
std::cout << std::endl;
}
// read every component of the variable into the buffers vector
std::string attributeName(attribute);
int nComps = this->Header->parsedVariableNames[attributeName].size();
std::vector<std::vector<char>> buffers(nComps);
for (int i = 0; i < nComps; ++i)
{
int compIndex = this->Header->parsedVariableNames[attributeName][i];
std::string compName = this->Header->variableNames[compIndex];
int offsetOfAttribute = this->GetOffsetOfAttribute(compName.c_str());
is.seekg((linefeed + 1) + (offsetOfAttribute * (numberOfPoints * ird->numBytes())));
buffers[i].resize(numberOfPoints * ird->numBytes());
this->ReadBlockAttribute(is, numberOfPoints, ird->numBytes(), buffers[i].data());
}
RealDescriptor* ord = nullptr;
// copy buffers into vtkSOADataArray
if (ird->numBytes() == 4)
{
vtkNew<vtkFloatArray> dataArray;
dataArray->SetName(attribute);
dataArray->SetNumberOfTuples(numberOfPoints);
float* arrayPtr = static_cast<float*>(dataArray->GetPointer(0));
std::vector<char> buffer(numberOfPoints * ird->numBytes());
this->ReadBlockAttribute(is, numberOfPoints, ird->numBytes(), buffer.data());
RealDescriptor* ord =
new RealDescriptor(ieee_float, little_float_order, 4); // we desire ieee little endian
this->Convert(arrayPtr, buffer.data(), numberOfPoints, *ord, *ird);
vtkNew<vtkSOADataArrayTemplate<float>> dataArray;
ord = new RealDescriptor(ieee_float, little_float_order, 4);
this->CreateVTKAttributeArray(
dataArray.Get(), ord, ird, buffers, numberOfPoints, attributeName);
pDataSet->GetCellData()->AddArray(dataArray);
delete ird;
delete ord;
}
else
{
vtkNew<vtkDoubleArray> dataArray;
dataArray->SetName(attribute);
dataArray->SetNumberOfTuples(numberOfPoints);
double* arrayPtr = static_cast<double*>(dataArray->GetPointer(0));
std::vector<char> buffer(numberOfPoints * ird->numBytes());
this->ReadBlockAttribute(is, numberOfPoints, ird->numBytes(), buffer.data());
RealDescriptor* ord =
new RealDescriptor(ieee_double, little_double_order, 8); // we desire ieee little endian
this->Convert(arrayPtr, buffer.data(), numberOfPoints, *ord, *ird);
vtkNew<vtkSOADataArrayTemplate<double>> dataArray;
ord = new RealDescriptor(ieee_double, little_double_order, 8);
this->CreateVTKAttributeArray(
dataArray.Get(), ord, ird, buffers, numberOfPoints, attributeName);
pDataSet->GetCellData()->AddArray(dataArray);
arrayPtr = nullptr;
delete ird;
delete ord;
}
delete ord;
delete ird;
if (debugReader)
{
std::cout << is.tellg() << " "
......
......@@ -24,10 +24,12 @@
#define vtkAMReXGridReaderInternal_h
#ifndef __VTK_WRAP__
#include <map>
#include <string>
#include <vector>
#include "vtkDataSet.h"
#include "vtkSOADataArrayTemplate.h"
class vtkIndent;
......@@ -91,6 +93,19 @@ public:
std::string versionName;
int variableNamesSize;
std::vector<std::string> variableNames;
// prefix string indicating a variable is a vector component
// Note: this prefix will be removed from any variable name
// whether or not the variable name is a properly formed
// vector variable name (contains a proper postfix)
std::string vectorNamePrefix = "amrexvec";
// delimeter must be the same after prefix and before postfix
char nameDelim = '_';
// variableNames map to (potentially a collection of) variableNames indices
std::map<std::string, std::vector<int>> parsedVariableNames;
int dim;
double time;
int finestLevel;
......@@ -114,6 +129,21 @@ public:
void PrintSelfGenericHeader(std::ostream& os, vtkIndent indent);
bool Parse(const std::string& headerData);
bool ParseGenericHeader(const std::string& headerData);
void SetVectorNamePrefix(const std::string& prefix);
void SetNameDelimiter(const char delim);
private:
// if the vectorNamePrefix is detected at the beginning of the name,
// remove it along with the expected x/y/z postfix. Otherwise, return
// the original string
std::string GetBaseVariableName(const std::string& name);
// returns 0 if postfix is x, 1 for y and 2 for z. returns -1 otherwise
int CheckComponent(const std::string& name);
// check if name has the vectorNamePrefix
bool HasVectorPrefix(const std::string& name);
};
// ----------------------------------------------------------------------------
......@@ -216,6 +246,11 @@ public:
void PermuteOrder(
void* out, const void* in, long nitems, const int* outord, const int* inord, int REALSIZE);
template <typename T>
void CreateVTKAttributeArray(vtkSOADataArrayTemplate<T>* dataArray, const RealDescriptor* ord,
const RealDescriptor* ird, const std::vector<std::vector<char>>& buffers,
const int numberOfPoints, const std::string& attribute);
bool headersAreRead;
bool debugReader;
std::string FileName;
......@@ -225,6 +260,23 @@ public:
friend class vtkAMReXGridLeveHeader;
};
template <typename T>
void vtkAMReXGridReaderInternal::CreateVTKAttributeArray(vtkSOADataArrayTemplate<T>* dataArray,
const RealDescriptor* ord, const RealDescriptor* ird,
const std::vector<std::vector<char>>& buffers, const int numberOfPoints,
const std::string& attribute)
{
const int nComps = this->Header->parsedVariableNames[attribute].size();
dataArray->SetName(attribute.c_str());
dataArray->SetNumberOfComponents(nComps);
dataArray->SetNumberOfTuples(numberOfPoints);
for (int i = 0; i < nComps; ++i)
{
T* arrayPtr = dataArray->GetComponentArrayPointer(i);
this->Convert(arrayPtr, buffers[i].data(), numberOfPoints, *ord, *ird);
}
}
// ----------------------------------------------------------------------------
// Class vtkAMReXGridReaderInternal ( end )
// ----------------------------------------------------------------------------
......
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