Commit 1133c56e authored by Andrew J. Burns (Cont's avatar Andrew J. Burns (Cont

changes to file splitting, hyperslab not completely working yet. changes to...

changes to file splitting, hyperslab not completely working yet. changes to Fortran to allow for polylines and releasing data after standard write
parent cf18fe6b
......@@ -78,6 +78,7 @@ swig -v -c++ -python -o XdmfPython.cpp Xdmf.i
#include <XdmfItem.hpp>
#include <XdmfItemProperty.hpp>
#include <XdmfSharedPtr.hpp>
#include <XdmfSparseMatrix.hpp>
#include <XdmfSystemUtils.hpp>
#include <XdmfVisitor.hpp>
#include <XdmfWriter.hpp>
......
......@@ -54,6 +54,7 @@ XdmfGraph::getItemTag() const
unsigned int
XdmfGraph::getNumberNodes() const
{
//The number of nodes is equal to the number of rows or columns. Either will work.
return this->getNumberRows();
}
......
......@@ -53,7 +53,7 @@ public:
virtual ~XdmfGraph();
LOKI_DEFINE_VISITABLE(XdmfGraph, XdmfSparseMatrix);
XDMF_CHILDREN(XdmfAttribute, Attribute, Name);
XDMF_CHILDREN(XdmfGraph, XdmfAttribute, Attribute, Name);
static const std::string ItemTag;
std::string getItemTag() const;
......
......@@ -22,9 +22,12 @@
/*****************************************************************************/
#include <boost/tokenizer.hpp>
#include <boost/assign.hpp>
#include <limits>
#include <sstream>
#include <utility>
#include <stack>
#include <math.h>
#include "XdmfArray.hpp"
#include "XdmfArrayType.hpp"
#include "XdmfHDF5Controller.hpp"
......@@ -32,6 +35,21 @@
#include "XdmfVisitor.hpp"
#include "XdmfError.hpp"
std::string XdmfArray::mSupportedOperations = "|#()";
const std::string XdmfArray::mValidVariableChars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890_:.";
const std::string XdmfArray::mValidDigitChars = "-1234567890.";
//list the priorities for the operations, based on the order of operations
//the index of the corresponding operation in validOperationChars is the same as the index of its priority in this array
int XdmfArray::mOperationPriority [8] = {2, 1, 0, 0};
//the higher the value, the earlier the operation is evaluated in the order of operations
//with the exception of parenthesis which are evaluated as soon as the closing parenthesis is found
//note, it doesn't handle overloaded functions well. Will generate errors unless overload methods are typecast.
std::map<std::string, shared_ptr<XdmfArray> (*)(std::vector<shared_ptr<XdmfArray> >)> XdmfArray::arrayFunctions = boost::assign::map_list_of ("SUM", (shared_ptr<XdmfArray> (*)(std::vector<shared_ptr<XdmfArray> >))XdmfArray::sum) ("AVE", (shared_ptr<XdmfArray> (*)(std::vector<shared_ptr<XdmfArray> >))XdmfArray::ave);
std::map<char, shared_ptr<XdmfArray> (*)(shared_ptr<XdmfArray>, shared_ptr<XdmfArray>)> XdmfArray::operations = boost::assign::map_list_of ('|', XdmfArray::chunk) ('#', XdmfArray::interlace);
XDMF_CHILDREN_IMPLEMENTATION(XdmfArray,
XdmfHeavyDataController,
HeavyDataController,
......@@ -46,7 +64,7 @@ public:
}
void
operator()(const boost::blank &) const
operator()(const boost::blank & array) const
{
return;
}
......@@ -67,7 +85,7 @@ public:
mArray->mArray);
}
private:
private:
XdmfArray * const mArray;
};
......@@ -82,7 +100,7 @@ public:
}
void
operator()(const boost::blank &) const
operator()(const boost::blank & array) const
{
return;
}
......@@ -96,7 +114,7 @@ public:
template<typename T>
void
operator()(const boost::shared_array<const T> &) const
operator()(const boost::shared_array<const T> & array) const
{
mArray->internalizeArrayPointer();
boost::apply_visitor(*this,
......@@ -179,10 +197,10 @@ public:
}
shared_ptr<const XdmfArrayType>
operator()(const boost::blank &) const
operator()(const boost::blank & array) const
{
if(mHeavyDataController.size > 0) {
return mHeavyDataControllers[0]->getType();
if(mHeavyDataController) {
return mHeavyDataController->getType();
}
return XdmfArrayType::Uninitialized();
}
......@@ -214,7 +232,7 @@ public:
}
unsigned int
operator()(const boost::blank &) const
operator()(const boost::blank & array) const
{
return 0;
}
......@@ -228,7 +246,7 @@ public:
template<typename T>
unsigned int
operator()(const boost::shared_array<const T> &) const
operator()(const boost::shared_array<const T> & array) const
{
return 0;
}
......@@ -243,7 +261,7 @@ public:
}
const void *
operator()(const boost::blank &) const
operator()(const boost::blank & array) const
{
return NULL;
}
......@@ -314,7 +332,7 @@ public:
}
std::string
operator()(const boost::blank &) const
operator()(const boost::blank & array) const
{
return "";
}
......@@ -361,7 +379,7 @@ public:
}
void
operator()(const boost::blank &) const
operator()(const boost::blank & array) const
{
mArray->initialize(mArrayToCopy->getArrayType());
boost::apply_visitor(*this,
......@@ -417,14 +435,14 @@ public:
}
void
operator()(const boost::blank &) const
operator()(const boost::blank & array) const
{
return;
}
template<typename T>
void
operator()(const shared_ptr<std::vector<T> > &) const
operator()(const shared_ptr<std::vector<T> > & array) const
{
return;
}
......@@ -445,33 +463,6 @@ private:
XdmfArray * const mArray;
};
class XdmfArray::IsInitialized : public boost::static_visitor<bool> {
public:
IsInitialized()
{
}
bool
operator()(const boost::blank &) const
{
return false;
}
template<typename T>
bool
operator()(const shared_ptr<std::vector<T> > &) const
{
return true;
}
template<typename T>
bool
operator()(const T &) const
{
return true;
}
};
class XdmfArray::Reserve : public boost::static_visitor<void> {
public:
......@@ -483,7 +474,7 @@ public:
}
void
operator()(const boost::blank &) const
operator()(const boost::blank & array) const
{
mArray->mTmpReserveSize = mSize;
}
......@@ -497,7 +488,7 @@ public:
template<typename T>
void
operator()(const boost::shared_array<const T> &) const
operator()(const boost::shared_array<const T> & array) const
{
mArray->internalizeArrayPointer();
boost::apply_visitor(*this,
......@@ -519,10 +510,15 @@ public:
}
unsigned int
operator()(const boost::blank &) const
operator()(const boost::blank & array) const
{
if(mArray->mHeavyDataControllers.size() > 0) {
return mArray->mHeavyDataControllers[0]->getSize();//modify this to compile all controllers
if(mArray->mHeavyDataControllers.size()>0) {
int total = 0;
for (int i = 0; i < mArray->mHeavyDataControllers.size(); i++)
{
total += mArray->mHeavyDataControllers[i]->getSize();
}
return total;//modify this to compile all controllers
}
return 0;
}
......@@ -536,14 +532,14 @@ public:
template<typename T>
unsigned int
operator()(const boost::shared_array<const T> &) const
operator()(const boost::shared_array<const T> & array) const
{
return mArray->mArrayPointerNumValues;
}
private:
const XdmfArray * const mArray;
const XdmfArray * const mArray;
};
shared_ptr<XdmfArray>
......@@ -569,7 +565,7 @@ const std::string XdmfArray::ItemTag = "DataItem";
void
XdmfArray::clear()
{
boost::apply_visitor(Clear(this),
boost::apply_visitor(Clear(this),
mArray);
mDimensions.clear();
}
......@@ -583,6 +579,734 @@ XdmfArray::erase(const unsigned int index)
mDimensions.clear();
}
//This function and the functions it depends on are reimplemented in XdmfCore.i in order to properly interface with python.
//There are differences between the versions, but the overall algorithm remains mostly the same.
shared_ptr<XdmfArray>
XdmfArray::evaluateExpression(std::string expression, std::map<std::string, shared_ptr<XdmfArray> > variables)
{
std::stack<shared_ptr<XdmfArray> > valueStack;
std::stack<char> operationStack;
//string is parsed left to right
//elements of the same priority are evaluated right to left
for (int i = 0; i < expression.size(); i++)
{
if (mValidDigitChars.find(expression[i]) != std::string::npos)//found to be a digit
{
//progress until a non-digit is found
int valueStart = i;
while (mValidDigitChars.find(expression[i + 1]) != std::string::npos)
{
i++;
}
//push back to the value stack
shared_ptr<XdmfArray> valueArray = XdmfArray::New();
valueArray->insert(0, atof(expression.substr(valueStart, i + 1 - valueStart).c_str()));//use this to convert to double
valueStack.push(valueArray);
}
else if (mValidVariableChars.find(expression[i]) != std::string::npos)//found to be a variable
{
int valueStart = i;
//progress until a nonvariable value is found
while (mValidVariableChars.find(expression[i + 1]) != std::string::npos)
{
i++;
}
//convert to equivalent
if (variables.find(expression.substr(valueStart, i + 1 - valueStart)) == variables.end())
{
if (arrayFunctions.find(expression.substr(valueStart, i + 1 - valueStart)) == arrayFunctions.end())
{
XdmfError::message(XdmfError::FATAL,
"Error: Invalid Variable in evaluateExpression " + expression.substr(valueStart, i + 1 - valueStart));
}
else
{
std::string currentFunction = expression.substr(valueStart, i + 1 - valueStart);
//check if next character is an open parenthesis
if (expression[i+1] != '(')
{
XdmfError::message(XdmfError::FATAL,
"Error: No values supplied to function " + expression.substr(valueStart, i + 1 - valueStart));
}
//if it is grab the string between paranthesis
i = i + 2;
valueStart = i;
int numOpenParenthesis = 0;
while ((expression[i] != ')' || numOpenParenthesis) && i < expression.size())
{
if (expression[i] == '(')
{
numOpenParenthesis++;
}
else if (expression[i] == ')')
{
numOpenParenthesis--;
}
i++;
}
std::string functionParameters = expression.substr(valueStart, i - valueStart);
std::vector<shared_ptr<XdmfArray> > parameterVector;
//split that string at commas
size_t parameterSplit = 0;
while (parameterSplit != std::string::npos)
{
parameterSplit = 0;
parameterSplit = functionParameters.find_first_of(",", parameterSplit);
//feed the substrings to the parse function
if (parameterSplit == std::string::npos)
{
parameterVector.push_back(evaluateExpression(functionParameters, variables));
}
else
{
parameterVector.push_back(evaluateExpression(functionParameters.substr(0, parameterSplit), variables));
functionParameters = functionParameters.substr(parameterSplit+1);
}
}
valueStack.push(evaluateFunction(parameterVector, currentFunction));
}
}
else
{
//push equivalent to value stack
valueStack.push(variables.find(expression.substr(valueStart, i + 1 - valueStart))->second);
}
}
else if (mSupportedOperations.find(expression[i]) != std::string::npos)//found to be an operation
{
//pop operations off the stack until one of a lower or equal importance is found
if (operationStack.size() > 0)
{
if (expression[i] == ')')
{
//to close a parenthesis pop off all operations until another parentheis is found
while (operationStack.size() > 0 && operationStack.top() != '(')
{
if (valueStack.size() < 2)//must be at least two values for this loop to work properly
{
XdmfError::message(XdmfError::FATAL,
"Error: Not Enough Values in evaluateExpression");
}
else
{
shared_ptr<XdmfArray> val2 = valueStack.top();
valueStack.pop();
shared_ptr<XdmfArray> val1 = valueStack.top();
valueStack.pop();
valueStack.push(evaluateOperation(val1, val2, operationStack.top()));
operationStack.pop();
}
}
operationStack.pop();
}
else if (expression[i] == '(')
{
//just add it if it's a start parenthesis
//nothing happens here in that case
//addition happens after the if statement
}
else
{
int operationLocation = getOperationPriority(expression[i]);
int topOperationLocation = getOperationPriority(operationStack.top());
//see order of operations to determine importance
while (operationStack.size() > 0 && operationLocation < topOperationLocation)
{
if (valueStack.size() < 2)//must be at least two values for this loop to work properly
{
XdmfError::message(XdmfError::FATAL,
"Error: Not Enough Values in evaluateExpression");
}
else
{
shared_ptr<XdmfArray> val2 = valueStack.top();
valueStack.pop();
shared_ptr<XdmfArray> val1 = valueStack.top();
valueStack.pop();
valueStack.push(evaluateOperation(val1, val2, operationStack.top()));
operationStack.pop();
if (operationStack.size() == 0)
{
break;
}
topOperationLocation = getOperationPriority(operationStack.top());
}
}
}
}
if (expression[i] != ')')
{
//add the operation to the operation stack
operationStack.push(expression[i]);
}
}
//if not a value or operation the character is ignored
}
//empty what's left in the stacks before finishing
while (valueStack.size() > 1 && operationStack.size() > 0)
{
if (valueStack.size() < 2)//must be at least two values for this loop to work properly
{
XdmfError::message(XdmfError::FATAL,
"Error: Not Enough Values in evaluateExpression");
}
else
{
if(operationStack.top() == '(')
{
XdmfError::message(XdmfError::WARNING,
"Warning: Unpaired Parenthesis");
}
else
{
shared_ptr<XdmfArray> val2 = valueStack.top();
valueStack.pop();
shared_ptr<XdmfArray> val1 = valueStack.top();
valueStack.pop();
if (operationStack.size() == 0)
{
XdmfError::message(XdmfError::FATAL,
"Error: Not Enough Operators in evaluateExpression");
}
else
{
valueStack.push(evaluateOperation(val1, val2, operationStack.top()));
operationStack.pop();
}
}
}
}
//throw error if there's extra operations
if (operationStack.size() > 0)
{
XdmfError::message(XdmfError::WARNING,
"Warning: Left Over Operators in evaluateExpression");
}
if (valueStack.size() > 1)
{
XdmfError::message(XdmfError::WARNING,
"Warning: Left Over Values in evaluateExpression");
}
return valueStack.top();
}
shared_ptr<XdmfArray>
XdmfArray::evaluateOperation(shared_ptr<XdmfArray> val1, shared_ptr<XdmfArray> val2, char operation)
{
if (operations.find(operation) != operations.end())
{
return (*(shared_ptr<XdmfArray>(*)(shared_ptr<XdmfArray>, shared_ptr<XdmfArray>))operations[operation])(val1, val2);
}
else
{
return shared_ptr<XdmfArray>();
}
}
int
XdmfArray::addOperation(char newoperator, shared_ptr<XdmfArray>(*operationref)(shared_ptr<XdmfArray>, shared_ptr<XdmfArray>), int priority)
{
if (newoperator == '(' || newoperator == ')')
{
XdmfError::message(XdmfError::FATAL,
"Error: Parenthesis can not be redefined");
}
//give warning if the operation already exists
size_t origsize = operations.size();
operations[newoperator] = operationref;//place reference in the associated location
if (origsize == operations.size())
{//it's nice to let people know they're doing this so they don't get surprised about changes in behavior
XdmfError::message(XdmfError::WARNING,
"Warning: Function Overwritten");
//overwrite the existing info for that operation
//add the priority to the specified location in the priority array
size_t priorityLocation = mSupportedOperations.find(newoperator);
mOperationPriority[priorityLocation] = priority;
}
else
{
//create new operation
//as long as the operation isn't a valid function character
if (mValidVariableChars.find(newoperator) != std::string::npos || mValidDigitChars.find(newoperator) != std::string::npos)
{
XdmfError::message(XdmfError::FATAL,
"Error: Operation Overlaps with Variables");
}
else //build the operation
{
//add operation to the supported character string
mSupportedOperations.push_back(newoperator);
int priorityArraySize = sizeof(mOperationPriority)/sizeof(int);
if (mSupportedOperations.size()-1 > priorityArraySize)//first check to see if the priority array is large enough
{
//if it isn't make it bigger, double size should be fine
int newArray [priorityArraySize*2];
std::copy(mOperationPriority, mOperationPriority+(priorityArraySize-1), newArray);
delete mOperationPriority;
*mOperationPriority = *newArray;
}
size_t priorityLocation = mSupportedOperations.find(newoperator);
mOperationPriority[priorityLocation] = priority;
}
}
return operations.size();
}
shared_ptr<XdmfArray>
XdmfArray::chunk(shared_ptr<XdmfArray> val1, shared_ptr<XdmfArray> val2)
{
//join chunk (add the new array to the end of the first one)
//joins into new array and returns it
shared_ptr<XdmfArray> returnArray = XdmfArray::New();
returnArray->insert(0, val1, 0, val1->getSize(), 1, 1);
returnArray->insert(val1->getSize(), val2, 0, val2->getSize(), 1, 1);
return returnArray;
}
shared_ptr<XdmfArray>
XdmfArray::interlace(shared_ptr<XdmfArray> val1, shared_ptr<XdmfArray> val2)
{
//join interlace (evenly space the second array within the first one)
//builds a new array
shared_ptr<XdmfArray> returnArray = XdmfArray::New();
//resize to the combined size of both arrays
//determining what type to class it as in order to not lose data, and to still have the smallest data type of the two
shared_ptr<const XdmfArrayType> arrayType1 = val1->getArrayType();
shared_ptr<const XdmfArrayType> arrayType2 = val2->getArrayType();
if (arrayType1 == XdmfArrayType::Int8())
{
//if floats reclass as floats of the appropriate size
if (arrayType2 == XdmfArrayType::String())
{
//string is the only compatible type here
std::string sampleValue = "";
returnArray->resize(val1->getSize()+val2->getSize(), sampleValue);
}
else if (arrayType2 == XdmfArrayType::Float32())
{
float sampleValue = 0.0;
returnArray->resize(val1->getSize()+val2->getSize(), sampleValue);
}
else if (arrayType2 == XdmfArrayType::Float64())
{
double sampleValue = 0.0;
returnArray->resize(val1->getSize()+val2->getSize(), sampleValue);
}
//if uints reclass as ints of the appropriate size
else if (arrayType2 == XdmfArrayType::Int64() || arrayType2 == XdmfArrayType::UInt32())
{
long sampleValue = 0;
returnArray->resize(val1->getSize()+val2->getSize(), sampleValue);
}
else if (arrayType2 == XdmfArrayType::Int32() || arrayType2 == XdmfArrayType::UInt16())
{
int sampleValue = 0;
returnArray->resize(val1->getSize()+val2->getSize(), sampleValue);
}
else if (arrayType2 == XdmfArrayType::Int16() || arrayType2 == XdmfArrayType::UInt8())
{
short sampleValue = 0;
returnArray->resize(val1->getSize()+val2->getSize(), sampleValue);
}
else
{
char sampleValue = 0;
returnArray->resize(val1->getSize()+val2->getSize(), sampleValue);
}
}
else if (arrayType1 == XdmfArrayType::Int16())
{
//if floats reclass as floats of the appropriate size
if (arrayType2 == XdmfArrayType::String())
{
//string is the only compatible type here
std::string sampleValue = "";
returnArray->resize(val1->getSize()+val2->getSize(), sampleValue);
}
else if (arrayType2 == XdmfArrayType::Float32())
{
float sampleValue = 0.0;
returnArray->resize(val1->getSize()+val2->getSize(), sampleValue);
}
else if (arrayType2 == XdmfArrayType::Float64())
{
double sampleValue = 0.0;
returnArray->resize(val1->getSize()+val2->getSize(), sampleValue);
}
//if uints reclass as ints of the appropriate size
else if (arrayType2 == XdmfArrayType::Int64() || arrayType2 == XdmfArrayType::UInt32())
{
long sampleValue = 0;
returnArray->resize(val1->getSize()+val2->getSize(), sampleValue);
}
else if (arrayType2 == XdmfArrayType::Int32() || arrayType2 == XdmfArrayType::UInt16())
{
int sampleValue = 0;
returnArray->resize(val1->getSize()+val2->getSize(), sampleValue);
}
else
{
short sampleValue = 0;
returnArray->resize(val1->getSize()+val2->getSize(), sampleValue);
}
}
else if (arrayType1 == XdmfArrayType::Int32())
{
//if floats reclass as floats of the appropriate size
if (arrayType2 == XdmfArrayType::String())
{
//string is the only compatible type here
std::string sampleValue = "";
returnArray->resize(val1->getSize()+val2->getSize(), sampleValue);
}
else if (arrayType2 == XdmfArrayType::Float32())
{
float sampleValue = 0.0;
returnArray->resize(val1->getSize()+val2->getSize(), sampleValue);
}
else if (arrayType2 == XdmfArrayType::Float64())
{
double sampleValue = 0.0;
returnArray->resize(val1->getSize()+val2->getSize(), sampleValue);
}
//if uints reclass as ints of the appropriate size
else if (arrayType2 == XdmfArrayType::Int64() || arrayType2 == XdmfArrayType::UInt32())
{
long sampleValue = 0;
returnArray->resize(val1->getSize()+val2->getSize(), sampleValue);
}
else
{
int sampleValue = 0;
returnArray->resize(val1->getSize()+val2->getSize(), sampleValue);
}
}
else if (arrayType1 == XdmfArrayType::Int64())
{
//if floats reclass as floats of the appropriate size
if (arrayType2 == XdmfArrayType::String())
{
//string is the only compatible type here
std::string sampleValue = "";
returnArray->resize(val1->getSize()+val2->getSize(), sampleValue);
}
else if (arrayType2 == XdmfArrayType::Float32())
{
float sampleValue = 0.0;
returnArray->resize(val1->getSize()+val2->getSize(), sampleValue);
}
else if (arrayType2 == XdmfArrayType::Float64())
{
double sampleValue = 0.0;
returnArray->resize(val1->getSize()+val2->getSize(), sampleValue);
}
//if uints reclass as ints of the appropriate size
else
{
long sampleValue = 0;
returnArray->resize(val1->getSize()+val2->getSize(), sampleValue);
}
}
else if (arrayType1 == XdmfArrayType::Float32())
{
//use floats of the appropriate size
if (arrayType2 == XdmfArrayType::String())
{
//string is the only compatible type here
std::string sampleValue = "";
returnArray->resize(val1->getSize()+val2->getSize(), sampleValue);
}
else if (arrayType2 == XdmfArrayType::Float64())
{
double sampleValue = 0.0;
returnArray->resize(val1->getSize()+val2->getSize(), sampleValue);
}
else
{
float sampleValue = 0.0;
returnArray->resize(val1->getSize()+val2->getSize(), sampleValue);
}
}
else if (arrayType1 == XdmfArrayType::Float64())
{
//use floats of the appropriate size
if (arrayType2 == XdmfArrayType::String())
{
//string is the only compatible type here