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

changes for file splitting and functions along with assorted changes to...

changes for file splitting and functions along with assorted changes to XdmfFortran for possible speed increases
parent f5c88a96
......@@ -44,6 +44,18 @@ public:
/**
* Create a new XdmfGraph.
*
* Example of use:
*
* C++
*
* @dontinclude ExampleXdmfGraph.cpp
* @skipline New
*
* Python
*
* @dontinclude XdmfExampleGraph.py
* @skipline New
*
* @param numberNodes number of nodes in graph.
*
* @return constructed XdmfGraph.
......
......@@ -513,11 +513,10 @@ public:
operator()(const boost::blank & array) const
{
if(mArray->mHeavyDataControllers.size()>0) {
int total = 0;
for (int i = 0; i < mArray->mHeavyDataControllers.size(); i++)
{
total += mArray->mHeavyDataControllers[i]->getSize();
}
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;
......@@ -584,713 +583,593 @@ XdmfArray::erase(const unsigned int index)
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
}
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();
}
}
}
}
//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");
}
//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");
}
if (valueStack.size() > 1) {
XdmfError::message(XdmfError::WARNING,
"Warning: Left Over Values in evaluateExpression");
}
return valueStack.top();
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>();
}
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();
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;
//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())
{