From 11e9f68fafa0b097e159e87f7b1f5fdc8689d694 Mon Sep 17 00:00:00 2001 From: "Andrew J. Burns (Cont" Date: Wed, 31 Jul 2013 14:44:10 -0400 Subject: [PATCH] made changes for preparations to push to master; still need to finish documentation changes and line length changes --- CMakeLists.txt | 1 + Xdmf.i | 572 +++++++- XdmfAttribute.hpp | 92 +- XdmfAttributeCenter.hpp | 16 +- XdmfAttributeType.hpp | 16 +- XdmfCurvilinearGrid.cpp | 2 +- XdmfCurvilinearGrid.hpp | 113 +- XdmfDomain.hpp | 6 +- XdmfFunction.cpp | 687 ++++++++++ XdmfFunction.hpp | 501 +++++++ XdmfGeometry.hpp | 42 +- XdmfGeometryType.hpp | 22 +- XdmfGraph.hpp | 6 +- XdmfGrid.hpp | 105 +- XdmfGridCollection.hpp | 46 +- XdmfGridCollectionType.hpp | 12 +- XdmfItemFactory.cpp | 70 + XdmfItemFactory.hpp | 6 +- XdmfMap.hpp | 158 ++- XdmfReader.hpp | 6 +- XdmfRectilinearGrid.cpp | 2 +- XdmfRectilinearGrid.hpp | 168 ++- XdmfRegularGrid.cpp | 2 +- XdmfRegularGrid.hpp | 160 ++- XdmfSet.hpp | 64 +- XdmfSetType.hpp | 16 +- XdmfTime.hpp | 34 +- XdmfTopology.hpp | 46 +- XdmfTopologyType.cpp | 165 ++- XdmfTopologyType.hpp | 78 +- XdmfUnstructuredGrid.hpp | 74 +- core/XdmfArray.cpp | 831 +---------- core/XdmfArray.hpp | 962 +++++-------- core/XdmfArrayType.cpp | 165 +++ core/XdmfArrayType.hpp | 41 +- core/XdmfCore.i | 564 -------- core/XdmfCoreItemFactory.hpp | 8 +- core/XdmfCoreReader.cpp | 387 +----- core/XdmfCoreReader.hpp | 80 +- core/XdmfDSMBuffer.cpp | 1178 ++++++++-------- core/XdmfDSMBuffer.hpp | 101 +- core/XdmfDSMCommMPI.cpp | 336 +++-- core/XdmfDSMCommMPI.hpp | 40 +- core/XdmfDSMDriver.cpp | 1 + core/XdmfDSMManager.cpp | 305 ++--- core/XdmfDSMManager.hpp | 26 +- core/XdmfError.hpp | 84 +- core/XdmfHDF5Controller.cpp | 6 +- core/XdmfHDF5ControllerDSM.cpp | 121 +- core/XdmfHDF5ControllerDSM.hpp | 87 +- core/XdmfHDF5Writer.cpp | 1195 ++-------------- core/XdmfHDF5Writer.hpp | 185 +-- core/XdmfHDF5WriterDSM.cpp | 152 +-- core/XdmfHDF5WriterDSM.hpp | 92 +- core/XdmfHeavyDataWriter.cpp | 1215 ++++++++++++++++- core/XdmfHeavyDataWriter.hpp | 193 ++- core/tests/Cxx/TestXdmfArray.cpp | 53 + core/tests/Cxx/TestXdmfHDF5WriterDSM.cpp | 2 +- examples/Cxx/DSMLoopTest.cpp | 21 +- examples/Cxx/ExampleXdmfArray.cpp | 354 ++++- examples/Cxx/ExampleXdmfArrayType.cpp | 18 + examples/Cxx/ExampleXdmfAttribute.cpp | 28 +- examples/Cxx/ExampleXdmfCoreItemFactory.cpp | 4 + examples/Cxx/ExampleXdmfCoreReader.cpp | 24 + examples/Cxx/ExampleXdmfCurvilinearGrid.cpp | 52 +- examples/Cxx/ExampleXdmfDSMNoThread.cpp | 79 +- examples/Cxx/ExampleXdmfDomain.cpp | 5 + examples/Cxx/ExampleXdmfError.cpp | 43 +- examples/Cxx/ExampleXdmfGeometry.cpp | 16 + examples/Cxx/ExampleXdmfGeometryType.cpp | 17 + examples/Cxx/ExampleXdmfGraph.cpp | 5 + examples/Cxx/ExampleXdmfGrid.cpp | 33 +- examples/Cxx/ExampleXdmfGridCollection.cpp | 16 + examples/Cxx/ExampleXdmfItemFactory.cpp | 5 + examples/Cxx/ExampleXdmfMap.cpp | 53 +- examples/Cxx/ExampleXdmfReader.cpp | 5 + examples/Cxx/ExampleXdmfRectilinearGrid.cpp | 56 + examples/Cxx/ExampleXdmfRegularGrid.cpp | 60 + examples/Cxx/ExampleXdmfSet.cpp | 20 +- examples/Cxx/ExampleXdmfTime.cpp | 14 +- examples/Cxx/ExampleXdmfTopology.cpp | 16 +- examples/Cxx/ExampleXdmfTopologyType.cpp | 38 + examples/Cxx/ExampleXdmfUnstructuredGrid.cpp | 25 +- examples/Cxx/XdmfAcceptTest.cpp | 44 + examples/Cxx/XdmfConnectTest.cpp | 179 +++ examples/Cxx/XdmfConnectTest2.cpp | 173 +++ examples/Python/XdmfExampleArray.py | 226 ++- examples/Python/XdmfExampleArrayType.py | 18 + examples/Python/XdmfExampleAttribute.py | 30 + examples/Python/XdmfExampleCoreItemFactory.py | 4 + examples/Python/XdmfExampleCoreReader.py | 25 + examples/Python/XdmfExampleCurvilinearGrid.py | 41 +- examples/Python/XdmfExampleDSMNoThread.py | 43 +- examples/Python/XdmfExampleDomain.py | 5 + examples/Python/XdmfExampleError.py | 44 +- examples/Python/XdmfExampleGeometry.py | 17 + examples/Python/XdmfExampleGeometryType.py | 14 + examples/Python/XdmfExampleGraph.py | 5 + examples/Python/XdmfExampleGrid.py | 29 +- examples/Python/XdmfExampleGridCollection.py | 16 + examples/Python/XdmfExampleItemFactory.py | 5 + examples/Python/XdmfExampleMap.py | 57 +- examples/Python/XdmfExampleReader.py | 5 + examples/Python/XdmfExampleRectilinearGrid.py | 40 +- examples/Python/XdmfExampleRegularGrid.py | 42 + examples/Python/XdmfExampleSet.py | 20 +- examples/Python/XdmfExampleTime.py | 14 +- examples/Python/XdmfExampleTopology.py | 16 +- examples/Python/XdmfExampleTopologyType.py | 32 + .../Python/XdmfExampleUnstructuredGrid.py | 25 +- tests/Cxx/HugeReadArray.cpp | 2 +- tests/Cxx/HugeWriteArray.cpp | 18 +- tests/Cxx/XdmfPostFixCalc.cpp | 23 +- tests/Python/ReadArray.py | 21 +- utils/CMakeLists.txt | 3 +- utils/XdmfTopologyConverter.cpp | 415 ++++++ utils/XdmfTopologyConverter.hpp | 13 + utils/XdmfUtils.i | 2 + utils/tests/Cxx/CMakeLists.txt | 1 - utils/tests/Cxx/TestXdmfTopologyConverter.cpp | 92 ++ 120 files changed, 8803 insertions(+), 5661 deletions(-) create mode 100644 XdmfFunction.cpp create mode 100644 XdmfFunction.hpp create mode 100644 examples/Cxx/XdmfAcceptTest.cpp create mode 100644 examples/Cxx/XdmfConnectTest.cpp create mode 100644 examples/Cxx/XdmfConnectTest2.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 10f35c9b..444bfa33 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -225,6 +225,7 @@ if(NOT XDMF_BUILD_CORE_ONLY) XdmfAttributeType XdmfCurvilinearGrid XdmfDomain + XdmfFunction XdmfGeometry XdmfGeometryType XdmfGraph diff --git a/Xdmf.i b/Xdmf.i index ac3a8222..13dd45e0 100644 --- a/Xdmf.i +++ b/Xdmf.i @@ -43,6 +43,7 @@ swig -v -c++ -python -o XdmfPython.cpp Xdmf.i #include #include #include + #include #include #include #include @@ -92,6 +93,7 @@ swig -v -c++ -python -o XdmfPython.cpp Xdmf.i #include #include #include + #include #include #include #include @@ -237,7 +239,7 @@ swig -v -c++ -python -o XdmfPython.cpp Xdmf.i %mpi4py_typemap(Comm, MPI_Comm); -#endif +#endif /* XDMF_BUILD_DSM */ %template(XdmfMapNodeIdSet) std::set; %template(XdmfMapNodeIdMap) std::map >; @@ -350,6 +352,572 @@ swig -v -c++ -python -o XdmfPython.cpp Xdmf.i } } +/*This causes it to avoid throwing a warning for redefining fuctions that are defined for XdmfArray. + I do this because doing so was intentional.*/ +#pragma SWIG nowarn=302 + +%extend XdmfFunction { + +%{ + #include + static std::map pythonFunctions; + static std::map pythonOperations; + static int pythonOperationPriority [4]; + static std::string pythonSupportedOperations = ""; +%} +/*These can't be accessed from python so don't worry about security issues.*/ + +/*Note, the things in this block are defined twice for a reason. + If they are not defined here they can not be referenced by other functions in swig.*/ +%{ + /*trying to transfer python funcitons*/ + /*note, accessing private members is impossible from swig.*/ + + /*to generate new static functions mark them as static here.*/ + static shared_ptr evaluateFunction(std::vector > functValues, std::string functName) + { + if (pythonFunctions.find(functName)!= pythonFunctions.end()) { + swig_type_info * paramType = SWIG_TypeQuery("_p_std__vectorT_boost__shared_ptrT_XdmfArray_t_std__allocatorT_boost__shared_ptrT_XdmfArray_t_t_t"); + PyObject * pyVector = SWIG_NewPointerObj(static_cast(& functValues), paramType, SWIG_POINTER_NEW); + PyObject * args = PyTuple_New(1); + PyTuple_SetItem(args, 0, pyVector);/*In this case you could also cast a pointer to the vector into the PyObject * type, but that doesn't work for all types*/ + PyObject * resultObject = PyObject_CallObject(pythonFunctions[functName], args); + void * resultPointer = 0; + swig_type_info * returnType = SWIG_TypeQuery("_p_boost__shared_ptrT_XdmfArray_t"); + SWIG_ConvertPtr(resultObject, &resultPointer, returnType, 0); + shared_ptr * returnArrayPointer = reinterpret_cast *>(resultPointer); + shared_ptr returnArray = returnArrayPointer[0]; + return returnArray; + } + else { + /*this does not actually cause an infinte recursive loop, it sends the values to the version of the function defined in XdmfArray.cpp*/ + return XdmfFunction::evaluateFunction(functValues, functName); + } + } + + static shared_ptr evaluateOperation(shared_ptr val1, shared_ptr val2, char functName) + { + if (pythonOperations.find(functName)!= pythonOperations.end()) { + swig_type_info * paramType = SWIG_TypeQuery("_p_boost__shared_ptrT_XdmfArray_t"); + PyObject * pyVal1 = SWIG_NewPointerObj(static_cast(& val1), paramType, SWIG_POINTER_NEW); + PyObject * pyVal2 = SWIG_NewPointerObj(static_cast(& val2), paramType, SWIG_POINTER_NEW); + PyObject * args = PyTuple_New(2); + PyTuple_SetItem(args, 0, pyVal1); + PyTuple_SetItem(args, 1, pyVal2); + PyObject * resultObject = PyObject_CallObject(pythonOperations[functName], args); + void * resultPointer = 0; + swig_type_info * returnType = SWIG_TypeQuery("_p_boost__shared_ptrT_XdmfArray_t"); + SWIG_ConvertPtr(resultObject, &resultPointer, returnType, 0); + shared_ptr * returnArrayPointer = reinterpret_cast *>(resultPointer); + shared_ptr returnArray = returnArrayPointer[0]; + return returnArray; + } + else { + /*this does not actually cause an infinte recursive loop, it sends the values to the version of the function defined in XdmfArray.cpp*/ + return XdmfFunction::evaluateOperation(val1, val2, functName); + } + } + + static shared_ptr evaluateExpression(std::string expression, std::map > variables) + { + std::stack > valueStack; + std::stack operationStack; + + /*string is parsed left to right + elements of the same priority are evaluated right to left*/ + for (unsigned int i = 0; i < expression.size(); i++) { + if (XdmfFunction::getValidDigitChars().find(expression[i]) != std::string::npos) { /*found to be a digit*/ + /*progress until a non-digit is found*/ + int valueStart = i; + while (XdmfFunction::getValidDigitChars().find(expression[i + 1]) != std::string::npos) { + i++; + } + /*push back to the value stack*/ + shared_ptr 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 (XdmfFunction::getValidVariableChars().find(expression[i]) != std::string::npos) {/*found to be a variable*/ + int valueStart = i; + /*progress until a nonvariable value is found*/ + while (XdmfFunction::getValidVariableChars().find(expression[i + 1]) != std::string::npos) { + i++; + } + /*convert to equivalent*/ + if (variables.find(expression.substr(valueStart, i + 1 - valueStart)) == variables.end()) { + std::vector functionList = XdmfFunction::getSupportedFunctions(); + bool functionExists = false; + for (unsigned int j = 0; j < functionList.size() && !functionExists; j++) { + if (functionList[j] == expression.substr(valueStart, i + 1 - valueStart)) { + functionExists = true; + } + } + if (functionExists) { + 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 > 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 (XdmfFunction::getSupportedOperations().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 val2 = valueStack.top(); + valueStack.pop(); + shared_ptr 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 block*/ + } + else { + int operationLocation = XdmfFunction::getOperationPriority(expression[i]); + int topOperationLocation = XdmfFunction::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 val2 = valueStack.top(); + valueStack.pop(); + shared_ptr val1 = valueStack.top(); + valueStack.pop(); + valueStack.push(evaluateOperation(val1, val2, operationStack.top())); + operationStack.pop(); + if (operationStack.size() == 0) { + break; + } + topOperationLocation = XdmfFunction::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 val2 = valueStack.top(); + valueStack.pop(); + shared_ptr 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(); + } + +%} + + /*trying to transfer python funcitons*/ + /*note, accessing private members is impossible from swig.*/ + static int addFunction(std::string newName, PyObject * functionref) + { + /*check if the object is callable*/ + if (PyCallable_Check(functionref) == 1) { + pythonFunctions[newName] = functionref; + return pythonFunctions.size(); + } + else { + XdmfError::message(XdmfError::FATAL, + "Error: Function is not callable"); + return -1; + } + } + + /*to generate new static functions mark them as static here.*/ + static std::vector getSupportedFunctions() + { + std::vector returnVector = XdmfFunction::getSupportedFunctions(); + for (std::map::iterator functionWalker = pythonFunctions.begin(); functionWalker != pythonFunctions.end(); functionWalker++) { + returnVector.push_back(functionWalker->first); + } + return returnVector; + } + + static shared_ptr evaluateFunction(std::vector > functValues, std::string functName) + { + if (pythonFunctions.find(functName)!= pythonFunctions.end()) { + swig_type_info * paramType = SWIG_TypeQuery("_p_std__vectorT_boost__shared_ptrT_XdmfArray_t_std__allocatorT_boost__shared_ptrT_XdmfArray_t_t_t"); + PyObject * pyVector = SWIG_NewPointerObj(static_cast(& functValues), paramType, SWIG_POINTER_NEW); + PyObject * args = PyTuple_New(1); + PyTuple_SetItem(args, 0, pyVector);/*In this case you could also cast a pointer to the vector into the PyObject * type, but that doesn't work for all types*/ + PyObject * resultObject = PyObject_CallObject(pythonFunctions[functName], args); + void * resultPointer = 0; + swig_type_info * returnType = SWIG_TypeQuery("_p_boost__shared_ptrT_XdmfArray_t"); + SWIG_ConvertPtr(resultObject, &resultPointer, returnType, 0); + shared_ptr * returnArrayPointer = reinterpret_cast *>(resultPointer); + shared_ptr returnArray = returnArrayPointer[0]; + return returnArray; + } + else { + /*this does not actually cause an infinte recursive loop, it sends the values to the version of the function defined in XdmfArray.cpp*/ + return XdmfFunction::evaluateFunction(functValues, functName); + } + } + + static int addOperation(char newName, PyObject * calcref, int priority) + { + if (newName == '(' || newName == ')') { + XdmfError::message(XdmfError::FATAL, + "Error: Parenthesis can not be redefined"); + } + /*check if the object is callable*/ + if (PyCallable_Check(calcref) == 1) { + if (pythonOperations.find(newName) != pythonOperations.end() || XdmfFunction::getSupportedOperations().find(newName) != std::string::npos) { + XdmfError::message(XdmfError::WARNING, + "Warning: Operation Redefined");/*It's a good idea to warn users when they're doing this*/ + size_t operationLocation = pythonSupportedOperations.find(newName); + /*if not an already defined python function*/ + if (pythonOperations.find(newName) == pythonOperations.end()) { + pythonSupportedOperations.push_back(newName); + unsigned int priorityArraySize = sizeof(pythonOperationPriority)/sizeof(int); + if (pythonSupportedOperations.size()-1 > priorityArraySize) { + int newArray [priorityArraySize*2]; + std::copy(pythonOperationPriority, pythonOperationPriority+(priorityArraySize-1), newArray); + *pythonOperationPriority = *newArray; + } + } + pythonOperationPriority[operationLocation] = priority; + /*if defined on the c++ side same as adding a new one*/ + } + else { + pythonSupportedOperations += newName; + if (XdmfFunction::getValidVariableChars().find(newName) != std::string::npos || XdmfFunction::getValidDigitChars().find(newName) != std::string::npos) { + XdmfError::message(XdmfError::FATAL, + "Error: Operation Overlaps with Variables"); + } + else { + pythonSupportedOperations.push_back(newName); + unsigned int priorityArraySize = sizeof(pythonOperationPriority)/sizeof(int); + if (pythonSupportedOperations.size()-1 > priorityArraySize) + { + int newArray [priorityArraySize*2]; + std::copy(pythonOperationPriority, pythonOperationPriority+(priorityArraySize-1), newArray); + *pythonOperationPriority = *newArray; + } + } + } + pythonOperations[newName] = calcref; + return pythonOperations.size(); + } + else { + XdmfError::message(XdmfError::FATAL, + "Error: Operation is not callable"); + return -1; + } + } + + static std::string getSupportedOperations() + { + std::string returnVector = XdmfFunction::getSupportedOperations(); + for (std::map::iterator functionWalker = pythonOperations.begin(); functionWalker != pythonOperations.end(); functionWalker++) { + returnVector += functionWalker->first; + } + return returnVector; + } + + static shared_ptr evaluateOperation(shared_ptr val1, shared_ptr val2, char functName) + { + if (pythonOperations.find(functName)!= pythonOperations.end()) { + swig_type_info * paramType = SWIG_TypeQuery("_p_boost__shared_ptrT_XdmfArray_t"); + PyObject * pyVal1 = SWIG_NewPointerObj(static_cast(& val1), paramType, SWIG_POINTER_NEW); + PyObject * pyVal2 = SWIG_NewPointerObj(static_cast(& val2), paramType, SWIG_POINTER_NEW); + PyObject * args = PyTuple_New(2); + PyTuple_SetItem(args, 0, pyVal1); + PyTuple_SetItem(args, 1, pyVal2); + PyObject * resultObject = PyObject_CallObject(pythonOperations[functName], args); + void * resultPointer = 0; + swig_type_info * returnType = SWIG_TypeQuery("_p_boost__shared_ptrT_XdmfArray_t"); + SWIG_ConvertPtr(resultObject, &resultPointer, returnType, 0); + shared_ptr * returnArrayPointer = reinterpret_cast *>(resultPointer); + shared_ptr returnArray = returnArrayPointer[0]; + return returnArray; + } + else { + /*this does not actually cause an infinte recursive loop, it sends the values to the version of the function defined in XdmfArray.cpp*/ + return XdmfFunction::evaluateOperation(val1, val2, functName); + } + } + + static shared_ptr evaluateExpression(std::string expression, std::map > variables) + { + std::stack > valueStack; + std::stack operationStack; + + /*string is parsed left to right + elements of the same priority are evaluated right to left*/ + for (unsigned int i = 0; i < expression.size(); i++) { + if (XdmfFunction::getValidDigitChars().find(expression[i]) != std::string::npos) { /*found to be a digit*/ + /*progress until a non-digit is found*/ + int valueStart = i; + while (XdmfFunction::getValidDigitChars().find(expression[i + 1]) != std::string::npos) { + i++; + } + /*push back to the value stack*/ + shared_ptr 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 (XdmfFunction::getValidVariableChars().find(expression[i]) != std::string::npos) {/*found to be a variable*/ + int valueStart = i; + /*progress until a nonvariable value is found*/ + while (XdmfFunction::getValidVariableChars().find(expression[i + 1]) != std::string::npos) { + i++; + } + /*convert to equivalent*/ + if (variables.find(expression.substr(valueStart, i + 1 - valueStart)) == variables.end()) { + std::vector functionList = XdmfFunction::getSupportedFunctions(); + bool functionExists = false; + for (unsigned int j = 0; j < functionList.size() && !functionExists; j++) { + if (functionList[j] == expression.substr(valueStart, i + 1 - valueStart)) { + functionExists = true; + } + } + if (functionExists) { + 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 > 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 (XdmfFunction::getSupportedOperations().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 val2 = valueStack.top(); + valueStack.pop(); + shared_ptr 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 = XdmfFunction::getOperationPriority(expression[i]); + int topOperationLocation = XdmfFunction::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 val2 = valueStack.top(); + valueStack.pop(); + shared_ptr val1 = valueStack.top(); + valueStack.pop(); + valueStack.push(evaluateOperation(val1, val2, operationStack.top())); + operationStack.pop(); + if (operationStack.size() == 0) { + break; + } + topOperationLocation = XdmfFunction::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 val2 = valueStack.top(); + valueStack.pop(); + shared_ptr 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(); + } +}; + #endif /* SWIGPYTHON */ // Shared Pointer Templates @@ -358,6 +926,7 @@ swig -v -c++ -python -o XdmfPython.cpp Xdmf.i %shared_ptr(XdmfAttributeType) %shared_ptr(XdmfCurvilinearGrid) %shared_ptr(XdmfDomain) +%shared_ptr(XdmfFunction) %shared_ptr(XdmfGeometry) %shared_ptr(XdmfGeometryType) %shared_ptr(XdmfGraph) @@ -384,6 +953,7 @@ swig -v -c++ -python -o XdmfPython.cpp Xdmf.i %include XdmfAttributeType.hpp %include XdmfCurvilinearGrid.hpp %include XdmfDomain.hpp +%include XdmfFunction.hpp %include XdmfGeometry.hpp %include XdmfGeometryType.hpp %include XdmfGraph.hpp diff --git a/XdmfAttribute.hpp b/XdmfAttribute.hpp index 03fb2629..29841dcb 100644 --- a/XdmfAttribute.hpp +++ b/XdmfAttribute.hpp @@ -53,12 +53,14 @@ public: * C++ * * @dontinclude ExampleXdmfAttribute.cpp - * @skipline New + * @skipline //#initialization + * @until //#initialization * * Python * * @dontinclude XdmfExampleAttribute.py - * @skipline New + * @skipline #//initialization + * @until #//initialization * * @return constructed XdmfAttribute. */ @@ -77,14 +79,22 @@ public: * C++ * * @dontinclude ExampleXdmfAttribute.cpp - * @skipline Assuming - * @skipline getCenter + * @skipline //#initialization + * @until //#initialization + * @skipline //#setCenter + * @until //#setCenter + * @skipline //#getCenter + * @until //#getCenter * * Python * * @dontinclude XdmfExampleAttribute.py - * @skipline Assuming - * @skipline getCenter + * @skipline #//initialization + * @until #//initialization + * @skipline #//setCenter + * @until #//setCenter + * @skipline #//getCenter + * @until #//getCenter * * @return XdmfAttributeCenter of the attribute. */ @@ -102,14 +112,22 @@ public: * C++ * * @dontinclude ExampleXdmfAttribute.cpp - * @skipline Assuming - * @skipline getName + * @skipline //#initialization + * @until //#initialization + * @skipline //#setName + * @until //#setName + * @skipline //#getName + * @until //#getName * * Python * * @dontinclude XdmfExampleAttribute.py - * @skipline Assuming - * @skipline getName + * @skipline #//initialization + * @until #//initialization + * @skipline #//setName + * @until #//setName + * @skipline #//getName + * @until #//getName * * @return a string containing the name of the attribute. */ @@ -123,14 +141,22 @@ public: * C++ * * @dontinclude ExampleXdmfAttribute.cpp - * @skipline Assuming - * @skipline getType + * @skipline //#initialization + * @until //#initialization + * @skipline //#setType + * @until //#setType + * @skipline //#getType + * @until //#getType * * Python * * @dontinclude XdmfExampleAttribute.py - * @skipline Assuming - * @skipline getType + * @skipline #//initialization + * @until #//initialization + * @skipline #//setType + * @until #//setType + * @skipline #//getType + * @until #//getType * * @return XdmfAttributeType of the attribute. */ @@ -144,14 +170,18 @@ public: * C++ * * @dontinclude ExampleXdmfAttribute.cpp - * @skipline New - * @skipline setCenter + * @skipline //#initialization + * @until //#initialization + * @skipline //#setCenter + * @until //#setCenter * * Python * * @dontinclude XdmfExampleAttribute.py - * @skipline New - * @skipline setCenter + * @skipline #//initialization + * @until #//initialization + * @skipline #//setCenter + * @until #//setCenter * * @param center the XdmfAttributeCenter to set. */ @@ -165,16 +195,18 @@ public: * C++ * * @dontinclude ExampleXdmfAttribute.cpp - * @skipline New - * @skipline newName - * @skipline setName + * @skipline //#initialization + * @until //#initialization + * @skipline //#setName + * @until //#setName * * Python * * @dontinclude XdmfExampleAttribute.py - * @skipline New - * @skipline newName - * @skipline setName + * @skipline #//initialization + * @until #//initialization + * @skipline #//setName + * @until #//setName * * @param name a string containing the name to set. */ @@ -188,14 +220,18 @@ public: * C++ * * @dontinclude ExampleXdmfAttribute.cpp - * @skipline New - * @skipline setType + * @skipline //#initialization + * @until //#initialization + * @skipline //#setType + * @until //#setType * * Python * * @dontinclude XdmfExampleAttribute.py - * @skipline New - * @skipline setType + * @skipline #//initialization + * @until #//initialization + * @skipline #//setType + * @until #//setType * * @param type XdmfAttributeType to set. */ diff --git a/XdmfAttributeCenter.hpp b/XdmfAttributeCenter.hpp index c09a46ec..5576f49a 100644 --- a/XdmfAttributeCenter.hpp +++ b/XdmfAttributeCenter.hpp @@ -42,14 +42,22 @@ * C++ * * @dontinclude ExampleXdmfAttribute.cpp - * @skipline exampleCenter - * @until } + * @skipline //#initialization + * @until //#initialization + * @skipline //#setCenter + * @until //#setCenter + * @skipline //#getCenter + * @until //#getCenter * * Python * * @dontinclude XdmfExampleAttribute.py - * @skipline exampleCenter - * @until do + * @skipline #//initialization + * @until #//initialization + * @skipline #//setCenter + * @until #//setCenter + * @skipline #//getCenter + * @until #//getCenter * * Grid * Cell diff --git a/XdmfAttributeType.hpp b/XdmfAttributeType.hpp index 01e42bfd..f917cc4e 100644 --- a/XdmfAttributeType.hpp +++ b/XdmfAttributeType.hpp @@ -42,14 +42,22 @@ * C++ * * @dontinclude ExampleXdmfAttribute.cpp - * @skipline exampleType - * @until } + * @skipline //#initialization + * @until //#initialization + * @skipline //#setType + * @until //#setType + * @skipline //#getType + * @until //#getType * * Python * * @dontinclude XdmfExampleAttribute.py - * @skipline exampleType - * @until do + * @skipline #//initialization + * @until #//initialization + * @skipline #//setType + * @until #//setType + * @skipline #//getType + * @until #//getType * * Xdmf supports the following attribute types: * NoAttributeType diff --git a/XdmfCurvilinearGrid.cpp b/XdmfCurvilinearGrid.cpp index a47d3cd5..a2a0a6ce 100644 --- a/XdmfCurvilinearGrid.cpp +++ b/XdmfCurvilinearGrid.cpp @@ -182,7 +182,7 @@ public: private: XdmfTopologyTypeCurvilinear(const XdmfCurvilinearGrid * const curvilinearGrid) : - XdmfTopologyType(0, 0, 0, "foo", XdmfTopologyType::Structured, 0x1110), + XdmfTopologyType(0, 0, std::vector >(), 0, "foo", XdmfTopologyType::Structured, 0x1110), mCurvilinearGrid(curvilinearGrid) { } diff --git a/XdmfCurvilinearGrid.hpp b/XdmfCurvilinearGrid.hpp index f10843ba..cc392bcb 100644 --- a/XdmfCurvilinearGrid.hpp +++ b/XdmfCurvilinearGrid.hpp @@ -54,15 +54,16 @@ public: * C++ * * @dontinclude ExampleXdmfCurvilinearGrid.cpp - * @skipline newPointsX - * @until New + * @skipline //#initializationdim2 + * @until //#initializationdim2 * * Python * * @dontinclude XdmfExampleCurvilinearGrid.py - * @skipline newPointsX - * @until newPointsY - * @skipline newPointsX + * @skipline #//initialization + * @until #//initialization + * @skipline #//constructor2 + * @until #//constructor2 * * @param xNumPoints the number of points in the x direction. * @param yNumPoints the number of points in the y direction. @@ -81,16 +82,16 @@ public: * C++ * * @dontinclude ExampleXdmfCurvilinearGrid.cpp - * @skip 3 - * @skipline newPointsX - * @until New + * @skipline //#initializationdim3 + * @until //#initializationdim3 * * Python * * @dontinclude XdmfExampleCurvilinearGrid.py - * @skipline newPointsX - * @until newPointsZ - * @skipline newPointsZ + * @skipline #//initialization + * @until #//initialization + * @skipline #//constructor3 + * @until #//constructor3 * * @param xNumPoints the number of points in the x direction. * @param yNumPoints the number of points in the y direction. @@ -111,15 +112,16 @@ public: * C++ * * @dontinclude ExampleXdmfCurvilinearGrid.cpp - * @skip via - * @skipline newPoints - * @until XdmfCurvilinearGrid + * @skipline //#initializationvector + * @until //#initializationvector * * Python * * @dontinclude XdmfExampleCurvilinearGrid.py - * @skipline newPoints - * @until exampleGrid + * @skipline #//initialization + * @until #//initialization + * @skipline #//constructorvector + * @until #//constructorvector * * @param numPoints the number of points in each direction. * @@ -142,14 +144,24 @@ public: * C++ * * @dontinclude ExampleXdmfCurvilinearGrid.cpp - * @skipline Assuming - * @skipline getDimensions + * @skipline //#initializationdim3 + * @until //#initializationdim3 + * @skipline //#setDimensions + * @until //#setDimensions + * @skipline //#getDimensions + * @until //#getDimensions * * Python * * @dontinclude XdmfExampleCurvilinearGrid.py - * @skipline Assuming - * @skipline getDimensions + * @skipline #//initialization + * @until #//initialization + * @skipline #//constructorvector + * @until #//constructorvector + * @skipline #//setDimensions + * @until #//setDimensions + * @skipline #//getDimensions + * @until #//getDimensions * * @return XdmfArray containing dimensions of this grid. */ @@ -164,8 +176,12 @@ public: * C++ * * @dontinclude ExampleXdmfCurvilinearGrid.cpp - * @skipline Assuming - * @skipline const + * @skipline //#initializationdim3 + * @until //#initializationdim3 + * @skipline //#setDimensions + * @until //#setDimensions + * @skipline //#getDimensionsconst + * @until //#getDimensionsconst * * Python: Python doesn't have a constant version * @@ -181,14 +197,24 @@ public: * C++ * * @dontinclude ExampleXdmfCurvilinearGrid.cpp - * @skipline Assuming - * @skipline getGeometry + * @skipline //#initializationdim3 + * @until //#initializationdim3 + * @skipline //#setGeometry + * @until //#setGeometry + * @skipline //#getGeometry + * @until //#getGeometry * * Python * * @dontinclude XdmfExampleCurvilinearGrid.py - * @skipline Assuming - * @skipline getGeometry + * @skipline #//initialization + * @until #//initialization + * @skipline #//constructorvector + * @until #//constructorvector + * @skipline #//setGeometry + * @until #//setGeometry + * @skipline #//getGeometry + * @until #//getGeometry * * @return the geometry associated with this grid. */ @@ -203,18 +229,20 @@ public: * C++ * * @dontinclude ExampleXdmfCurvilinearGrid.cpp - * @skipline Assuming - * @skipline XdmfArray::New - * @until setDimensions + * @skipline //#initializationdim3 + * @until //#initializationdim3 + * @skipline //#setDimensions + * @until //#setDimensions * * Python * * @dontinclude XdmfExampleCurvilinearGrid.py - * @skipline Assuming - * @skip setDimensions - * @skipline newPoints - * @until setDimensions - * Assuming that exampleGrid is a sharedPointer to an XdmfCurvilinearGrid object + * @skipline #//initialization + * @until #//initialization + * @skipline #//constructorvector + * @until #//constructorvector + * @skipline #//setDimensions + * @until #//setDimensions * * @param dimensions the dimension of the grid. */ @@ -228,17 +256,20 @@ public: * C++ * * @dontinclude ExampleXdmfCurvilinearGrid.cpp - * @skipline newData - * @until setGeometry + * @skipline //#initializationdim3 + * @until //#initializationdim3 + * @skipline //#setGeometry + * @until //#setGeometry * * Python * * @dontinclude XdmfExampleCurvilinearGrid.py - * @skip setGeometry - * @skipline newPoints - * @until insert - * Assuming that exampleGrid is a sharedPointer to an XdmfCurvilinearGrid object - * @skipline setGeometry + * @skipline #//initialization + * @until #//initialization + * @skipline #//constructorvector + * @until #//constructorvector + * @skipline #//setGeometry + * @until #//setGeometry * * @param geometry an XdmfGeometry to associate with this grid. */ diff --git a/XdmfDomain.hpp b/XdmfDomain.hpp index 6e8e0641..4e2632ee 100644 --- a/XdmfDomain.hpp +++ b/XdmfDomain.hpp @@ -55,12 +55,14 @@ public: * C++ * * @dontinclude ExampleXdmfDomain.cpp - * @skipline New + * @skipline //#initialization + * @until //#initialization * * Python * * @dontinclude XdmfExampleDomain.py - * @skipline New + * @skipline #//initialization + * @until #//initialization * * @return constructed XdmfDomain. */ diff --git a/XdmfFunction.cpp b/XdmfFunction.cpp new file mode 100644 index 00000000..aa41c4ca --- /dev/null +++ b/XdmfFunction.cpp @@ -0,0 +1,687 @@ +/*****************************************************************************/ +/* XDMF */ +/* eXtensible Data Model and Format */ +/* */ +/* Id : XdmfFunction.cpp */ +/* */ +/* Author: */ +/* Kenneth Leiter */ +/* kenneth.leiter@arl.army.mil */ +/* US Army Research Laboratory */ +/* Aberdeen Proving Ground, MD */ +/* */ +/* Copyright @ 2011 US Army Research Laboratory */ +/* All Rights Reserved */ +/* See Copyright.txt for details */ +/* */ +/* This software is distributed WITHOUT ANY WARRANTY; without */ +/* even the implied warranty of MERCHANTABILITY or FITNESS */ +/* FOR A PARTICULAR PURPOSE. See the above copyright notice */ +/* for more information. */ +/* */ +/*****************************************************************************/ + + +#include "XdmfArray.hpp" +#include "XdmfArrayType.hpp" +#include "XdmfFunction.hpp" +#include +#include +#include +#include "XdmfError.hpp" + +std::string XdmfFunction::mSupportedOperations = "|#()"; +const std::string XdmfFunction::mValidVariableChars = + "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890_:."; +const std::string XdmfFunction::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 +std::map XdmfFunction::mOperationPriority = boost::assign::map_list_of ('|', 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::vector >)> + XdmfFunction::arrayFunctions = + boost::assign::map_list_of ("SUM", (shared_ptr (*)(std::vector >))XdmfFunction::sum) + ("AVE", (shared_ptr (*)(std::vector >))XdmfFunction::average); +std::map (*)(shared_ptr, shared_ptr)> + XdmfFunction::operations = boost::assign::map_list_of ('|', XdmfFunction::chunk) ('#', XdmfFunction::interlace); + + + + + +shared_ptr +XdmfFunction::New() +{ + shared_ptr p(new XdmfFunction()); + return p; +} + +XdmfFunction::XdmfFunction() +{ +} + +XdmfFunction::~XdmfFunction() +{ +} + +const std::string XdmfFunction::ItemTag = "Function"; + +int +XdmfFunction::addFunction(std::string name, + shared_ptr(*functionref)(std::vector >)) +{ + // Check to ensure that the name has valid characters + for (unsigned int i = 0; i < name.size(); ++i) { + // If the character is not found in the list of valid characters + if (mValidVariableChars.find(name[i]) == std::string::npos) { + // Then throw an error + try { + XdmfError::message(XdmfError::FATAL, + "Error: Function Name Contains Invalid Character(s)"); + } + catch (XdmfError e) { + throw e; + } + } + } + size_t origsize = arrayFunctions.size(); + arrayFunctions[name] = functionref; + // If no new functions were added + if (origsize == arrayFunctions.size()) { + // Toss a warning, it's nice to let people know that they're doing this + try { + XdmfError::message(XdmfError::WARNING, + "Warning: Function Overwritten"); + } + catch (XdmfError e) { + throw e; + } + } + return arrayFunctions.size(); +} + +shared_ptr +XdmfFunction::average(std::vector > values) +{ + double total = sum(values)->getValue(0);; + int totalSize = 0; + for (unsigned int i = 0; i < values.size(); ++i) + { + totalSize += values[i]->getSize(); + } + shared_ptr returnArray = XdmfArray::New(); + returnArray->insert(0, total/totalSize); + return returnArray; +} + +shared_ptr +XdmfFunction::chunk(shared_ptr val1, shared_ptr val2) +{ + // Join chunk (add the new array to the end of the first one) + // Joins into new array and returns it + shared_ptr returnArray = XdmfArray::New(); + // 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 resultType = XdmfArrayType::comparePrecision(val1->getArrayType(), val2->getArrayType()); + + if (resultType == XdmfArrayType::Int8()) { + char sampleValue = 0; + returnArray->resize(val1->getSize()+val2->getSize(), sampleValue); + } + else if (resultType == XdmfArrayType::Int16()) { + short sampleValue = 0; + returnArray->resize(val1->getSize()+val2->getSize(), sampleValue); + } + else if (resultType == XdmfArrayType::Int32()) { + int sampleValue = 0; + returnArray->resize(val1->getSize()+val2->getSize(), sampleValue); + } + else if (resultType == XdmfArrayType::Int64()) { + long sampleValue = 0; + returnArray->resize(val1->getSize()+val2->getSize(), sampleValue); + } + else if (resultType == XdmfArrayType::UInt8()) { + unsigned char sampleValue = 0; + returnArray->resize(val1->getSize()+val2->getSize(), sampleValue); + } + else if (resultType == XdmfArrayType::UInt16()) { + unsigned short sampleValue = 0; + returnArray->resize(val1->getSize()+val2->getSize(), sampleValue); + } + else if (resultType == XdmfArrayType::UInt32()) { + unsigned int sampleValue = 0; + returnArray->resize(val1->getSize()+val2->getSize(), sampleValue); + } + else if (resultType == XdmfArrayType::Float32()) { + float sampleValue = 0.0; + returnArray->resize(val1->getSize()+val2->getSize(), sampleValue); + } + else if (resultType == XdmfArrayType::Float64()) { + double sampleValue = 0.0; + returnArray->resize(val1->getSize()+val2->getSize(), sampleValue); + } + else if (resultType == XdmfArrayType::String()) { + std::string sampleValue = ""; + returnArray->resize(val1->getSize()+val2->getSize(), sampleValue); + } + else { + // error type not supported + XdmfError::message(XdmfError::FATAL, "Invalid type during Interlace"); + } + returnArray->insert(0, val1, 0, val1->getSize(), 1, 1); + returnArray->insert(val1->getSize(), val2, 0, val2->getSize(), 1, 1); + return returnArray; +} + +// 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 +XdmfFunction::evaluateExpression(std::string expression, + std::map > variables) +{ + std::stack > valueStack; + std::stack operationStack; + + // String is parsed left to right + // Elements of the same priority are evaluated right to left + for (unsigned int i = 0; i < expression.size(); ++i) { + // Found to be a digit + if (mValidDigitChars.find(expression[i]) != std::string::npos) { + // Progress until a non-digit is found + int valueStart = i; + if (i + 1 < expression.size()) { + while (mValidDigitChars.find(expression[i+1]) != std::string::npos) { + i++; + } + } + // Push back to the value stack + shared_ptr valueArray = XdmfArray::New(); + // Use this to convert to double + valueArray->insert(0, atof(expression.substr(valueStart, i + 1 - valueStart).c_str())); + 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 + if (i+1 < expression.size()){ + 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()) { + try { + XdmfError::message(XdmfError::FATAL, + "Error: Invalid Variable in evaluateExpression " + + expression.substr(valueStart, i + 1 - valueStart)); + } + catch (XdmfError e) { + throw e; + } + } + else { + std::string currentFunction = expression.substr(valueStart, i + 1 - valueStart); + // Check if next character is an open parenthesis + if (i+1 >= expression.size()) { + if (expression[i+1] != '(') { + try { + XdmfError::message(XdmfError::FATAL, + "Error: No values supplied to function " + + expression.substr(valueStart, i + 1 - valueStart)); + } + catch (XdmfError e) { + throw e; + } + } + } + // If it is grab the string between paranthesis + + if (i + 2 >= expression.size()) { + XdmfError::message(XdmfError::FATAL, + "Error: Missing closing parethesis to function " + + expression.substr(valueStart, i + 1 - valueStart)); + } + 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 > 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 + // Ppop 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() != '(') { + // Must be at least two values for this loop to work properly + if (valueStack.size() < 2) { + try { + XdmfError::message(XdmfError::FATAL, + "Error: Not Enough Values in evaluateExpression"); + } + catch (XdmfError e) { + throw e; + } + } + else { + shared_ptr val2 = valueStack.top(); + valueStack.pop(); + shared_ptr 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) { + // Must be at least two values for this loop to work properly + if (valueStack.size() < 2) { + try { + XdmfError::message(XdmfError::FATAL, + "Error: Not Enough Values in evaluateExpression"); + } + catch (XdmfError e) { + throw e; + } + } + else { + shared_ptr val2 = valueStack.top(); + valueStack.pop(); + shared_ptr 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 + try { + XdmfError::message(XdmfError::FATAL, + "Error: Not Enough Values in evaluateExpression"); + } + catch (XdmfError e) { + throw e; + } + } + else { + if(operationStack.top() == '(') { + try { + XdmfError::message(XdmfError::WARNING, + "Warning: Unpaired Parenthesis"); + } + catch (XdmfError e) { + throw e; + } + } + else { + shared_ptr val2 = valueStack.top(); + valueStack.pop(); + shared_ptr val1 = valueStack.top(); + valueStack.pop(); + if (operationStack.size() == 0) { + try { + XdmfError::message(XdmfError::FATAL, + "Error: Not Enough Operators in evaluateExpression"); + } + catch (XdmfError e) { + throw e; + } + } + else { + valueStack.push(evaluateOperation(val1, val2, operationStack.top())); + operationStack.pop(); + } + } + } + } + + // Throw error if there's extra operations + if (operationStack.size() > 0) { + try { + XdmfError::message(XdmfError::WARNING, + "Warning: Left Over Operators in evaluateExpression"); + } + catch (XdmfError e) { + throw e; + } + } + + if (valueStack.size() > 1) { + try { + XdmfError::message(XdmfError::WARNING, + "Warning: Left Over Values in evaluateExpression"); + } + catch (XdmfError e) { + throw e; + } + } + + return valueStack.top(); +} + +shared_ptr +XdmfFunction::evaluateOperation(shared_ptr val1, + shared_ptr val2, + char operation) +{ + if (operations.find(operation) != operations.end()) { + return (*(shared_ptr(*)(shared_ptr, + shared_ptr))operations[operation])(val1, + val2); + } + else { + return shared_ptr(); + } +} + +int +XdmfFunction::addOperation(char newoperator, + shared_ptr(*operationref)(shared_ptr, + shared_ptr), + int priority) +{ + if (newoperator == '(' || newoperator == ')') { + try { + XdmfError::message(XdmfError::FATAL, + "Error: Parenthesis can not be redefined"); + } + catch (XdmfError e) { + throw e; + } + } + if (mValidVariableChars.find(newoperator) != std::string::npos + || mValidDigitChars.find(newoperator) != std::string::npos) { + try { + XdmfError::message(XdmfError::FATAL, + "Error: Operation Overlaps with Variables"); + } + catch (XdmfError e) { + throw e; + } + } + // Give warning if the operation already exists + size_t origsize = operations.size(); + // Place reference in the associated location + operations[newoperator] = operationref; + // It's nice to let people know they're doing this + // So they don't get surprised about changes in behavior + if (origsize == operations.size()) { + try { + XdmfError::message(XdmfError::WARNING, + "Warning: Operation Overwritten"); + } + catch (XdmfError e) { + throw e; + } + // Overwrite the existing info for that operation + // Add the priority to the specified location in the priority array + mOperationPriority[newoperator] = priority; + } + else { + // Create new operation + // Add operation to the supported character string + mSupportedOperations.push_back(newoperator); + mOperationPriority[newoperator] = priority; + } + return operations.size(); +} + +// This is how you use references to functions +shared_ptr +XdmfFunction::evaluateFunction(std::vector > valueVector, + std::string functionName) +{ + if (arrayFunctions.find(functionName) != arrayFunctions.end()) { + return (*(shared_ptr(*)(std::vector >))arrayFunctions[functionName])(valueVector); + } + else { + return shared_ptr(); + } +} + +std::string +XdmfFunction::getItemTag() const +{ + return ItemTag; +} + +std::map +XdmfFunction::getItemProperties() const +{ + std::map functionProperties; + return functionProperties; +} + +int +XdmfFunction::getOperationPriority(char operation) +{ + size_t operationLocation = mSupportedOperations.find(operation); + if (operationLocation != std::string::npos) { + return mOperationPriority[operation]; + } + else { + return -1; + } +} + + +const std::string +XdmfFunction::getSupportedOperations() +{ + return mSupportedOperations; +} + +const std::vector +XdmfFunction::getSupportedFunctions() +{ + std::vector returnVector; + for (std::map(*)(std::vector >)>::iterator functionWalker + = arrayFunctions.begin(); + functionWalker != arrayFunctions.end(); + ++functionWalker) { + returnVector.push_back(functionWalker->first); + } + return returnVector; +} + +const std::string +XdmfFunction::getValidDigitChars() +{ + return mValidDigitChars; +} + +const std::string +XdmfFunction::getValidVariableChars() +{ + return mValidVariableChars; +} + +shared_ptr +XdmfFunction::interlace(shared_ptr val1, shared_ptr val2) +{ + // Join interlace (evenly space the second array within the first one) + // Builds a new array + shared_ptr 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 resultType = XdmfArrayType::comparePrecision(val1->getArrayType(), val2->getArrayType()); + + if (resultType == XdmfArrayType::Int8()) { + char sampleValue = 0; + returnArray->resize(val1->getSize()+val2->getSize(), sampleValue); + } + else if (resultType == XdmfArrayType::Int16()) { + short sampleValue = 0; + returnArray->resize(val1->getSize()+val2->getSize(), sampleValue); + } + else if (resultType == XdmfArrayType::Int32()) { + int sampleValue = 0; + returnArray->resize(val1->getSize()+val2->getSize(), sampleValue); + } + else if (resultType == XdmfArrayType::Int64()) { + long sampleValue = 0; + returnArray->resize(val1->getSize()+val2->getSize(), sampleValue); + } + else if (resultType == XdmfArrayType::UInt8()) { + unsigned char sampleValue = 0; + returnArray->resize(val1->getSize()+val2->getSize(), sampleValue); + } + else if (resultType == XdmfArrayType::UInt16()) { + unsigned short sampleValue = 0; + returnArray->resize(val1->getSize()+val2->getSize(), sampleValue); + } + else if (resultType == XdmfArrayType::UInt32()) { + unsigned int sampleValue = 0; + returnArray->resize(val1->getSize()+val2->getSize(), sampleValue); + } + else if (resultType == XdmfArrayType::Float32()) { + float sampleValue = 0.0; + returnArray->resize(val1->getSize()+val2->getSize(), sampleValue); + } + else if (resultType == XdmfArrayType::Float64()) { + double sampleValue = 0.0; + returnArray->resize(val1->getSize()+val2->getSize(), sampleValue); + } + else if (resultType == XdmfArrayType::String()) { + std::string sampleValue = ""; + returnArray->resize(val1->getSize()+val2->getSize(), sampleValue); + } + else { + // error type not supported + XdmfError::message(XdmfError::FATAL, "Invalid type during Interlace"); + } + + // Determine ratio of array sizes + int arrayRatio1 = (int)floor(static_cast(val1->getSize())/val2->getSize()); + int arrayRatio2 = (int)floor(static_cast(val2->getSize())/val1->getSize()); + if (arrayRatio1 < 1) { + arrayRatio1 = 1; + } + if (arrayRatio2 < 1) { + arrayRatio2 = 1; + } + // Stride is equal to the ratios rounded up and added together + int stride = arrayRatio1+arrayRatio2; + int arrayExcess1 = 0; + int arrayExcess2 = 0; + for (int i = 0; i < stride; ++i) { + // Add the values of each array, using strides to interlace and starting index to offset + // first array gets the first value of the new array + if (igetSize()/arrayRatio1; + if (((amountWritten * arrayRatio1) + i) < (int)val1->getSize()) { + amountWritten++; + } + if (amountWritten > floor(val2->getSize()/arrayRatio2)) { + arrayExcess1 += amountWritten - (int)floor(val2->getSize()/arrayRatio2); + amountWritten = (int)floor(val2->getSize()/arrayRatio2); + } + returnArray->insert(i, val1, i, amountWritten, stride, arrayRatio1); + } + else { + // Second array takes the rest + int amountWritten = val2->getSize()/arrayRatio2; + if (((amountWritten * arrayRatio2) + i) < (int)val2->getSize()) { + amountWritten++; + } + if (amountWritten > floor(val1->getSize()/arrayRatio1)) { + arrayExcess2 += amountWritten - (int)floor(val1->getSize()/arrayRatio1); + amountWritten = (int)floor(val1->getSize()/arrayRatio1); + } + returnArray->insert(i, val2, i-arrayRatio1, amountWritten, stride, arrayRatio2); + } + } + if (arrayExcess1 > 0) { + returnArray->insert(val1->getSize()+val2->getSize()-arrayExcess1, val1, 0, arrayExcess1, 1, 1); + } + else if (arrayExcess2 > 0) { + returnArray->insert(val1->getSize()+val2->getSize()-arrayExcess2, val2, 0, arrayExcess2, 1, 1); + } + // After all inserts are done, add the excess values to the end of the array + return returnArray; +} + +shared_ptr +XdmfFunction::sum(std::vector > values) +{ + double total = 0.0; + for (unsigned int i = 0; i < values.size(); ++i) { + for (unsigned int j = 0; j < values[i]->getSize(); ++j) { + total += values[i]->getValue(j); + } + } + shared_ptr returnArray = XdmfArray::New(); + returnArray->insert(0, total); + return returnArray; +} + diff --git a/XdmfFunction.hpp b/XdmfFunction.hpp new file mode 100644 index 00000000..28c9b2b8 --- /dev/null +++ b/XdmfFunction.hpp @@ -0,0 +1,501 @@ +/*****************************************************************************/ +/* XDMF */ +/* eXtensible Data Model and Format */ +/* */ +/* Id : XdmfFunction.hpp */ +/* */ +/* Author: */ +/* Kenneth Leiter */ +/* kenneth.leiter@arl.army.mil */ +/* US Army Research Laboratory */ +/* Aberdeen Proving Ground, MD */ +/* */ +/* Copyright @ 2011 US Army Research Laboratory */ +/* All Rights Reserved */ +/* See Copyright.txt for details */ +/* */ +/* This software is distributed WITHOUT ANY WARRANTY; without */ +/* even the implied warranty of MERCHANTABILITY or FITNESS */ +/* FOR A PARTICULAR PURPOSE. See the above copyright notice */ +/* for more information. */ +/* */ +/*****************************************************************************/ + +#ifndef XDMFFUNCTION_HPP_ +#define XDMFFUNCTION_HPP_ + +// Includes +#include "Xdmf.hpp" +#include "XdmfArray.hpp" + +/** + * @brief + * + * + */ +class XDMF_EXPORT XdmfFunction : public XdmfItem { + +public: + + /** + * Create a new XdmfFunction + * + * @return constructed XdmfFunction. + */ + static shared_ptr New(); + + virtual ~XdmfFunction(); + + LOKI_DEFINE_VISITABLE(XdmfFunction, XdmfItem); + + static const std::string ItemTag; + + /** + * Adds an operation to the list of viable operators. + * + * Example of Use: + * + * C++ + * + * @dontinclude ExampleXdmfArray.cpp + * @dontinclude ExampleXdmfArray.cpp + * @skipline //#declareoperation + * @until //#declareoperation + * @skipline //#programstart + * @until //#programstart + * @skipline //#addOperation + * @until //#addOperation + * @skipline //#programend + * @until //#programend + * @skipline //#defineoperation + * @until //#defineoperation + * + * Python + * + * @dontinclude XdmfExampleArray.py + * @skipline #//defineoperation + * @until #//defineoperation + * @skipline #//programstart + * @until #//programstart + * @skipline #//addOperation + * @until #//addOperation + * + * @param newoperator the character to be associated with the provided binary operation + * @param functionref a pointer to the function to be associated with the provided operator + * @param priority used to determine order of operations the higher the value the earlier it is evaluated + */ + static int addOperation(char newoperator, shared_ptr(*functionref)(shared_ptr, shared_ptr), int priority); + + /* + * adds a specified function to the list of functions used while evaluating strings + * + * C++ + * + * @dontinclude ExampleXdmfArray.cpp + * @skipline //#declarefunction + * @until //#declarefunction + * @skipline //#programstart + * @until //#programstart + * @skipline //#addFunction + * @until //#addFunction + * @skipline //#programend + * @until //#programend + * @skipline //#definefunction + * @until //#definefunction + * + * Python + * + * @dontinclude XdmfExampleArray.py + * @skipline #//definefunction + * @until #//definefunction + * @skipline #//programstart + * @until #//programstart + * @skipline #//addFunction + * @until #//addFunction + * + * @param name A string to be associated with the provided function during string evaluation + * @param functionref A pointer to the function to be associated with the given string + * @return The total number of functions currently associated + */ + static int addFunction(std::string name, shared_ptr(*functionref)(std::vector >)); + + /** + * Averages the values contained in all the provided arrays. + * + * C++ + * + * @dontinclude ExampleXdmfArray.cpp + * @skipline //#valueinit + * @until //#valueinit + * @skipline //#average + * @until //#average + * + * Python + * + * @dontinclude XdmfExampleArray.py + * @skipline #//valueinit + * @until #//valueinit + * @skipline #//average + * @until #//average + * + * @param values a vector containing the arrays to be used + * @return an XdmfArray containing one value which is the average of all values contained within the provided arrays + */ + static shared_ptr average(std::vector > values); + + /** + * Joins the two provided arrays together end to end. + * + * Example of Use: + * + * C++ + * + * @dontinclude ExampleXdmfArray.cpp + * @skipline //#valueinit + * @until //#valueinit + * @skipline //#chunk + * @until //#chunk + * + * Python + * + * @dontinclude XdmfExampleArray.py + * @skipline #//valueinit + * @until #//valueinit + * @skipline #//chunk + * @until #//chunk + * + * @param val1 the first array being evaluated + * @param val2 the second array being evaluated + * @return the arrays joined end to end + */ + static shared_ptr chunk(shared_ptr val1, shared_ptr val2); + + /** + * Evaluates an expression based on the list of variables provided. + * A list of valid operations is retrievable from the getSupportedOperations static method. + * None of the XdmfArrays provided are modified during the evaluation process. + * + * Example of Use: + * + * C++ + * + * @dontinclude ExampleXdmfArray.cpp + * @skipline //#declarefunction + * @until //#declarefunction + * @skipline //#declareoperation + * @until //#declareoperation + * @skipline //#programstart + * @until //#programstart + * @skipline //#valueinit + * @until //#valueinit + * @skipline //#addOperation + * @until //#addOperation + * @skipline //#addFunction + * @until //#addFunction + * @skipline //#evaluateExpression + * @until //#evaluateExpression + * @skipline //#programend + * @until //#programend + * @skipline //#definefunction + * @until //#definefunction + * @skipline //#defineoperation + * @until //#defineoperation + * + * Python + * + * @dontinclude XdmfExampleArray.py + * @skipline #//definefunction + * @until #//definefunction + * @skipline #//defineoperation + * @until #//defineoperation + * @skipline #//programstart + * @until #//programstart + * @skipline #//valueinit + * @until #//valueinit + * @skipline #//addOperation + * @until #//addOperation + * @skipline #//addFunction + * @until #//addFunction + * @skipline #//evaluateExpression + * @until #//evaluateExpression + * + * @param expression a string containing the expresion to be evaluated + * @param variables a map of strings to their XdmfArray equivalent + * @return a shared pointer to the XdmfArray resulting from the expression + */ + static shared_ptr evaluateExpression(std::string expression, std::map > variables); + + /** + * Evaluates the operation specified using the two shared pointers to XdmfArrays provided. + * A list of valid operations is retrievable from the getSupportedOperations static method. + * None of the XdmfArrays provided are modified during the evaluation process. + * + * Example of Use: + * + * C++ + * + * @dontinclude ExampleXdmfArray.cpp + * @skipline //#declareoperation + * @until //#declareoperation + * @skipline //#programstart + * @until //#programstart + * @skipline //#valueinit + * @until //#valueinit + * @skipline //#addOperation + * @until //#addOperation + * @skipline //#evaluateOperation + * @until //#evaluateOperation + * @skipline //#programend + * @until //#programend + * @skipline //#defineoperation + * @until //#defineoperation + * + * Python + * + * @dontinclude XdmfExampleArray.py + * @skipline #//defineoperation + * @until #//defineoperation + * @skipline #//programstart + * @until #//programstart + * @skipline #//valueinit + * @until #//valueinit + * @skipline #//addOperation + * @until #//addOperation + * @skipline #//evaluateOperation + * @until #//evaluateOperation + * + * @param val1 the first array being evaluated + * @param val2 the second array being evaluated + * @param operation a character specifying the operation performed + * @return a shared pointer to the Xdmf Array that results from the calculation + */ + static shared_ptr evaluateOperation(shared_ptr val1, shared_ptr val2, char operation); + + /** + * Evaluates the function specified using the vector of XdmfArrays provided. + * None of the XdmfArrays provided are modified during the evaluation process. + * + * C++ + * + * @dontinclude ExampleXdmfArray.cpp + * @skipline //#declarefunction + * @until //#declarefunction + * @skipline //#programstart + * @until //#programstart + * @skipline //#valueinit + * @until //#valueinit + * @skipline //#addFunction + * @until //#addFunction + * @skipline //#evaluateFunction + * @until //#evaluateFunction + * @skipline //#programend + * @until //#programend + * @skipline //#definefunction + * @until //#definefunction + * + * Python + * + * @dontinclude XdmfExampleArray.py + * @skipline #//definefunction + * @until #//definefunction + * @skipline #//programstart + * @until #//programstart + * @skipline #//valueinit + * @until #//valueinit + * @skipline #//addFunction + * @until #//addFunction + * @skipline #//evaluateFunction + * @until #//evaluateFunction + * + * @param valueVector a vector containing the arrays to be used + * @param functionName the string associated with the function being called + * @return the result of the function being called, a scalar will be returned as an XdmfArray with one value + */ + static shared_ptr evaluateFunction(std::vector > valueVector, std::string functionName); + + std::map getItemProperties() const; + + virtual std::string getItemTag() const; + + /** + * Gets the priority of operation whose associated character is provided. Returns -1 if the operation is not supported. + * The higher the value the earlier that operation is evaluated during evaluateExpression. + * + * Example of Use: + * + * C++ + * + * @dontinclude ExampleXdmfArray.cpp + * @skipline //#getOperationPriority + * @until //#getOperationPriority + * + * Python + * + * @dontinclude XdmfExampleArray.py + * @skipline #//getOperationPriority + * @until #//getOperationPriority + * + * @param operation the character associated with the operation to be checked + * @return the priority of the operation + */ + static int getOperationPriority(char operation); + + /** + * Gets a string that contains all the characters of the supported operations. + * Parenthesis are included for grouping purposes in expressions. + * + * Example of Use: + * + * C++ + * + * @dontinclude ExampleXdmfArray.cpp + * @skipline //#getSupportedOperations + * @until //#getSupportedOperations + * + * Python + * + * @dontinclude XdmfExampleArray.py + * @skipline #//getSupportedOperations + * @until #//getSupportedOperations + * + * @return a string containing the characters for all supported operations + */ + static const std::string getSupportedOperations(); + + /** + * Gets a string that contains all the characters of the supported operations. + * Parenthesis are included for grouping purposes in expressions. + * + * Example of Use: + * + * C++ + * + * @dontinclude ExampleXdmfArray.cpp + * @skipline //#getSupportedFunctions + * @until //#getSupportedFunctions + * + * Python + * + * @dontinclude XdmfExampleArray.py + * @skipline #//getSupportedFunctions + * @until #//getSupportedFunctions + * + * @return a vector containing the strings associated with all valid functions + */ + static const std::vector getSupportedFunctions(); + + /** + * Gets a string that contains all strings that are viable for use when mapping + * to scalars (which are stored in XdmfArrays of size 1) for the evaluateExpression function. + * + * Example of Use: + * + * C++ + * + * @dontinclude ExampleXdmfArray.cpp + * @skipline //#getValidDigitChars + * @until //#getValidDigitChars + * + * Python + * + * @dontinclude XdmfExampleArray.py + * @skipline #//getValidDigitChars + * @until #//getValidDigitChars + * + * @return a string containing all valid variable characters + */ + static const std::string getValidDigitChars(); + + /** + * Gets a string that contains all strings that are viable for use when mapping + * to shared pointers of XdmfArrays for the evaluateExpression function. + * + * Example of Use: + * + * C++ + * + * @dontinclude ExampleXdmfArray.cpp + * @skipline //#getValidVariableChars + * @until //#getValidVariableChars + * + * Python + * + * @dontinclude XdmfExampleArray.py + * @skipline #//getValidVariableChars + * @until #//getValidVariableChars + * + * @return a string containing all valid variable characters + */ + static const std::string getValidVariableChars(); + + /** + * Joins the two provided arrays while interspercing their values evenly. + * Example of Use: + * + * C++ + * + * @dontinclude ExampleXdmfArray.cpp + * @skipline //#valueinit + * @until //#valueinit + * @skipline //#interlace + * @until //#interlace + * + * Python + * + * @dontinclude XdmfExampleArray.py + * @skipline #//valueinit + * @until #//valueinit + * @skipline #//interlace + * @until #//interlace + * + * @param val1 the first array being evaluated + * @param val2 the second array being evaluated + * @return the interlaced arrays + */ + static shared_ptr interlace(shared_ptr val1, shared_ptr val2); + + /** + * Adds together all the values contained in the provided arrays. + * + * C++ + * + * @dontinclude ExampleXdmfArray.cpp + * @skipline //#valueinit + * @until //#valueinit + * @skipline //#sum + * @until //#sum + * + * Python + * + * @dontinclude XdmfExampleArray.py + * @skipline #//valueinit + * @until #//valueinit + * @skipline #//sum + * @until #//sum + * + * @param values a vector containing the arrays to be used + * @return an XdmfArray containing one value which is the total of all the values contained within the provided arrays + */ + static shared_ptr sum(std::vector > values); + +protected: + + XdmfFunction(); + +private: + + XdmfFunction(const XdmfFunction &); // Not implemented. + void operator=(const XdmfFunction &); // Not implemented. + + + static std::string mSupportedOperations; + static const std::string mValidVariableChars; + static const std::string mValidDigitChars; + + static std::map mOperationPriority; + static std::map(*)(std::vector >)> arrayFunctions; + static std::map(*)(shared_ptr, shared_ptr)> operations; + +}; + +#endif /* XDMFFUNCTION_HPP_ */ diff --git a/XdmfGeometry.hpp b/XdmfGeometry.hpp index d715c955..1cf28c60 100644 --- a/XdmfGeometry.hpp +++ b/XdmfGeometry.hpp @@ -51,12 +51,14 @@ public: * C++ * * @dontinclude ExampleXdmfGeometry.cpp - * @skipline New + * @skipline //#initialization + * @until //#initialization * * Python * * @dontinclude XdmfExampleGeometry.py - * @skipline New + * @skipline #//initialization + * @until #//initialization * * @return constructed XdmfGeometry. */ @@ -79,14 +81,18 @@ public: * C++ * * @dontinclude ExampleXdmfGeometry.cpp - * @skipline Assuming - * @skipline getNumberPoints + * @skipline //#initialization + * @until //#initialization + * @skipline //#getNumberPoints + * @until //#getNumberPoints * * Python * * @dontinclude XdmfExampleGeometry.py - * @skipline Assuming - * @skipline getNumberPoints + * @skipline #//initialization + * @until #//initialization + * @skipline #//getNumberPoints + * @until #//getNumberPoints */ virtual unsigned int getNumberPoints() const; @@ -98,14 +104,18 @@ public: * C++ * * @dontinclude ExampleXdmfGeometry.cpp - * @skipline Assuming - * @skipline getType + * @skipline //#initialization + * @until //#initialization + * @skipline //#getType + * @until //#getType * * Python * * @dontinclude XdmfExampleGeometry.py - * @skipline Assuming - * @skipline getType + * @skipline #//initialization + * @until #//initialization + * @skipline #//getType + * @until #//getType * * @return XdmfGeometryType of this geometry. */ @@ -119,14 +129,18 @@ public: * C++ * * @dontinclude ExampleXdmfGeometry.cpp - * @skipline New - * @skipline setType + * @skipline //#initialization + * @until //#initialization + * @skipline //#setType + * @until //#setType * * Python * * @dontinclude XdmfExampleGeometry.py - * @skipline New - * @skipline setType + * @skipline #//initialization + * @until #//initialization + * @skipline #//setType + * @until #//setType * * @param type the XdmfGeometryType to set. */ diff --git a/XdmfGeometryType.hpp b/XdmfGeometryType.hpp index c8be0aaa..0646f192 100644 --- a/XdmfGeometryType.hpp +++ b/XdmfGeometryType.hpp @@ -42,14 +42,16 @@ * C++ * * @dontinclude ExampleXdmfGeometryType.cpp - * @skipline getType - * @until } + * @skipline //#initialization + * @until //#initialization + * @skipline //#getType + * @until //#getType * * Python * * @dontinclude XdmfExampleGeometryType.py - * @skipline getType - * @until do + * @skipline #//getType + * @until #//getType * * Xdmf supports the following geometry types: * NoGeometryType @@ -77,12 +79,14 @@ public: * C++ * * @dontinclude ExampleXdmfGeometryType.cpp - * @skipline getDimensions + * @skipline //#getDimensions + * @until //#getDimensions * * Python * * @dontinclude XdmfExampleGeometryType.py - * @skipline getDimensions + * @skipline #//getDimensions + * @until #//getDimensions * * @return an int containing number of dimensions. */ @@ -96,12 +100,14 @@ public: * C++ * * @dontinclude ExampleXdmfGeometryType.cpp - * @skipline getName + * @skipline //#getName + * @until //#getName * * Python * * @dontinclude XdmfExampleGeometryType.py - * @skipline getName + * @skipline #//getName + * @until #//getName * * @return the name of this geometry type. */ diff --git a/XdmfGraph.hpp b/XdmfGraph.hpp index ceafa347..8bd9e9d7 100644 --- a/XdmfGraph.hpp +++ b/XdmfGraph.hpp @@ -49,12 +49,14 @@ public: * C++ * * @dontinclude ExampleXdmfGraph.cpp - * @skipline New + * @skipline //#initialization + * @until //#initialization * * Python * * @dontinclude XdmfExampleGraph.py - * @skipline New + * @skipline #//initialization + * @until #//initialization * * @param numberNodes number of nodes in graph. * diff --git a/XdmfGrid.hpp b/XdmfGrid.hpp index 499d9d26..89aeba38 100644 --- a/XdmfGrid.hpp +++ b/XdmfGrid.hpp @@ -71,16 +71,18 @@ public: * C++ * * @dontinclude ExampleXdmfGrid.cpp - * @skipline Using - * @until Assumming - * @skipline getGeometry + * @skipline //#initialization + * @until //#initialization + * @skipline //#getGeometry + * @until //#getGeometry * * Python * * @dontinclude XdmfExampleGrid.py - * @skipline Using - * @until Assumming - * @skipline getGeometry + * @skipline #//initialization + * @until #//initialization + * @skipline #//getGeometry + * @until #//getGeometry * * @return the geometry associated with this grid. */ @@ -98,16 +100,22 @@ public: * C++ * * @dontinclude ExampleXdmfGrid.cpp - * @skipline Using - * @until Assumming - * @skipline getName + * @skipline //#initialization + * @until //#initialization + * @skipline //#setName + * @until //#setName + * @skipline //#getName + * @until //#getName * * Python * * @dontinclude XdmfExampleGrid.py - * @skipline Using - * @until Assumming - * @skipline getName + * @skipline #//initialization + * @until #//initialization + * @skipline #//setName + * @until #//setName + * @skipline #//getName + * @until #//getName * * @return the name of the grid. */ @@ -121,16 +129,22 @@ public: * C++ * * @dontinclude ExampleXdmfGrid.cpp - * @skipline Using - * @until Assumming - * @skipline getTime + * @skipline //#initialization + * @until //#initialization + * @skipline //#setTime + * @until //#setTime + * @skipline //#getTime + * @until //#getTime * * Python * * @dontinclude XdmfExampleGrid.py - * @skipline Using - * @until Assumming - * @skipline getTime + * @skipline #//initialization + * @until #//initialization + * @skipline #//setTime + * @until #//setTime + * @skipline #//getTime + * @until #//getTime * * @return pointer to the XdmfTime attached to this grid. If no * XdmfTime is attached, return a NULL pointer. @@ -145,9 +159,12 @@ public: * C++ * * @dontinclude ExampleXdmfGrid.cpp - * @skipline Using - * @until Assumming - * @skipline exampleTimeConst + * @skipline //#initialization + * @until //#initialization + * @skipline //#setTime + * @until //#setTime + * @skipline //#getTimeconst + * @until //#getTimeconst * * Python: Python doesn't have a constant version * @@ -164,16 +181,18 @@ public: * C++ * * @dontinclude ExampleXdmfGrid.cpp - * @skipline Using - * @until Assumming - * @skipline getTopology + * @skipline //#initialization + * @until //#initialization + * @skipline //#getTopology + * @until //#getTopology * * Python * * @dontinclude XdmfExampleGrid.py - * @skipline Using - * @until Assumming - * @skipline getTopology + * @skipline #//initialization + * @until #//initialization + * @skipline #//getTopology + * @until #//getTopology * * @return the topology associated with this grid. */ @@ -189,18 +208,18 @@ public: * C++ * * @dontinclude ExampleXdmfGrid.cpp - * @skipline Using - * @until Assumming - * @skipline newName - * @skipline setName + * @skipline //#initialization + * @until //#initialization + * @skipline //#setName + * @until //#setName * * Python * * @dontinclude XdmfExampleGrid.py - * @skipline Using - * @until Assumming - * @skipline newName - * @skipline setName + * @skipline #//initialization + * @until #//initialization + * @skipline #//setName + * @until #//setName * * @param name of the grid to set. */ @@ -214,18 +233,18 @@ public: * C++ * * @dontinclude ExampleXdmfGrid.cpp - * @skipline Using - * @until Assumming - * @skipline newTime - * @skipline setTime + * @skipline //#initialization + * @until //#initialization + * @skipline //#setTime + * @until //#setTime * * Python * * @dontinclude XdmfExampleGrid.py - * @skipline Using - * @until Assumming - * @skipline newTime - * @skipline setTime + * @skipline #//initialization + * @until #//initialization + * @skipline #//setTime + * @until #//setTime * * @param time an XdmfTime to associate with this grid. */ diff --git a/XdmfGridCollection.hpp b/XdmfGridCollection.hpp index 3de37480..12dee798 100644 --- a/XdmfGridCollection.hpp +++ b/XdmfGridCollection.hpp @@ -56,12 +56,14 @@ public: * C++ * * @dontinclude ExampleXdmfGridCollection.cpp - * @skipline New + * @skipline //#initalization + * @until //#initalization * * Python * * @dontinclude XdmfExampleGridCollection.py - * @skipline New + * @skipline #//initalization + * @until #//initalization * * @return constructed XdmfGridCollection. */ @@ -84,14 +86,18 @@ public: * C++ * * @dontinclude ExampleXdmfGridCollection.cpp - * @skipline Assuming - * @skipline getType + * @skipline //#initalization + * @until //#initalization + * @skipline //#getType + * @until //#getType * * Python * * @dontinclude XdmfExampleGridCollection.py - * @skipline Assuming - * @skipline getType + * @skipline #//initalization + * @until #//initalization + * @skipline #//getType + * @until #//getType * * @return XdmfGridCollectionType of this collection. */ @@ -108,18 +114,18 @@ public: * C++ * * @dontinclude ExampleXdmfGridCollection.cpp - * @skipline Assuming - * @skipline exampleInformation - * @until setValue - * @skipline insert + * @skipline //#initalization + * @until //#initalization + * @skipline //#insert + * @until //#insert * * Python * * @dontinclude XdmfExampleGridCollection.py - * @skipline Assuming - * @skipline exampleInformation - * @until setValue - * @skipline insert + * @skipline #//initalization + * @until #//initalization + * @skipline #//insert + * @until #//insert * * @param information an XdmfInformation to attach to this item. */ @@ -134,14 +140,18 @@ public: * C++ * * @dontinclude ExampleXdmfGridCollection.cpp - * @skipline Assuming - * @skipline setType + * @skipline //#initalization + * @until //#initalization + * @skipline //#setType + * @until //#setType * * Python * * @dontinclude XdmfExampleGridCollection.py - * @skipline Assuming - * @skipline setType + * @skipline #//initalization + * @until #//initalization + * @skipline #//setType + * @until #//setType * * @param type the XdmfGridCollectionType to set. */ diff --git a/XdmfGridCollectionType.hpp b/XdmfGridCollectionType.hpp index 8ba13e0d..bb53835b 100644 --- a/XdmfGridCollectionType.hpp +++ b/XdmfGridCollectionType.hpp @@ -42,14 +42,18 @@ * C++ * * @dontinclude ExampleXdmfGridCollection.cpp - * @skipline exampleType - * @until } + * @skipline //#initalization + * @until //#initalization + * @skipline //#getType + * @until //#getType * * Python * * @dontinclude XdmfExampleGridCollection.py - * @skipline exampleType - * @until do + * @skipline #//initalization + * @until #//initalization + * @skipline #//getType + * @until #//getType * * Xdmf supports the following collection types: * NoCollectionType diff --git a/XdmfItemFactory.cpp b/XdmfItemFactory.cpp index 3f772a0f..4748fd68 100644 --- a/XdmfItemFactory.cpp +++ b/XdmfItemFactory.cpp @@ -26,6 +26,7 @@ #include "XdmfAttribute.hpp" #include "XdmfCurvilinearGrid.hpp" #include "XdmfDomain.hpp" +#include "XdmfFunction.hpp" #include "XdmfGeometry.hpp" #include "XdmfGeometryType.hpp" #include "XdmfGraph.hpp" @@ -227,6 +228,75 @@ XdmfItemFactory::createItem(const std::string & itemTag, } return XdmfTopology::New(); } + else if (itemTag.compare(XdmfFunction::ItemTag) == 0) { + std::map::const_iterator type = + itemProperties.find("ConstructedType"); + std::string arraySubType; + if(type == itemProperties.end()) { + // If no type is specified an array is generated + arraySubType = "DataItem"; + } + else { + arraySubType = type->second; + } + + std::map::const_iterator expression = + itemProperties.find("Expression"); + std::string expressionToParse; + if(expression == itemProperties.end()) { + try { + XdmfError::message(XdmfError::FATAL, "Error: Function found no expression"); + } + catch (XdmfError e) { + throw e; + } + } + else { + expressionToParse = expression->second; + } + std::map > variableCollection; + for (unsigned int i = 0; i < childItems.size(); ++i) { + try { + shared_ptr tempArray = shared_dynamic_cast(childItems[i]); + variableCollection[tempArray->getName()] = tempArray; + tempArray->read(); + } + catch (...) { + try { + XdmfError::message(XdmfError::FATAL, "Error: Function passed non-Array item"); + } + catch (XdmfError e) { + throw e; + } + } + } + shared_ptr parsedArray = shared_ptr(); + try { + parsedArray = XdmfFunction::evaluateExpression(expressionToParse, variableCollection); + } + catch (XdmfError e) { + throw e; + } + if (arraySubType != "DataItem") { + // The properties and children aren't really needed to generate the object, but the factory still requires them. + std::vector > newArrayChildren; + shared_ptr returnArray = XdmfArray::New(); + + // This should generate an item that corresponds to the tag provided, the casting ensures that it is a subtype of array + // Using a factory to be able to build things outside of core + returnArray = shared_dynamic_cast(createItem( + arraySubType, + itemProperties, + newArrayChildren)); + + returnArray->insert(0, parsedArray, 0, parsedArray->getSize()); + //returnArray->setFunction(); + return returnArray; + } + else { + return parsedArray; + } + } return shared_ptr(); } catch (XdmfError e) { diff --git a/XdmfItemFactory.hpp b/XdmfItemFactory.hpp index 92a63c38..bda691ea 100644 --- a/XdmfItemFactory.hpp +++ b/XdmfItemFactory.hpp @@ -47,12 +47,14 @@ public: * C++ * * @dontinclude ExampleXdmfItemFactory.cpp - * @skipline New + * @skipline //#initialization + * @until //#initialization * * Python * * @dontinclude XdmfExampleItemFactory.py - * @skipline New + * @skipline #//initialization + * @until #//initialization * * @return constructed XdmfItemFactory. */ diff --git a/XdmfMap.hpp b/XdmfMap.hpp index e400c0f2..74364528 100644 --- a/XdmfMap.hpp +++ b/XdmfMap.hpp @@ -70,12 +70,14 @@ public: * C++ * * @dontinclude ExampleXdmfMap.cpp - * @skipline New + * @skipline //#initialization + * @until //#initialization * * Python * * @dontinclude XdmfExampleMap.py - * @skipline New + * @skipline #//initialization + * @until #//initialization * * @return constructed XdmfMap. */ @@ -91,16 +93,14 @@ public: * C++ * * @dontinclude ExampleXdmfMap.cpp - * @skipline holdGlobalNodes - * @until localNodeID) + * @skipline //#initializationnode + * @until //#initializationnode * * Python * * @dontinclude XdmfExampleMap.py - * @skipline #create - * @until push_back(map2Attribute) - * @skipline New - * @until localNodeID) + * @skipline #//initializationnode + * @until #//initializationnode * * @param globalNodeIds a vector of attributes containing globalNodeId * values for each partition to be mapped. @@ -126,16 +126,18 @@ public: * C++ * * @dontinclude ExampleXdmfMap.cpp - * @skip getMap - * @skipline Assuming - * @until //remoteNodeValue + * @skipline //#initialization + * @until //#initialization + * @skipline //#getMap + * @until //#getMap * * Python * * @dontinclude XdmfExampleMap.py - * @skip getMap - * @skipline Assuming - * @until #prints + * @skipline #//initialization + * @until #//initialization + * @skipline #//getMap + * @until #//getMap * * @return stored boundary communicator map. */ @@ -149,14 +151,22 @@ public: * C++ * * @dontinclude ExampleXdmfMap.cpp - * @skipline Assumming - * @skipline getName + * @skipline //#initialization + * @until //#initialization + * @skipline //#setName + * @until //#setName + * @skipline //#getName + * @until //#getName * * Python * * @dontinclude XdmfExampleMap.py - * @skipline Assumming - * @skipline getName + * @skipline #//initialization + * @until #//initialization + * @skipline #//setName + * @until #//setName + * @skipline #//getName + * @until #//getName * * @return name of boundary communicator map. */ @@ -171,20 +181,18 @@ public: * C++ * * @dontinclude ExampleXdmfMap.cpp - * @skip getMap - * @skipline Assuming - * @until 4) - * @skipline getRemoteNodeIds - * @until //remoteNodeValue + * @skipline //#initialization + * @until //#initialization + * @skipline //#getRemoteNodeIds + * @until //#getRemoteNodeIds * * Python * * @dontinclude XdmfExampleMap.py - * @skip getMap - * @skipline Assuming - * @until 4) - * @skipline getRemoteNodeIds - * @until #prints + * @skipline #//initialization + * @until #//initialization + * @skipline #//getRemoteNodeIds + * @until #//getRemoteNodeIds * * @param remoteTaskId a task id to retrieve mapping for. * @@ -205,16 +213,18 @@ public: * C++ * * @dontinclude ExampleXdmfMap.cpp - * @skipline New - * @skipline newRemoteTaskID - * @until //This + * @skipline //#initialization + * @until //#initialization + * @skipline //#inserttuple + * @until //#inserttuple * * Python * * @dontinclude XdmfExampleMap.py - * @skipline New - * @skipline newRemoteTaskID - * @until #This + * @skipline #//initialization + * @until #//initialization + * @skipline #//inserttuple + * @until #//inserttuple * * @param remoteTaskId task id where the remoteLoalNodeId is located. * @param localNodeId the node id of the node being mapped. @@ -234,16 +244,18 @@ public: * C++ * * @dontinclude ExampleXdmfMap.cpp - * @skipline Assumming - * @skipline isInitialized - * @until } + * @skipline //#initialization + * @until //#initialization + * @skipline //#isInitialized + * @until //#isInitialized * * Python * * @dontinclude XdmfExampleMap.py - * @skipline Assumming - * @skipline isInitialized - * @until read + * @skipline //#initialization + * @until //#initialization + * @skipline #//isInitialized + * @until #//isInitialized * * @return bool true if map contains values in memory. */ @@ -257,16 +269,18 @@ public: * C++ * * @dontinclude ExampleXdmfMap.cpp - * @skipline Assumming - * @skipline isInitialized - * @until } + * @skipline //#initialization + * @until //#initialization + * @skipline //#isInitialized + * @until //#isInitialized * * Python * * @dontinclude XdmfExampleMap.py - * @skipline Assumming - * @skipline isInitialized - * @until read + * @skipline //#initialization + * @until //#initialization + * @skipline #//isInitialized + * @until #//isInitialized */ void read(); @@ -278,14 +292,18 @@ public: * C++ * * @dontinclude ExampleXdmfMap.cpp - * @skipline Assumming - * @skipline release + * @skipline //#initialization + * @until //#initialization + * @skipline //#release + * @until //#release * * Python * * @dontinclude XdmfExampleMap.py - * @skipline Assumming - * @skipline release + * @skipline //#initialization + * @until //#initialization + * @skipline #//release + * @until #//release */ void release(); @@ -297,14 +315,18 @@ public: * C++ * * @dontinclude ExampleXdmfMap.cpp - * @skipline hdf5FilePath - * @until setHeavyDataController + * @skipline //#initialization + * @until //#initialization + * @skipline //#setHeavyDataController + * @until //#setHeavyDataController * * Python * * @dontinclude XdmfExampleMap.py - * @skipline hdf5FilePath - * @until setHeavyDataController + * @skipline //#initialization + * @until //#initialization + * @skipline #//setHeavyDataController + * @until #//setHeavyDataController * * @param remoteTaskIdsControllers a vector of XdmfHeavyDataControllers to the remote * task ids dataset. @@ -326,16 +348,18 @@ public: * C++ * * @dontinclude ExampleXdmfMap.cpp - * @skipline New - * First create a std::map > - * @skipline taskMap - * @until //Are + * @skipline //#initialization + * @until //#initialization + * @skipline //#setMap + * @until //#setMap * * Python * * @dontinclude XdmfExampleMap.py - * @skipline newTaskMap - * @until #Is + * @skipline #//initialization + * @until #//initialization + * @skipline #//setMap + * @until #//setMap * * @param map the boundary communicator map to store. */ @@ -349,16 +373,18 @@ public: * C++ * * @dontinclude ExampleXdmfMap.cpp - * @skipline Assumming - * @skipline newName - * @until setName + * @skipline //#initialization + * @until //#initialization + * @skipline //#setName + * @until //#setName * * Python * * @dontinclude XdmfExampleMap.py - * @skipline Assumming - * @skipline newName - * @until setName + * @skipline #//initialization + * @until #//initialization + * @skipline #//setName + * @until #//setName * * @param name the name of the boundary communicator map to set. */ diff --git a/XdmfReader.hpp b/XdmfReader.hpp index 25197b9f..ef929ed2 100644 --- a/XdmfReader.hpp +++ b/XdmfReader.hpp @@ -48,12 +48,14 @@ public: * C++ * * @dontinclude ExampleXdmfReader.cpp - * @skipline New + * @skipline //#initialization + * @until //#initialization * * Python * * @dontinclude XdmfExampleReader.py - * @skipline New + * @skipline #//initialization + * @until #//initialization * * @return constructed XdmfReader. */ diff --git a/XdmfRectilinearGrid.cpp b/XdmfRectilinearGrid.cpp index 441d9ec3..e477bcff 100644 --- a/XdmfRectilinearGrid.cpp +++ b/XdmfRectilinearGrid.cpp @@ -276,7 +276,7 @@ public: private: XdmfTopologyTypeRectilinear(const XdmfRectilinearGrid * const rectilinearGrid) : - XdmfTopologyType(0, 0, 0, "foo", XdmfTopologyType::Structured, 0x1101), + XdmfTopologyType(0, 0, std::vector >(), 0, "foo", XdmfTopologyType::Structured, 0x1101), mRectilinearGrid(rectilinearGrid) { } diff --git a/XdmfRectilinearGrid.hpp b/XdmfRectilinearGrid.hpp index d44a4d32..c266366b 100644 --- a/XdmfRectilinearGrid.hpp +++ b/XdmfRectilinearGrid.hpp @@ -55,15 +55,18 @@ public: * C++ * * @dontinclude ExampleXdmfRectilinearGrid.cpp - * @skipline pointsXArray - * @until pointsYArray->pushBack(10) - * @skipline XdmfRectilinearGrid + * @skipline //#initvalues + * @until //#initvalues + * @skipline //#initialization2 + * @until //#initialization2 * * Python * * @dontinclude XdmfExampleRectilinearGrid.py - * @skipline pointsXArray - * @until XdmfRectilinearGrid + * @skipline #//initvalues + * @until #//initvalues + * @skipline #//initialization2 + * @until #//initialization2 * * @param xCoordinates the coordinates of points along the x axis * @param yCoordinates the coordinates of points along the y axis. @@ -82,18 +85,18 @@ public: * C++ * * @dontinclude ExampleXdmfRectilinearGrid.cpp - * @skipline pointsXArray - * @until pointsZArray->pushBack(2) - * @skip size - * @skipline pointsZArray + * @skipline //#initvalues + * @until //#initvalues + * @skipline //#initialization3 + * @until //#initialization3 * * Python * * @dontinclude XdmfExampleRectilinearGrid.py - * @skipline pointsXArray - * @until pointsYArray.pushBackAsInt32(10) - * @skipline pointsZArray - * @until XdmfRectilinearGrid + * @skipline #//initvalues + * @until #//initvalues + * @skipline #//initialization3 + * @until #//initialization3 * * @param xCoordinates the coordinates of points along the x axis * @param yCoordinates the coordinates of points along the y axis. @@ -114,20 +117,18 @@ public: * C++ * * @dontinclude ExampleXdmfRectilinearGrid.cpp - * @skipline pointsXArray - * @until pointsZArray->pushBack(2) - * @skipline pointsCollector - * @until XdmfRectilinearGrid + * @skipline //#initvalues + * @until //#initvalues + * @skipline //#initializationvector + * @until //#initializationvector * * Python * * @dontinclude XdmfExampleRectilinearGrid.py - * @skipline pointsXArray - * @until pointsYArray.pushBackAsInt32(10) - * @skipline pointsZArray - * @until pointsZArray.pushBackAsInt32(2) - * @skipline pointsCollector - * @until XdmfRectilinearGrid + * @skipline #//initvalues + * @until #//initvalues + * @skipline #//initializationvector + * @until #//initializationvector * * @param axesCoordinates the coordinates of points along each axis. * @@ -149,16 +150,22 @@ public: * C++ * * @dontinclude ExampleXdmfRectilinearGrid.cpp - * @skipline Assuming - * @skipline readPointsX - * @until readPointsY + * @skipline //#initvalues + * @until //#initvalues + * @skipline //#initialization2 + * @until //#initialization2 + * @skipline //#getCoodinatessingle + * @until //#getCoodinatessingle * * Python * * @dontinclude XdmfExampleRectilinearGrid.py - * @skipline Assuming - * @skipline readPointsX - * @until readPointsY + * @skipline #//initvalues + * @until #//initvalues + * @skipline #//initialization2 + * @until #//initialization2 + * @skipline #//getCoodinatessingle + * @until #//getCoodinatessingle * * @param axisIndex the index of the axis to retrieve, (i.e. 0 for * x-axis). If no array exists at the index, return NULL. @@ -176,9 +183,12 @@ public: * C++ * * @dontinclude ExampleXdmfRectilinearGrid.cpp - * @skipline Assuming - * @skipline readPointsXConst - * @until readPointsYConst + * @skipline //#initvalues + * @until //#initvalues + * @skipline //#initialization2 + * @until //#initialization2 + * @skipline //#getCoodinatessingleconst + * @until //#getCoodinatessingleconst * * Python: does not support a constant version of this function * @@ -198,14 +208,22 @@ public: * C++ * * @dontinclude ExampleXdmfRectilinearGrid.cpp - * @skipline Assuming - * @skipline exampleCoordinates + * @skipline //#initvalues + * @until //#initvalues + * @skipline //#initializationvector + * @until //#initializationvector + * @skipline //#getCoodinatesvector + * @until //#getCoodinatesvector * * Python * * @dontinclude XdmfExampleRectilinearGrid.py - * @skipline Assuming - * @skipline exampleCoordinates + * @skipline #//initvalues + * @until #//initvalues + * @skipline #//initializationvector + * @until #//initializationvector + * @skipline #//getCoodinatesvector + * @until #//getCoodinatesvector * * @return vector containing an array of coordinates along each * direction. @@ -220,8 +238,12 @@ public: * C++ * * @dontinclude ExampleXdmfRectilinearGrid.cpp - * @skipline Assuming - * @skipline exampleCoordinatesConst + * @skipline //#initvalues + * @until //#initvalues + * @skipline //#initializationvector + * @until //#initializationvector + * @skipline //#getCoodinatesvectorconst + * @until //#getCoodinatesvectorconst * * Python: does not support a constant version of this function * @@ -239,14 +261,22 @@ public: * C++ * * @dontinclude ExampleXdmfRectilinearGrid.cpp - * @skipline Assuming - * @skipline exampleDimensions + * @skipline //#initvalues + * @until //#initvalues + * @skipline //#initializationvector + * @until //#initializationvector + * @skipline //#getDimensions + * @until //#getDimensions * * Python * * @dontinclude XdmfExampleRectilinearGrid.py - * @skipline Assuming - * @skipline exampleDimensions + * @skipline #//initvalues + * @until #//initvalues + * @skipline #//initializationvector + * @until #//initializationvector + * @skipline #//getDimensions + * @until #//getDimensions * * @return XdmfArray containing dimensions of this grid. */ @@ -261,8 +291,12 @@ public: * C++ * * @dontinclude ExampleXdmfRectilinearGrid.cpp - * @skipline Assuming - * @skipline exampleDimensionsConst + * @skipline //#initvalues + * @until //#initvalues + * @skipline //#initializationvector + * @until //#initializationvector + * @skipline //#getDimensionsconst + * @until //#getDimensionsconst * * Python: Doesn't support a constant version of this function * @@ -278,18 +312,22 @@ public: * C++ * * @dontinclude ExampleXdmfRectilinearGrid.cpp - * @skipline Assuming - * @skipline pointsXArray - * @until pointsXArray->pushBack(10) - * @skipline setCoordinates + * @skipline //#initvalues + * @until //#initvalues + * @skipline //#initialization3 + * @until //#initialization3 + * @skipline //#setCoordinatessingle + * @until //#setCoordinatessingle * * Python * * @dontinclude XdmfExampleRectilinearGrid.py - * @skipline Assuming - * @skipline pointsXArray - * @until pointsXArray.pushBackAsInt32(10) - * @skipline setCoordinates + * @skipline #//initvalues + * @until #//initvalues + * @skipline #//initialization3 + * @until #//initialization3 + * @skipline #//setCoordinatessingle + * @until #//setCoordinatessingle * * @param axisIndex the index of the axis to set (i.e. 0 for x-axis). * @param axisCoordinates the coordinates of points along a single axis to @@ -306,24 +344,22 @@ public: * C++ * * @dontinclude ExampleXdmfRectilinearGrid.cpp - * @skipline Assuming - * @skipline pointsXArray - * @until pointsZArray->pushBack(2); - * @skipline pointsCollector - * @until pointsZArray - * @skipline setCoordinates + * @skipline //#initvalues + * @until //#initvalues + * @skipline //#initializationvector + * @until //#initializationvector + * @skipline //#setCoordinatesvector + * @until //#setCoordinatesvector * * Python * * @dontinclude XdmfExampleRectilinearGrid.py - * @skipline Assuming - * @skipline pointsXArray - * @until pointsYArray.pushBackAsInt32(10) - * @skipline pointsZArray - * @until pointsZArray.pushBackAsInt32(2) - * @skipline ArrayVector - * @until pointsZArray - * @skipline setCoordinates + * @skipline #//initvalues + * @until #//initvalues + * @skipline #//initializationvector + * @until #//initializationvector + * @skipline #//setCoordinatesvector + * @until #//setCoordinatesvector * * @param axesCoordinates the coordinates of points along each axis. */ diff --git a/XdmfRegularGrid.cpp b/XdmfRegularGrid.cpp index b91a7c43..4d2f038d 100644 --- a/XdmfRegularGrid.cpp +++ b/XdmfRegularGrid.cpp @@ -267,7 +267,7 @@ public: private: XdmfTopologyTypeRegular(const XdmfRegularGrid * const regularGrid) : - XdmfTopologyType(0, 0, 0, "foo", XdmfTopologyType::Structured, 0x1102), + XdmfTopologyType(0, 0, std::vector >(), 0, "foo", XdmfTopologyType::Structured, 0x1102), mRegularGrid(regularGrid) { } diff --git a/XdmfRegularGrid.hpp b/XdmfRegularGrid.hpp index d4d39a26..1e54a70f 100644 --- a/XdmfRegularGrid.hpp +++ b/XdmfRegularGrid.hpp @@ -55,18 +55,18 @@ public: * C++ * * @dontinclude ExampleXdmfRegularGrid.cpp - * @skipline newBrickX - * @until newOriginY - * @skipline XdmfRegularGrid - * @until ; + * @skipline //#initvalue + * @until //#initvalue + * @skipline //#initialization2 + * @until //#initialization2 * * Python * * @dontinclude XdmfExampleRegularGrid.py - * @skipline newBrickX - * @until newOriginY - * @skipline XdmfRegularGrid - * @until ) + * @skipline #//initvalue + * @until #//initvalue + * @skipline #//initialization2 + * @until #//initialization2 * * @param xBrickSize the size of the brick in the x direction. * @param yBrickSize the size of the brick in the y direction. @@ -92,18 +92,18 @@ public: * C++ * * @dontinclude ExampleXdmfRegularGrid.cpp - * @skipline newBrickX - * @until newOriginY - * @skipline XdmfRegularGrid - * @skipline newBrickZ + * @skipline //#initvalue + * @until //#initvalue + * @skipline //#initialization3 + * @until //#initialization3 * * Python * * @dontinclude XdmfExampleRegularGrid.py - * @skipline newBrickX - * @until newOriginY - * @skipline XdmfRegularGrid - * @skipline newBrickZ + * @skipline #//initvalue + * @until #//initvalue + * @skipline #//initialization3 + * @until #//initialization3 * * @param xBrickSize the size of the brick in the x direction. * @param yBrickSize the size of the brick in the y direction. @@ -135,14 +135,14 @@ public: * C++ * * @dontinclude ExampleXdmfRegularGrid.cpp - * @skipline newBrickSize - * @until XdmfRegularGrid + * @skipline //#initializationvector + * @until //#initializationvector * * Python * * @dontinclude XdmfExampleRegularGrid.py - * @skipline newBrickSize - * @until XdmfRegularGrid + * @skipline #//initializationvector + * @until #//initializationvector * * @param brickSize the size of the brick in each direction. * @param numPoints the number of points in each direction. @@ -168,14 +168,22 @@ public: * C++ * * @dontinclude ExampleXdmfRegularGrid.cpp - * @skipline Assuming - * @skipline exampleBrick + * @skipline //#initvalue + * @until //#initvalue + * @skipline //#initialization2 + * @until //#initialization2 + * @skipline //#getBrickSize + * @until //#getBrickSize * * Python * * @dontinclude XdmfExampleRegularGrid.py - * @skipline Assuming - * @skipline getBrickSize + * @skipline #//initvalue + * @until #//initvalue + * @skipline #//initialization2 + * @until #//initialization2 + * @skipline #//getBrickSize + * @until #//getBrickSize * * @return XdmfArray containing brick sizes for this grid. */ @@ -189,8 +197,12 @@ public: * C++ * * @dontinclude ExampleXdmfRegularGrid.cpp - * @skipline Assuming - * @skipline exampleBrickConst + * @skipline //#initvalue + * @until //#initvalue + * @skipline //#initialization2 + * @until //#initialization2 + * @skipline //#getBrickSizeconst + * @until //#getBrickSizeconst * * Python: Does not support a constant version of this function * @@ -207,14 +219,22 @@ public: * C++ * * @dontinclude ExampleXdmfRegularGrid.cpp - * @skipline Assuming - * @skipline exampleDimensions + * @skipline //#initvalue + * @until //#initvalue + * @skipline //#initialization2 + * @until //#initialization2 + * @skipline //#getDimensions + * @until //#getDimensions * * Python * * @dontinclude XdmfExampleRegularGrid.py - * @skipline Assuming - * @skipline getDimensions + * @skipline #//initvalue + * @until #//initvalue + * @skipline #//initialization2 + * @until #//initialization2 + * @skipline #//getDimensions + * @until #//getDimensions * * @return XdmfArray containing dimensions of this grid. */ @@ -229,8 +249,12 @@ public: * C++ * * @dontinclude ExampleXdmfRegularGrid.cpp - * @skipline Assuming - * @skipline exampleDimensions + * @skipline //#initvalue + * @until //#initvalue + * @skipline //#initialization2 + * @until //#initialization2 + * @skipline //#getDimensionsconst + * @until //#getDimensionsconst * * Python: Does not support a constant version of this function * @@ -246,14 +270,22 @@ public: * C++ * * @dontinclude ExampleXdmfRegularGrid.cpp - * @skipline Assuming - * @skipline exampleOrigin + * @skipline //#initvalue + * @until //#initvalue + * @skipline //#initialization2 + * @until //#initialization2 + * @skipline //#getOrigin + * @until //#getOrigin * * Python * * @dontinclude XdmfExampleRegularGrid.py - * @skipline Assuming - * @skipline getOrigin + * @skipline #//initvalue + * @until #//initvalue + * @skipline #//initialization2 + * @until #//initialization2 + * @skipline #//getOrigin + * @until #//getOrigin * * @return XdmfArray containing the location of the origin of the * grid. @@ -268,8 +300,12 @@ public: * C++ * * @dontinclude ExampleXdmfRegularGrid.cpp - * @skipline Assuming - * @skipline exampleOriginConst + * @skipline //#initvalue + * @until //#initvalue + * @skipline //#initialization2 + * @until //#initialization2 + * @skipline //#getOriginconst + * @until //#getOriginconst * * Python: Does not support a constant version of this function * @@ -286,18 +322,18 @@ public: * C++ * * @dontinclude ExampleXdmfRegularGrid.cpp - * @skipline Assuming - * @skipline newBrickSize - * @until newBrickSize->pushBack(22.0) - * @skipline setBrickSize + * @skipline //#initializationvector + * @until //#initializationvector + * @skipline //#setBrickSize + * @until //#setBrickSize * * Python * * @dontinclude XdmfExampleRegularGrid.py - * @skipline Assuming - * @skipline newBrickSize - * @until newBrickSize.pushBackAsFloat64(22.0) - * @skipline setBrickSize + * @skipline #//initializationvector + * @until #//initializationvector + * @skipline #//setBrickSize + * @until #//setBrickSize * * @param brickSize the sizes of the points composing the mesh. This * should have the same number of terms as the dimensionality of the @@ -314,18 +350,18 @@ public: * C++ * * @dontinclude ExampleXdmfRegularGrid.cpp - * @skipline Assuming - * @skipline newNumPoints - * @until newNumPoints->pushBack(7) - * @skipline setDimensions + * @skipline //#initializationvector + * @until //#initializationvector + * @skipline //#setDimensions + * @until //#setDimensions * * Python * * @dontinclude XdmfExampleRegularGrid.py - * @skipline Assuming - * @skipline newNumPoints - * @until newNumPoints.pushBackAsUInt32(7) - * @skipline setDimensions + * @skipline #//initializationvector + * @until #//initializationvector + * @skipline #//setDimensions + * @until #//setDimensions * * @param dimensions the dimension of the grid. */ @@ -339,18 +375,18 @@ public: * C++ * * @dontinclude ExampleXdmfRegularGrid.cpp - * @skipline Assuming - * @skipline newGridOrigin - * @until newGridOrigin->pushBack(2.0) - * @skipline setOrigin + * @skipline //#initializationvector + * @until //#initializationvector + * @skipline //#setOrigin + * @until //#setOrigin * * Python * * @dontinclude XdmfExampleRegularGrid.py - * @skipline Assuming - * @skipline newGridOrigin - * @until newGridOrigin.pushBackAsFloat64(2.0) - * @skipline setOrigin + * @skipline #//initializationvector + * @until #//initializationvector + * @skipline #//setOrigin + * @until #//setOrigin * * @param origin location of the origin of the grid. This should * have the same number of terms as the dimensionality of the mesh. diff --git a/XdmfSet.hpp b/XdmfSet.hpp index 092f3683..9f7a8d08 100644 --- a/XdmfSet.hpp +++ b/XdmfSet.hpp @@ -56,12 +56,14 @@ public: * C++ * * @dontinclude ExampleXdmfSet.cpp - * @skipline New + * @skipline //#initialize + * @until //#initialize * * Python * * @dontinclude XdmfExampleSet.py - * @skipline New + * @skipline #//initialize + * @until #//initialize * * @return constructed XdmfSet. */ @@ -85,14 +87,22 @@ public: * C++ * * @dontinclude ExampleXdmfSet.cpp - * @skipline Assuming - * @skipline getName + * @skipline //#initialize + * @until //#initialize + * @skipline //#setName + * @until //#setName + * @skipline //#getName + * @until //#getName * * Python * * @dontinclude XdmfExampleSet.py - * @skipline Assuming - * @skipline getName + * @skipline #//initialize + * @until #//initialize + * @skipline #//setName + * @until #//setName + * @skipline #//getName + * @until #//getName * * @return a string containing the name of the set. */ @@ -106,14 +116,22 @@ public: * C++ * * @dontinclude ExampleXdmfSet.cpp - * @skipline Assuming - * @skipline getType + * @skipline //#initialize + * @until //#initialize + * @skipline //#setType + * @until //#setType + * @skipline //#getType + * @until //#getType * * Python * * @dontinclude XdmfExampleSet.py - * @skipline Assuming - * @skipline getType + * @skipline #//initialize + * @until #//initialize + * @skipline #//setType + * @until #//setType + * @skipline #//getType + * @until #//getType * * @return XdmfSetType of this set. */ @@ -133,16 +151,18 @@ public: * C++ * * @dontinclude ExampleXdmfSet.cpp - * @skipline New - * @skipline newName - * @until setName + * @skipline //#initialize + * @until //#initialize + * @skipline //#setName + * @until //#setName * * Python * * @dontinclude XdmfExampleSet.py - * @skipline New - * @skipline newName - * @until setName + * @skipline #//initialize + * @until #//initialize + * @skipline #//setName + * @until #//setName * * @param name a string containing the name to set. */ @@ -156,14 +176,18 @@ public: * C++ * * @dontinclude ExampleXdmfSet.cpp - * @skipline New - * @skipline setType + * @skipline //#initialize + * @until //#initialize + * @skipline //#setType + * @until //#setType * * Python * * @dontinclude XdmfExampleSet.py - * @skipline New - * @skipline setType + * @skipline //#initialize + * @until //#initialize + * @skipline //#setType + * @until //#setType * * @param type the XdmfSetType to set. */ diff --git a/XdmfSetType.hpp b/XdmfSetType.hpp index f205cd2a..74620c58 100644 --- a/XdmfSetType.hpp +++ b/XdmfSetType.hpp @@ -17,14 +17,22 @@ * C++ * * @dontinclude ExampleXdmfSet.cpp - * @skipline exampleType - * @until } + * @skipline //#initialize + * @until //#initialize + * @skipline //#setType + * @until //#setType + * @skipline //#getType + * @until //#getType * * Python * * @dontinclude XdmfExampleSet.py - * @skipline exampleType - * @until do + * @skipline #//initialize + * @until #//initialize + * @skipline #//setType + * @until #//setType + * @skipline #//getType + * @until #//getType * * Xdmf supports the following set types: * NoSetType diff --git a/XdmfTime.hpp b/XdmfTime.hpp index 35949e18..d7c01bc2 100644 --- a/XdmfTime.hpp +++ b/XdmfTime.hpp @@ -45,14 +45,14 @@ public: * C++ * * @dontinclude ExampleXdmfTime.cpp - * @skipline New - * @until exampleTime2 + * @skipline //#initialization + * @until //#initialization * * Python * * @dontinclude XdmfExampleTime.py - * @skipline New - * @until exampleTime2 + * @skipline #//initialization + * @until #//initialization * * @param value the timeValue of the XdmfTime to create. * @return the new XdmfTime. @@ -76,14 +76,18 @@ public: * C++ * * @dontinclude ExampleXdmfTime.cpp - * @skipline Assumming - * @skipline getTime + * @skipline //#initialization + * @until //#initialization + * @skipline //#getValue + * @until //#getValue * * Python * * @dontinclude XdmfExampleTime.py - * @skipline Assumming - * @skipline getTime + * @skipline #//initialization + * @until #//initialization + * @skipline #//getValue + * @until #//getValue * * @return a double containing the time value. */ @@ -97,16 +101,18 @@ public: * C++ * * @dontinclude ExampleXdmfTime.cpp - * @skipline New - * @skipline newTime - * @skipline setValue + * @skipline //#initialization + * @until //#initialization + * @skipline //#setValue + * @until //#setValue * * Python * * @dontinclude XdmfExampleTime.py - * @skipline New - * @skipline newTime - * @skipline setValue + * @skipline #//initialization + * @until #//initialization + * @skipline #//setValue + * @until #//setValue * * @param time a double containing the time value. */ diff --git a/XdmfTopology.hpp b/XdmfTopology.hpp index 362ca49c..cd5b7a53 100644 --- a/XdmfTopology.hpp +++ b/XdmfTopology.hpp @@ -64,12 +64,14 @@ public: * C++ * * @dontinclude ExampleXdmfTopology.cpp - * @skipline New + * @skipline //#initialization + * @until //#initialization * * Python * * @dontinclude XdmfExampleTopology.py - * @skipline New + * @skipline #//initialization + * @until #//initialization * * @return constructed XdmfTopology. */ @@ -92,14 +94,18 @@ public: * C++ * * @dontinclude ExampleXdmfTopology.cpp - * @skipline Assuming - * @skipline getNumberElements + * @skipline //#initialization + * @until //#initialization + * @skipline //#getNumberElements + * @until //#getNumberElements * * Python * * @dontinclude XdmfExampleTopology.py - * @skipline Assuming - * @skipline getNumberElements + * @skipline #//initialization + * @until #//initialization + * @skipline #//getNumberElements + * @until #//getNumberElements * * @return int of number elements in the Topology. */ @@ -113,14 +119,22 @@ public: * C++ * * @dontinclude ExampleXdmfTopology.cpp - * @skipline Assuming - * @skipline getType + * @skipline //#initialization + * @until //#initialization + * @skipline //#setType + * @until //#setType + * @skipline //#getType + * @until //#getType * * Python * * @dontinclude XdmfExampleTopology.py - * @skipline Assuming - * @skipline getType + * @skipline #//initialization + * @until #//initialization + * @skipline #//setType + * @until #//setType + * @skipline #//getType + * @until #//getType * * @return XdmfTopologyType of the topology. */ @@ -134,14 +148,18 @@ public: * C++ * * @dontinclude ExampleXdmfTopology.cpp - * @skipline New - * @skipline setType + * @skipline //#initialization + * @until //#initialization + * @skipline //#setType + * @until //#setType * * Python * * @dontinclude XdmfExampleTopology.py - * @skipline New - * @skipline setType + * @skipline #//initialization + * @until #//initialization + * @skipline #//setType + * @until #//setType * * @param type the XdmfTopologyType to set. */ diff --git a/XdmfTopologyType.cpp b/XdmfTopologyType.cpp index 03a2f64c..34622cc4 100644 --- a/XdmfTopologyType.cpp +++ b/XdmfTopologyType.cpp @@ -24,6 +24,7 @@ #include #include #include +#include #include "XdmfError.hpp" #include "XdmfTopologyType.hpp" @@ -31,22 +32,27 @@ shared_ptr XdmfTopologyType::NoTopologyType() { + std::vector > faces; static shared_ptr - p(new XdmfTopologyType(0, 0, 0, "NoTopology", NoCellType, 0x0)); + p(new XdmfTopologyType(0, 0, faces, 0, "NoTopology", NoCellType, 0x0)); return p; } shared_ptr XdmfTopologyType::Polyvertex() { + std::vector > faces; + faces.push_back(XdmfTopologyType::NoTopologyType()); static shared_ptr - p(new XdmfTopologyType(1, 0, 0, "Polyvertex", Linear, 0x1)); + p(new XdmfTopologyType(1, 0, faces, 0, "Polyvertex", Linear, 0x1)); return p; } shared_ptr XdmfTopologyType::Polyline(const unsigned int nodesPerElement) { + std::vector > faces; + faces.push_back(XdmfTopologyType::NoTopologyType()); static std::map > previousTypes; std::map >::const_iterator @@ -55,7 +61,7 @@ XdmfTopologyType::Polyline(const unsigned int nodesPerElement) return type->second; } shared_ptr - p(new XdmfTopologyType(nodesPerElement, 0, nodesPerElement - 1, + p(new XdmfTopologyType(nodesPerElement, 0, faces, nodesPerElement - 1, "Polyline", Linear, 0x2)); previousTypes[nodesPerElement] = p; return p; @@ -64,6 +70,8 @@ XdmfTopologyType::Polyline(const unsigned int nodesPerElement) shared_ptr XdmfTopologyType::Polygon(const unsigned int nodesPerElement) { + std::vector > faces; + faces.push_back(XdmfTopologyType::NoTopologyType()); static std::map > previousTypes; std::map >::const_iterator @@ -72,7 +80,7 @@ XdmfTopologyType::Polygon(const unsigned int nodesPerElement) return type->second; } shared_ptr - p(new XdmfTopologyType(nodesPerElement, 1, nodesPerElement, + p(new XdmfTopologyType(nodesPerElement, 1, faces, nodesPerElement, "Polygon", Linear, 0x3)); previousTypes[nodesPerElement] = p; return p; @@ -81,160 +89,201 @@ XdmfTopologyType::Polygon(const unsigned int nodesPerElement) shared_ptr XdmfTopologyType::Triangle() { + std::vector > faces; + faces.push_back(XdmfTopologyType::NoTopologyType()); static shared_ptr - p(new XdmfTopologyType(3, 1, 3, "Triangle", Linear, 0x4)); + p(new XdmfTopologyType(3, 1, faces, 3, "Triangle", Linear, 0x4)); return p; } shared_ptr XdmfTopologyType::Quadrilateral() { + std::vector > faces; + faces.push_back(XdmfTopologyType::NoTopologyType()); static shared_ptr - p(new XdmfTopologyType(4, 1, 4, "Quadrilateral", Linear, 0x5)); + p(new XdmfTopologyType(4, 1, faces, 4, "Quadrilateral", Linear, 0x5)); return p; } shared_ptr XdmfTopologyType::Tetrahedron() { + std::vector > faces; + faces.push_back(XdmfTopologyType::Triangle()); static shared_ptr - p(new XdmfTopologyType(4, 4, 6, "Tetrahedron", Linear, 0x6)); + p(new XdmfTopologyType(4, 4, faces, 6, "Tetrahedron", Linear, 0x6)); return p; } shared_ptr XdmfTopologyType::Pyramid() { + std::vector > faces; + faces.push_back(XdmfTopologyType::NoTopologyType()); static shared_ptr - p(new XdmfTopologyType(5, 5, 8, "Pyramid", Linear, 0x7)); + p(new XdmfTopologyType(5, 5, faces, 8, "Pyramid", Linear, 0x7)); return p; } shared_ptr XdmfTopologyType::Wedge() { + std::vector > faces; + faces.push_back(XdmfTopologyType::NoTopologyType()); static shared_ptr - p(new XdmfTopologyType(6, 5, 9, "Wedge", Linear, 0x8)); + p(new XdmfTopologyType(6, 5, faces, 9, "Wedge", Linear, 0x8)); return p; } shared_ptr XdmfTopologyType::Hexahedron() { + std::vector > faces; + faces.push_back(XdmfTopologyType::Quadrilateral()); static shared_ptr - p(new XdmfTopologyType(8, 6, 12, "Hexahedron", Linear, 0x9)); + p(new XdmfTopologyType(8, 6, faces, 12, "Hexahedron", Linear, 0x9)); return p; } shared_ptr XdmfTopologyType::Edge_3() { + std::vector > faces; + faces.push_back(XdmfTopologyType::NoTopologyType()); static shared_ptr - p(new XdmfTopologyType(3, 0, 1, "Edge_3", Quadratic, 0x22)); + p(new XdmfTopologyType(3, 0, faces, 1, "Edge_3", Quadratic, 0x22)); return p; } shared_ptr XdmfTopologyType::Triangle_6() { + std::vector > faces; + faces.push_back(XdmfTopologyType::NoTopologyType()); static shared_ptr - p(new XdmfTopologyType(6, 1, 3, "Triangle_6", Quadratic, 0x24)); + p(new XdmfTopologyType(6, 1, faces, 3, "Triangle_6", Quadratic, 0x24)); return p; } shared_ptr XdmfTopologyType::Quadrilateral_8() { + std::vector > faces; + faces.push_back(XdmfTopologyType::NoTopologyType()); static shared_ptr - p(new XdmfTopologyType(8, 1, 4, "Quadrilateral_8", Quadratic, 0x25)); + p(new XdmfTopologyType(8, 1, faces, 4, "Quadrilateral_8", Quadratic, 0x25)); return p; } shared_ptr XdmfTopologyType::Quadrilateral_9() { + std::vector > faces; + faces.push_back(XdmfTopologyType::NoTopologyType()); static shared_ptr - p(new XdmfTopologyType(9, 1, 4, "Quadrilateral_9", Quadratic, 0x23)); + p(new XdmfTopologyType(9, 1, faces, 4, "Quadrilateral_9", Quadratic, 0x23)); return p; } shared_ptr XdmfTopologyType::Tetrahedron_10() { + std::vector > faces; + faces.push_back(XdmfTopologyType::NoTopologyType()); + faces.push_back(XdmfTopologyType::Triangle_6()); static shared_ptr - p(new XdmfTopologyType(10, 4, 6, "Tetrahedron_10", Quadratic, 0x26)); + p(new XdmfTopologyType(10, 4, faces, 6, "Tetrahedron_10", Quadratic, 0x26)); return p; } shared_ptr XdmfTopologyType::Pyramid_13() { + std::vector > faces; + faces.push_back(XdmfTopologyType::NoTopologyType()); static shared_ptr - p(new XdmfTopologyType(13, 5, 8, "Pyramid_13", Quadratic, 0x27)); + p(new XdmfTopologyType(13, 5, faces, 8, "Pyramid_13", Quadratic, 0x27)); return p; } shared_ptr XdmfTopologyType::Wedge_15() { + std::vector > faces; + faces.push_back(XdmfTopologyType::NoTopologyType()); static shared_ptr - p(new XdmfTopologyType(15, 5, 9, "Wedge_15", Quadratic, 0x28)); + p(new XdmfTopologyType(15, 5, faces, 9, "Wedge_15", Quadratic, 0x28)); return p; } shared_ptr XdmfTopologyType::Wedge_18() { + std::vector > faces; + faces.push_back(XdmfTopologyType::NoTopologyType()); static shared_ptr - p(new XdmfTopologyType(18, 5, 9, "Wedge_18", Quadratic, 0x29)); + p(new XdmfTopologyType(18, 5, faces, 9, "Wedge_18", Quadratic, 0x29)); return p; } shared_ptr XdmfTopologyType::Hexahedron_20() { + std::vector > faces; + faces.push_back(XdmfTopologyType::Quadrilateral_8()); static shared_ptr - p(new XdmfTopologyType(20, 6, 12, "Hexahedron_20", Quadratic, 0x30)); + p(new XdmfTopologyType(20, 6, faces, 12, "Hexahedron_20", Quadratic, 0x30)); return p; } shared_ptr XdmfTopologyType::Hexahedron_24() { + std::vector > faces; + faces.push_back(XdmfTopologyType::NoTopologyType()); static shared_ptr - p(new XdmfTopologyType(24, 6, 12, "Hexahedron_24", Quadratic, 0x31)); + p(new XdmfTopologyType(24, 6, faces, 12, "Hexahedron_24", Quadratic, 0x31)); return p; } shared_ptr XdmfTopologyType::Hexahedron_27() { + std::vector > faces; + faces.push_back(XdmfTopologyType::Quadrilateral_9()); static shared_ptr - p(new XdmfTopologyType(27, 6, 12, "Hexahedron_27", Quadratic, 0x32)); + p(new XdmfTopologyType(27, 6, faces, 12, "Hexahedron_27", Quadratic, 0x32)); return p; } shared_ptr XdmfTopologyType::Hexahedron_64() { + std::vector > faces; + faces.push_back(XdmfTopologyType::NoTopologyType()); static shared_ptr - p(new XdmfTopologyType(64, 6, 12, "Hexahedron_64", Cubic, 0x33)); + p(new XdmfTopologyType(64, 6, faces, 12, "Hexahedron_64", Cubic, 0x33)); return p; } shared_ptr XdmfTopologyType::Hexahedron_125() { + std::vector > faces; + faces.push_back(XdmfTopologyType::NoTopologyType()); static shared_ptr - p(new XdmfTopologyType(125, 6, 12, "Hexahedron_125", Quartic, 0x34)); + p(new XdmfTopologyType(125, 6, faces, 12, "Hexahedron_125", Quartic, 0x34)); return p; } shared_ptr XdmfTopologyType::Hexahedron_216() { + std::vector > faces; + faces.push_back(XdmfTopologyType::NoTopologyType()); static shared_ptr - p(new XdmfTopologyType(216, 6, 12, "Hexahedron_216", Quintic, 0x35)); + p(new XdmfTopologyType(216, 6, faces, 12, "Hexahedron_216", Quintic, 0x35)); return p; } @@ -242,8 +291,10 @@ XdmfTopologyType::Hexahedron_216() shared_ptr XdmfTopologyType::Hexahedron_343() { + std::vector > faces; + faces.push_back(XdmfTopologyType::NoTopologyType()); static shared_ptr - p(new XdmfTopologyType(343, 6, 12, "Hexahedron_343", Sextic, 0x36)); + p(new XdmfTopologyType(343, 6, faces, 12, "Hexahedron_343", Sextic, 0x36)); return p; } @@ -251,8 +302,10 @@ XdmfTopologyType::Hexahedron_343() shared_ptr XdmfTopologyType::Hexahedron_512() { + std::vector > faces; + faces.push_back(XdmfTopologyType::NoTopologyType()); static shared_ptr - p(new XdmfTopologyType(512, 6, 12, "Hexahedron_512", Septic, 0x37)); + p(new XdmfTopologyType(512, 6, faces, 12, "Hexahedron_512", Septic, 0x37)); return p; } @@ -260,8 +313,10 @@ XdmfTopologyType::Hexahedron_512() shared_ptr XdmfTopologyType::Hexahedron_729() { + std::vector > faces; + faces.push_back(XdmfTopologyType::NoTopologyType()); static shared_ptr - p(new XdmfTopologyType(729, 6, 12, "Hexahedron_729", Octic, 0x38)); + p(new XdmfTopologyType(729, 6, faces, 12, "Hexahedron_729", Octic, 0x38)); return p; } @@ -269,32 +324,40 @@ XdmfTopologyType::Hexahedron_729() shared_ptr XdmfTopologyType::Hexahedron_1000() { + std::vector > faces; + faces.push_back(XdmfTopologyType::NoTopologyType()); static shared_ptr - p(new XdmfTopologyType(1000, 6, 12, "Hexahedron_1000", Nonic, 0x39)); + p(new XdmfTopologyType(1000, 6, faces, 12, "Hexahedron_1000", Nonic, 0x39)); return p; } shared_ptr XdmfTopologyType::Hexahedron_1331() { + std::vector > faces; + faces.push_back(XdmfTopologyType::NoTopologyType()); static shared_ptr - p(new XdmfTopologyType(1331, 6, 12, "Hexahedron_1331", Decic, 0x40)); + p(new XdmfTopologyType(1331, 6, faces, 12, "Hexahedron_1331", Decic, 0x40)); return p; } shared_ptr XdmfTopologyType::Hexahedron_Spectral_64() { + std::vector > faces; + faces.push_back(XdmfTopologyType::NoTopologyType()); static shared_ptr - p(new XdmfTopologyType(64, 6, 12, "Hexahedron_Spectral_64", Cubic, 0x41)); + p(new XdmfTopologyType(64, 6, faces, 12, "Hexahedron_Spectral_64", Cubic, 0x41)); return p; } shared_ptr XdmfTopologyType::Hexahedron_Spectral_125() { + std::vector > faces; + faces.push_back(XdmfTopologyType::NoTopologyType()); static shared_ptr - p(new XdmfTopologyType(125, 6, 12, + p(new XdmfTopologyType(125, 6, faces, 12, "Hexahedron_Spectral_125", Quartic, 0x42)); return p; } @@ -302,8 +365,10 @@ XdmfTopologyType::Hexahedron_Spectral_125() shared_ptr XdmfTopologyType::Hexahedron_Spectral_216() { + std::vector > faces; + faces.push_back(XdmfTopologyType::NoTopologyType()); static shared_ptr - p(new XdmfTopologyType(216, 6, 12, + p(new XdmfTopologyType(216, 6, faces, 12, "Hexahedron_Spectral_216", Quintic, 0x43)); return p; } @@ -312,8 +377,10 @@ XdmfTopologyType::Hexahedron_Spectral_216() shared_ptr XdmfTopologyType::Hexahedron_Spectral_343() { + std::vector > faces; + faces.push_back(XdmfTopologyType::NoTopologyType()); static shared_ptr - p(new XdmfTopologyType(343, 6, 12, + p(new XdmfTopologyType(343, 6, faces, 12, "Hexahedron_Spectral_343", Sextic, 0x44)); return p; } @@ -322,8 +389,10 @@ XdmfTopologyType::Hexahedron_Spectral_343() shared_ptr XdmfTopologyType::Hexahedron_Spectral_512() { + std::vector > faces; + faces.push_back(XdmfTopologyType::NoTopologyType()); static shared_ptr - p(new XdmfTopologyType(512, 6, 12, + p(new XdmfTopologyType(512, 6, faces, 12, "Hexahedron_Spectral_512", Septic, 0x45)); return p; } @@ -332,8 +401,10 @@ XdmfTopologyType::Hexahedron_Spectral_512() shared_ptr XdmfTopologyType::Hexahedron_Spectral_729() { + std::vector > faces; + faces.push_back(XdmfTopologyType::NoTopologyType()); static shared_ptr - p(new XdmfTopologyType(729, 6, 12, + p(new XdmfTopologyType(729, 6, faces, 12, "Hexahedron_Spectral_729", Octic, 0x46)); return p; } @@ -342,8 +413,10 @@ XdmfTopologyType::Hexahedron_Spectral_729() shared_ptr XdmfTopologyType::Hexahedron_Spectral_1000() { + std::vector > faces; + faces.push_back(XdmfTopologyType::NoTopologyType()); static shared_ptr - p(new XdmfTopologyType(1000, 6, 12, + p(new XdmfTopologyType(1000, 6, faces, 12, "Hexahedron_Spectral_1000", Nonic, 0x47)); return p; } @@ -351,8 +424,10 @@ XdmfTopologyType::Hexahedron_Spectral_1000() shared_ptr XdmfTopologyType::Hexahedron_Spectral_1331() { + std::vector > faces; + faces.push_back(XdmfTopologyType::NoTopologyType()); static shared_ptr - p(new XdmfTopologyType(1331, 6, 12, + p(new XdmfTopologyType(1331, 6, faces, 12, "Hexahedron_Spectral_1331", Decic, 0x48)); return p; } @@ -360,8 +435,9 @@ XdmfTopologyType::Hexahedron_Spectral_1331() shared_ptr XdmfTopologyType::Mixed() { + std::vector > faces; static shared_ptr - p(new XdmfTopologyType(0, 0, 0, "Mixed", Arbitrary, 0x70)); + p(new XdmfTopologyType(0, 0, faces, 0, "Mixed", Arbitrary, 0x70)); return p; } @@ -487,12 +563,14 @@ XdmfTopologyType::New(const unsigned int id) XdmfTopologyType::XdmfTopologyType(const unsigned int nodesPerElement, const unsigned int facesPerElement, + std::vector > faces, const unsigned int edgesPerElement, const std::string & name, const CellType cellType, const unsigned int id) : mCellType(cellType), mEdgesPerElement(edgesPerElement), + mFaces(faces), mFacesPerElement(facesPerElement), mID(id), mName(name), @@ -683,6 +761,17 @@ XdmfTopologyType::getEdgesPerElement() const return mEdgesPerElement; } +shared_ptr +XdmfTopologyType::getFaceType() +{ + if (mFaces.size() == 0) { + return XdmfTopologyType::NoTopologyType(); + } + else { + return mFaces[0]; + } +} + unsigned int XdmfTopologyType::getFacesPerElement() const { diff --git a/XdmfTopologyType.hpp b/XdmfTopologyType.hpp index b0d63d5b..90d505cb 100644 --- a/XdmfTopologyType.hpp +++ b/XdmfTopologyType.hpp @@ -42,14 +42,14 @@ * C++ * * @dontinclude ExampleXdmfTopologyType.cpp - * @skipline getType - * @until } + * @skipline //#getType + * @until //#getType * * Python * * @dontinclude XdmfExampleTopologyType.py - * @skipline getType - * @until do + * @skipline #//getType + * @until #//getType * * Xdmf supports the following topology types: * NoTopologyType @@ -166,14 +166,14 @@ public: * C++ * * @dontinclude ExampleXdmfTopologyType.cpp - * @skipline exampleID - * @until setType + * @skipline //#initialization + * @until //#initialization * * Python * * @dontinclude XdmfExampleTopologyType.py - * @skipline exampleID - * @until setType + * @skipline #//initialization + * @until #//initialization * * @param id of the topology type. * @@ -190,15 +190,14 @@ public: * C++ * * @dontinclude ExampleXdmfTopologyType.cpp - * @skipline exampleType - * @until } + * @skipline //#getCellType + * @until //#getCellType * * Python * * @dontinclude XdmfExampleTopologyType.py - * @skipline exampleType - * @until Do - * @skipline ''' + * @skipline #//getCellType + * @until #//getCellType * * @return a CellType containing the cell type. */ @@ -212,12 +211,14 @@ public: * C++ * * @dontinclude ExampleXdmfTopologyType.cpp - * @skipline getEdgesPerElement + * @skipline //#getEdgesPerElement + * @until //#getEdgesPerElement * * Python * * @dontinclude XdmfExampleTopologyType.py - * @skipline getEdgesPerElement + * @skipline #//getEdgesPerElement + * @until #//getEdgesPerElement * * @return an unsigned int containing the number of edges per element. */ @@ -231,17 +232,40 @@ public: * C++ * * @dontinclude ExampleXdmfTopologyType.cpp - * @skipline getFacesPerElement + * @skipline //#getFacesPerElement + * @until //#getFacesPerElement * * Python * * @dontinclude XdmfExampleTopologyType.py - * @skipline getFacePerElement + * @skipline #//getFacesPerElement + * @until #//getFacesPerElement * * @return an unsigned int containing the number of faces per element. */ virtual unsigned int getFacesPerElement() const; + /** + * Gets the type of the faces of the topology. + * + * Example of use: + * + * C++ + * + * @dontinclude ExampleXdmfTopologyType.cpp + * @skipline //#getFaceType + * @until //#getFaceType + * + * Python + * + * @dontinclude XdmfExampleTopologyType.py + * @skipline #//getFaceType + * @until #//getFaceType + * + * @return The face's topology type + */ + shared_ptr getFaceType(); + /** * Get the id of this cell type, necessary in order to create grids * containing mixed cells. @@ -251,12 +275,14 @@ public: * C++ * * @dontinclude ExampleXdmfTopologyType.cpp - * @skipline holdID + * @skipline //#getID + * @until //#getID * * Python * * @dontinclude XdmfExampleTopologyType.py - * @skipline holdID + * @skipline //#getID + * @until //#getID * * @return the ID of the topology type. */ @@ -270,12 +296,14 @@ public: * C++ * * @dontinclude ExampleXdmfTopologyType.cpp - * @skipline getName + * @skipline //#getName + * @until //#getName * * Python * * @dontinclude XdmfExampleTopologyType.py - * @skipline getName + * @skipline #//getName + * @until #//getName * * @return the name of this topology type. */ @@ -290,12 +318,14 @@ public: * C++ * * @dontinclude ExampleXdmfTopologyType.cpp - * @skipline getNodesPerElement + * @skipline //#getNodesPerElement + * @until //#getNodesPerElement * * Python * * @dontinclude XdmfExampleTopologyType.py - * @skipline getNodesPerElement + * @skipline #//getNodesPerElement + * @until #//getNodesPerElement * * @return an unsigned int containing number of nodes per element. */ @@ -314,6 +344,7 @@ protected: */ XdmfTopologyType(const unsigned int nodesPerElement, const unsigned int facesPerElement, + std::vector > faces, const unsigned int edgesPerElement, const std::string & name, const CellType cellType, @@ -330,6 +361,7 @@ private: const CellType mCellType; const unsigned int mEdgesPerElement; const unsigned int mFacesPerElement; + std::vector > mFaces; const unsigned int mID; const std::string mName; const unsigned int mNodesPerElement; diff --git a/XdmfUnstructuredGrid.hpp b/XdmfUnstructuredGrid.hpp index adede72f..9ed1e6c3 100644 --- a/XdmfUnstructuredGrid.hpp +++ b/XdmfUnstructuredGrid.hpp @@ -52,12 +52,14 @@ public: * C++ * * @dontinclude ExampleXdmfUnstructuredGrid.cpp - * @skipline New + * @skipline //#initialization + * @until //#initialization * * Python * * @dontinclude XdmfExampleUnstructuredGrid.py - * @skipline New + * @skipline #//initialization + * @until #//initialization * * @return constructed XdmfUnstructuredGrid. */ @@ -71,14 +73,14 @@ public: * C++ * * @dontinclude ExampleXdmfUnstructuredGrid.cpp - * @skipline newBrickX - * @until XdmfUnstructuredGrid + * @skipline //#initializationregular + * @until //#initializationregular * * Python * * @dontinclude XdmfExampleUnstructuredGrid.py - * @skipline newBrickX - * @until XdmfUnstructuredGrid + * @skipline #//initializationregular + * @until #//initializationregular * * @param regularGrid The grid that the unstructured grid will be created from * @@ -99,14 +101,22 @@ public: * C++ * * @dontinclude ExampleXdmfUnstructuredGrid.cpp - * @skipline Assuming - * @skipline getGeometry + * @skipline //#initialization + * @until //#initialization + * @skipline //#setGeometry + * @until //#setGeometry + * @skipline //#getGeometry + * @until //#getGeometry * * Python * * @dontinclude XdmfExampleUnstructuredGrid.py - * @skipline Assuming - * @skipline getGeometry + * @skipline #//initialization + * @until #//initialization + * @skipline #//setGeometry + * @until #//setGeometry + * @skipline #//getGeometry + * @until #//getGeometry * * @return the geometry associated with this grid. */ @@ -122,14 +132,22 @@ public: * C++ * * @dontinclude ExampleXdmfUnstructuredGrid.cpp - * @skipline Assuming - * @skipline getTopology + * @skipline //#initialization + * @until //#initialization + * @skipline //#setTopology + * @until //#setTopology + * @skipline //#getTopology + * @until //#getTopology * * Python * * @dontinclude XdmfExampleUnstructuredGrid.py - * @skipline Assuming - * @skipline getTopology + * @skipline #//initialization + * @until #//initialization + * @skipline #//setTopology + * @until #//setTopology + * @skipline #//getTopology + * @until #//getTopology * * @return the topology associated with this grid. */ @@ -143,16 +161,18 @@ public: * C++ * * @dontinclude ExampleXdmfUnstructuredGrid.cpp - * @skipline New - * @skipline newGeometry - * @until setGeometry + * @skipline //#initialization + * @until //#initialization + * @skipline //#setGeometry + * @until //#setGeometry * * Python * * @dontinclude XdmfExampleUnstructuredGrid.py - * @skipline New - * @skipline newGeometry - * @until setGeometry + * @skipline #//initialization + * @until #//initialization + * @skipline #//setGeometry + * @until #//setGeometry * * @param geometry an XdmfGeometry to associate with this grid. */ @@ -166,16 +186,18 @@ public: * C++ * * @dontinclude ExampleXdmfUnstructuredGrid.cpp - * @skipline New - * @skipline newTopology - * @until setTopology + * @skipline //#initialization + * @until //#initialization + * @skipline //#setTopology + * @until //#setTopology * * Python * * @dontinclude XdmfExampleUnstructuredGrid.py - * @skipline New - * @skipline newTopology - * @until setTopology + * @skipline #//initialization + * @until #//initialization + * @skipline #//setTopology + * @until #//setTopology * * @param topology an XdmfTopology to associate with this grid. */ diff --git a/core/XdmfArray.cpp b/core/XdmfArray.cpp index 5d0ff764..67106df5 100644 --- a/core/XdmfArray.cpp +++ b/core/XdmfArray.cpp @@ -35,29 +35,6 @@ #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::vector >)> - XdmfArray::arrayFunctions = - boost::assign::map_list_of ("SUM", (shared_ptr (*)(std::vector >))XdmfArray::sum) - ("AVE", (shared_ptr (*)(std::vector >))XdmfArray::ave); -std::map (*)(shared_ptr, shared_ptr)> - XdmfArray::operations = boost::assign::map_list_of ('|', XdmfArray::chunk) ('#', XdmfArray::interlace); - - XDMF_CHILDREN_IMPLEMENTATION(XdmfArray, XdmfHeavyDataController, @@ -595,54 +572,6 @@ XdmfArray::~XdmfArray() const std::string XdmfArray::ItemTag = "DataItem"; -int -XdmfArray::addFunction(std::string name, - shared_ptr(*functionref)(std::vector >)) -{ - // Check to ensure that the name has valid characters - for (unsigned int i = 0; i < name.size(); ++i) { - // If the character is not found in the list of valid characters - if (mValidVariableChars.find(name[i]) == std::string::npos) { - // Then throw an error - try { - XdmfError::message(XdmfError::FATAL, - "Error: Function Name Contains Invalid Character(s)"); - } - catch (XdmfError e) { - throw e; - } - } - } - size_t origsize = arrayFunctions.size(); - arrayFunctions[name] = functionref; - // If no new functions were added - if (origsize == arrayFunctions.size()) { - // Toss a warning, it's nice to let people know that they're doing this - try { - XdmfError::message(XdmfError::WARNING, - "Warning: Function Overwritten"); - } - catch (XdmfError e) { - throw e; - } - } - return arrayFunctions.size(); -} - -shared_ptr -XdmfArray::ave(std::vector > values) -{ - double total = sum(values)->getValue(0);; - int totalSize = 0; - for (unsigned int i = 0; i < values.size(); ++i) - { - totalSize += values[i]->getSize(); - } - shared_ptr returnArray = XdmfArray::New(); - returnArray->insert(0, total/totalSize); - return returnArray; -} - void XdmfArray::clear() { @@ -651,17 +580,6 @@ XdmfArray::clear() mDimensions.clear(); } -shared_ptr -XdmfArray::chunk(shared_ptr val1, shared_ptr val2) -{ - // Join chunk (add the new array to the end of the first one) - // Joins into new array and returns it - shared_ptr returnArray = XdmfArray::New(); - returnArray->insert(0, val1, 0, val1->getSize(), 1, 1); - returnArray->insert(val1->getSize(), val2, 0, val2->getSize(), 1, 1); - return returnArray; -} - void XdmfArray::erase(const unsigned int index) { @@ -671,350 +589,6 @@ 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::evaluateExpression(std::string expression, - std::map > variables) -{ - std::stack > valueStack; - std::stack operationStack; - - // String is parsed left to right - // Elements of the same priority are evaluated right to left - for (unsigned int i = 0; i < expression.size(); ++i) { - // Found to be a digit - if (mValidDigitChars.find(expression[i]) != std::string::npos) { - // Progress until a non-digit is found - int valueStart = i; - if (i + 1 < expression.size()) { - while (mValidDigitChars.find(expression[i+1]) != std::string::npos) { - i++; - } - } - // Push back to the value stack - shared_ptr valueArray = XdmfArray::New(); - // Use this to convert to double - valueArray->insert(0, atof(expression.substr(valueStart, i + 1 - valueStart).c_str())); - 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 - if (i+1 < expression.size()){ - 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()) { - try { - XdmfError::message(XdmfError::FATAL, - "Error: Invalid Variable in evaluateExpression " - + expression.substr(valueStart, i + 1 - valueStart)); - } - catch (XdmfError e) { - throw e; - } - } - else { - std::string currentFunction = expression.substr(valueStart, i + 1 - valueStart); - // Check if next character is an open parenthesis - if (i+1 >= expression.size()) { - if (expression[i+1] != '(') { - try { - XdmfError::message(XdmfError::FATAL, - "Error: No values supplied to function " - + expression.substr(valueStart, i + 1 - valueStart)); - } - catch (XdmfError e) { - throw e; - } - } - } - // If it is grab the string between paranthesis - - if (i + 2 >= expression.size()) { - XdmfError::message(XdmfError::FATAL, - "Error: Missing closing parethesis to function " - + expression.substr(valueStart, i + 1 - valueStart)); - } - 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 > 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 - // Ppop 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() != '(') { - // Must be at least two values for this loop to work properly - if (valueStack.size() < 2) { - try { - XdmfError::message(XdmfError::FATAL, - "Error: Not Enough Values in evaluateExpression"); - } - catch (XdmfError e) { - throw e; - } - } - else { - shared_ptr val2 = valueStack.top(); - valueStack.pop(); - shared_ptr 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) { - // Must be at least two values for this loop to work properly - if (valueStack.size() < 2) { - try { - XdmfError::message(XdmfError::FATAL, - "Error: Not Enough Values in evaluateExpression"); - } - catch (XdmfError e) { - throw e; - } - } - else { - shared_ptr val2 = valueStack.top(); - valueStack.pop(); - shared_ptr 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 - try { - XdmfError::message(XdmfError::FATAL, - "Error: Not Enough Values in evaluateExpression"); - } - catch (XdmfError e) { - throw e; - } - } - else { - if(operationStack.top() == '(') { - try { - XdmfError::message(XdmfError::WARNING, - "Warning: Unpaired Parenthesis"); - } - catch (XdmfError e) { - throw e; - } - } - else { - shared_ptr val2 = valueStack.top(); - valueStack.pop(); - shared_ptr val1 = valueStack.top(); - valueStack.pop(); - if (operationStack.size() == 0) { - try { - XdmfError::message(XdmfError::FATAL, - "Error: Not Enough Operators in evaluateExpression"); - } - catch (XdmfError e) { - throw e; - } - } - else { - valueStack.push(evaluateOperation(val1, val2, operationStack.top())); - operationStack.pop(); - } - } - } - } - - // Throw error if there's extra operations - if (operationStack.size() > 0) { - try { - XdmfError::message(XdmfError::WARNING, - "Warning: Left Over Operators in evaluateExpression"); - } - catch (XdmfError e) { - throw e; - } - } - - if (valueStack.size() > 1) { - try { - XdmfError::message(XdmfError::WARNING, - "Warning: Left Over Values in evaluateExpression"); - } - catch (XdmfError e) { - throw e; - } - } - - return valueStack.top(); -} - -shared_ptr -XdmfArray::evaluateOperation(shared_ptr val1, - shared_ptr val2, - char operation) -{ - if (operations.find(operation) != operations.end()) { - return (*(shared_ptr(*)(shared_ptr, - shared_ptr))operations[operation])(val1, - val2); - } - else { - return shared_ptr(); - } -} - -int -XdmfArray::addOperation(char newoperator, - shared_ptr(*operationref)(shared_ptr, - shared_ptr), - int priority) -{ - if (newoperator == '(' || newoperator == ')') { - try { - XdmfError::message(XdmfError::FATAL, - "Error: Parenthesis can not be redefined"); - } - catch (XdmfError e) { - throw e; - } - } - // Give warning if the operation already exists - size_t origsize = operations.size(); - // Place reference in the associated location - operations[newoperator] = operationref; - // It's nice to let people know they're doing this - // So they don't get surprised about changes in behavior - if (origsize == operations.size()) { - try { - XdmfError::message(XdmfError::WARNING, - "Warning: Function Overwritten"); - } - catch (XdmfError e) { - throw e; - } - // 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) { - try { - XdmfError::message(XdmfError::FATAL, - "Error: Operation Overlaps with Variables"); - } - catch (XdmfError e) { - throw e; - } - } - else { - // Build the operation - // Add operation to the supported character string - mSupportedOperations.push_back(newoperator); - unsigned int priorityArraySize = sizeof(mOperationPriority)/sizeof(int); - // First check to see if the priority array is large enough - if (mSupportedOperations.size()-1 > priorityArraySize) { - // If it isn't make it bigger, double size should be fine - int newArray [priorityArraySize*2]; - std::copy(mOperationPriority, mOperationPriority+(priorityArraySize-1), newArray); - *mOperationPriority = *newArray; - } - size_t priorityLocation = mSupportedOperations.find(newoperator); - mOperationPriority[priorityLocation] = priority; - } - } - return operations.size(); -} - -// This is how you use references to functions -shared_ptr -XdmfArray::evaluateFunction(std::vector > valueVector, - std::string functionName) -{ - if (arrayFunctions.find(functionName) != arrayFunctions.end()) { - return (*(shared_ptr(*)(std::vector >))arrayFunctions[functionName])(valueVector); - } - else { - return shared_ptr(); - } -} - shared_ptr XdmfArray::getArrayType() const { @@ -1112,18 +686,6 @@ XdmfArray::getName() const return mName; } -int -XdmfArray::getOperationPriority(char operation) -{ - size_t operationLocation = mSupportedOperations.find(operation); - if (operationLocation != std::string::npos) { - return mOperationPriority[operationLocation]; - } - else { - return -1; - } -} - unsigned int XdmfArray::getSize() const { @@ -1131,37 +693,6 @@ XdmfArray::getSize() const mArray); } -const std::string -XdmfArray::getSupportedOperations() -{ - return mSupportedOperations; -} - -const std::vector -XdmfArray::getSupportedFunctions() -{ - std::vector returnVector; - for (std::map(*)(std::vector >)>::iterator functionWalker - = arrayFunctions.begin(); - functionWalker != arrayFunctions.end(); - ++functionWalker) { - returnVector.push_back(functionWalker->first); - } - return returnVector; -} - -const std::string -XdmfArray::getValidDigitChars() -{ - return mValidDigitChars; -} - -const std::string -XdmfArray::getValidVariableChars() -{ - return mValidVariableChars; -} - void * XdmfArray::getValuesInternal() { @@ -1429,317 +960,6 @@ XdmfArray::insert(const std::vector startIndex, } } -shared_ptr -XdmfArray::interlace(shared_ptr val1, shared_ptr val2) -{ - // Join interlace (evenly space the second array within the first one) - // Builds a new array - shared_ptr 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 arrayType1 = val1->getArrayType(); - shared_ptr 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 - std::string sampleValue = ""; - returnArray->resize(val1->getSize()+val2->getSize(), sampleValue); - } - else { - double sampleValue = 0.0; - returnArray->resize(val1->getSize()+val2->getSize(), sampleValue); - } - } - else if (arrayType1 == XdmfArrayType::UInt8()) { - // If int are used reclass as int of the larger size - if (arrayType2 == XdmfArrayType::Int8() || arrayType2 == XdmfArrayType::Int16()) { - short sampleValue = 0; - returnArray->resize(val1->getSize()+val2->getSize(), sampleValue); - } - else if (arrayType2 == XdmfArrayType::Int32()) { - int sampleValue = 0; - returnArray->resize(val1->getSize()+val2->getSize(), sampleValue); - } - else if (arrayType2 == XdmfArrayType::Int64()) { - long sampleValue = 0; - returnArray->resize(val1->getSize()+val2->getSize(), sampleValue); - } - // If floats are used, reclass as floats of the appropriate size - 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 are used, adjust size as required - else if (arrayType2 == XdmfArrayType::UInt8()) { - unsigned char sampleValue = 0; - returnArray->resize(val1->getSize()+val2->getSize(), sampleValue); - } - else if (arrayType2 == XdmfArrayType::UInt16()) { - unsigned short sampleValue = 0; - returnArray->resize(val1->getSize()+val2->getSize(), sampleValue); - } - else if (arrayType2 == XdmfArrayType::UInt32()) { - unsigned int sampleValue = 0; - returnArray->resize(val1->getSize()+val2->getSize(), sampleValue); - } - else if (arrayType2 == XdmfArrayType::String()) { - // String is the only compatible type here - std::string sampleValue = ""; - returnArray->resize(val1->getSize()+val2->getSize(), sampleValue); - } - } - else if (arrayType1 == XdmfArrayType::UInt16()) { - // If int are used reclass as int of the larger size - if (arrayType2 == XdmfArrayType::Int8() || arrayType2 == XdmfArrayType::Int16() || arrayType2 == XdmfArrayType::Int32()) { - int sampleValue = 0; - returnArray->resize(val1->getSize()+val2->getSize(), sampleValue); - } - else if (arrayType2 == XdmfArrayType::Int64()) { - long sampleValue = 0; - returnArray->resize(val1->getSize()+val2->getSize(), sampleValue); - } - // If floats are used, reclass as floats of the appropriate size - 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 are used, adjust size as required - else if (arrayType2 == XdmfArrayType::UInt8() || arrayType2 == XdmfArrayType::UInt16()) { - unsigned short sampleValue = 0; - returnArray->resize(val1->getSize()+val2->getSize(), sampleValue); - } - else if (arrayType2 == XdmfArrayType::UInt32()) { - unsigned int sampleValue = 0; - returnArray->resize(val1->getSize()+val2->getSize(), sampleValue); - } - else if (arrayType2 == XdmfArrayType::String()) { - // String is the only compatible type here - std::string sampleValue = ""; - returnArray->resize(val1->getSize()+val2->getSize(), sampleValue); - } - } - else if (arrayType1 == XdmfArrayType::UInt32()) { - // If int are used reclass as int of the larger size - if (arrayType2 == XdmfArrayType::Int8() - || arrayType2 == XdmfArrayType::Int16() - || arrayType2 == XdmfArrayType::Int32() - || arrayType2 == XdmfArrayType::Int64()) { - long sampleValue = 0; - returnArray->resize(val1->getSize()+val2->getSize(), sampleValue); - } - // If floats are used, reclass as floats of the appropriate size - 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 are used, adjust size as required - else if (arrayType2 == XdmfArrayType::UInt8() - || arrayType2 == XdmfArrayType::UInt16() - || arrayType2 == XdmfArrayType::UInt32()) { - unsigned int sampleValue = 0; - returnArray->resize(val1->getSize()+val2->getSize(), sampleValue); - } - else if (arrayType2 == XdmfArrayType::String()) { - // String is the only compatible type here - std::string sampleValue = ""; - returnArray->resize(val1->getSize()+val2->getSize(), sampleValue); - } - } - else if (arrayType1 == XdmfArrayType::String()) { - // String is the only compatible type here - std::string sampleValue = ""; - returnArray->resize(val1->getSize()+val2->getSize(), sampleValue); - } - // Determine ratio of array sizes - int arrayRatio1 = (int)floor(static_cast(val1->getSize())/val2->getSize()); - int arrayRatio2 = (int)floor(static_cast(val2->getSize())/val1->getSize()); - if (arrayRatio1 < 1) { - arrayRatio1 = 1; - } - if (arrayRatio2 < 1) { - arrayRatio2 = 1; - } - // Stride is equal to the ratios rounded up and added together - int stride = arrayRatio1+arrayRatio2; - int arrayExcess1 = 0; - int arrayExcess2 = 0; - for (int i = 0; i < stride; ++i) { - // Add the values of each array, using strides to interlace and starting index to offset - // first array gets the first value of the new array - if (igetSize()/arrayRatio1; - if (((amountWritten * arrayRatio1) + i) < (int)val1->getSize()) { - amountWritten++; - } - if (amountWritten > floor(val2->getSize()/arrayRatio2)) { - arrayExcess1 += amountWritten - (int)floor(val2->getSize()/arrayRatio2); - amountWritten = (int)floor(val2->getSize()/arrayRatio2); - } - returnArray->insert(i, val1, i, amountWritten, stride, arrayRatio1); - } - else { - // Second array takes the rest - int amountWritten = val2->getSize()/arrayRatio2; - if (((amountWritten * arrayRatio2) + i) < (int)val2->getSize()) { - amountWritten++; - } - if (amountWritten > floor(val1->getSize()/arrayRatio1)) { - arrayExcess2 += amountWritten - (int)floor(val1->getSize()/arrayRatio1); - amountWritten = (int)floor(val1->getSize()/arrayRatio1); - } - returnArray->insert(i, val2, i-arrayRatio1, amountWritten, stride, arrayRatio2); - } - } - if (arrayExcess1 > 0) { - returnArray->insert(val1->getSize()+val2->getSize()-arrayExcess1, val1, 0, arrayExcess1, 1, 1); - } - else if (arrayExcess2 > 0) { - returnArray->insert(val1->getSize()+val2->getSize()-arrayExcess2, val2, 0, arrayExcess2, 1, 1); - } - returnArray->resize(val1->getSize()+val2->getSize(), 0); - // After all inserts are done, add the excess values to the end of the array? - // Possibly do during the initial insert process? - return returnArray; -} - bool XdmfArray::isInitialized() const { @@ -1765,11 +985,11 @@ XdmfArray::populateItem(const std::map & itemPropertie const shared_ptr arrayType = XdmfArrayType::New(itemProperties); - std::map::const_iterator content = - itemProperties.find("Content0"); + std::map::const_iterator content = + itemProperties.find("Content"); if(content == itemProperties.end()) { try { - XdmfError::message(XdmfError::FATAL, + XdmfError::message(XdmfError::FATAL, "'Content' not found in itemProperties in " "XdmfArray::populateItem"); } @@ -1778,27 +998,28 @@ XdmfArray::populateItem(const std::map & itemPropertie } } - // Tthis was originally a constant, - // but the compiler doesn't like creating vectors of constant strings. - std::vector contentVals; - contentVals.push_back(content->second); + int contentIndex; - unsigned int contentIndex=1; + const std::string & contentVal = content->second; - bool endOfContent = false; + std::vector contentVals; - while(!endOfContent) - { - std::stringstream contentSearch; - contentSearch << "Content" << contentIndex; - content = itemProperties.find(contentSearch.str()); - if(content != itemProperties.end()) { - contentVals.push_back(content->second); + // Split the content based on "|" characters + size_t barSplit = 0; + std::string splitString(contentVal); + std::string subcontent; + while (barSplit != std::string::npos) { + barSplit = 0; + barSplit = splitString.find_first_of("|", barSplit); + if (barSplit == std::string::npos) { + subcontent = splitString; } else { - endOfContent = true; + subcontent = splitString.substr(0, barSplit); + splitString = splitString.substr(barSplit+1); + barSplit++; } - contentIndex++; + contentVals.push_back(subcontent); } std::map::const_iterator dimensions = @@ -2005,20 +1226,6 @@ XdmfArray::setName(const std::string & name) mName = name; } -shared_ptr -XdmfArray::sum(std::vector > values) -{ - double total = 0.0; - for (unsigned int i = 0; i < values.size(); ++i) { - for (unsigned int j = 0; j < values[i]->getSize(); ++j) { - total += values[i]->getValue(j); - } - } - shared_ptr returnArray = XdmfArray::New(); - returnArray->insert(0, total); - return returnArray; -} - void XdmfArray::swap(const shared_ptr array) { diff --git a/core/XdmfArray.hpp b/core/XdmfArray.hpp index cb9774ad..bdf6bd55 100644 --- a/core/XdmfArray.hpp +++ b/core/XdmfArray.hpp @@ -107,12 +107,14 @@ public: * C++ * * @dontinclude ExampleXdmfArray.cpp - * @skipline New + * @skipline //#initialization + * @until //#initialization * * Python * * @dontinclude XdmfExampleArray.py - * @skipline New + * @skipline #//initialization + * @until #//initialization * * @return constructed XdmfArray. */ @@ -124,98 +126,6 @@ public: XDMF_CHILDREN(XdmfArray, XdmfHeavyDataController, HeavyDataController, Name); static const std::string ItemTag; - /** - * Adds an operation to the list of viable operators. - * - * Example of Use: - * - * C++ - * - * @dontinclude ExampleXdmfArray.cpp - * @skipline prepend - * @skipline main - * @skipline addOperation - * @skipline return - * @until } - * @skipline prepend - * @until } - * - * Python - * - * @dontinclude XdmfExampleArray.py - * @skipline prepend - * @until val2.getSize - * @skipline return - * @skipline __main__ - * @skipline addOperation - * - * @param newoperator the character to be associated with the provided binary operation - * @param functionref a pointer to the function to be associated with the provided operator - * @param priority used to determine order of operations the higher the value the earlier it is evaluated - */ - static int addOperation(char newoperator, shared_ptr(*functionref)(shared_ptr, shared_ptr), int priority); - - /* - * adds a specified function to the list of functions used while evaluating strings - * - * C++ - * - * @dontinclude ExampleXdmfArray.cpp - * @skipline maximum - * @skipline main - * @skipline addFunction - * @skipline return - * @until } - * @skipline maximum - * @until else - * @skipline { - * @until returnArray; - * @skipline } - * @until } - * - * Python - * - * @dontinclude XdmfExampleArray.py - * @skipline maximum - * @until else - * @skipline maxVal - * @until pushBackAsFloat - * @skipline return - * @skipline __main__ - * @skipline addFunction - * - * @param name A string to be associated with the provided function during string evaluation - * @param functionref A pointer to the function to be associated with the given string - * @return The total number of functions currently associated - */ - static int addFunction(std::string name, shared_ptr(*functionref)(std::vector >)); - - /** - * Averages the values contained in all the provided arrays. - * - * C++ - * - * @dontinclude ExampleXdmfArray.cpp - * @skipline valueArray1 - * @until valueVector - * @skipline valueArray1 - * @until valueArray2 - * @skipline ave - * - * Python - * - * @dontinclude XdmfExampleArray.py - * @skipline valueArray1 - * @until valueVector - * @skipline valueArray1 - * @until valueArray2 - * @skipline ave - * - * @param values a vector containing the arrays to be used - * @return an XdmfArray containing one value which is the average of all values contained within the provided arrays - */ - static shared_ptr ave(std::vector > values); - /** * Remove all values from this array. * @@ -224,42 +134,21 @@ public: * C++ * * @dontinclude ExampleXdmfArray.cpp - * @skipline Assuming - * @skipline clear + * @skipline //#initialization + * @until //#initialization + * @skipline //#clear + * @until //#clear * * Python * * @dontinclude XdmfExampleArray.py - * @skipline Assuming - * @skipline clear + * @skipline #//initialization + * @until #//initialization + * @skipline #//clear + * @until #//clear */ void clear(); - /** - * Joins the two provided arrays together end to end. - * - * Example of Use: - * - * C++ - * - * @dontinclude ExampleXdmfArray.cpp - * @skipline valueArray1 - * @until (6) - * @skipline chunk - * - * Python - * - * @dontinclude XdmfExampleArray.py - * @skipline valueArray1 - * @until (6) - * @skipline chunk - * - * @param val1 the first array being evaluated - * @param val2 the second array being evaluated - * @return the arrays joined end to end - */ - static shared_ptr chunk(shared_ptr val1, shared_ptr val2); - /** * Remove a value from this array. * @@ -268,143 +157,25 @@ public: * C++ * * @dontinclude ExampleXdmfArray.cpp - * @skipline Assuming - * @skip exampleInternalPointerConst - * @skipline // - * @until ] + * @skipline //#initialization + * @until //#initialization + * @skipline //#erase + * @until //#erase * * Python * * @dontinclude XdmfExampleArray.py - * @skip exampleArray.insertAsFloat64(newIndex, newValue) - * @skipline contains - * @until ] + * @skipline #//initialization + * @until #//initialization + * @skipline #//arraydefaultvalues + * @until #//arraydefaultvalues + * @skipline #//erase + * @until //#erase + * + * @param index the index of the value to be removed */ void erase(const unsigned int index); - /** - * Evaluates an expression based on the list of variables provided. - * A list of valid operations is retrievable from the getSupportedOperations static method. - * None of the XdmfArrays provided are modified during the evaluation process. - * - * Example of Use: - * - * C++ - * - * @dontinclude ExampleXdmfArray.cpp - * @skipline maximum - * @skipline main - * @skipline addOperation - * @skipline addFunction - * @skipline valueMap - * @until } - * @skipline maximum - * @until else - * @skipline { - * @until returnArray; - * @skipline } - * @until } - * @skipline prepend - * @until } - * - * Python - * - * @dontinclude XdmfExampleArray.py - * @skipline maximum - * @until else - * @skipline maxVal - * @until pushBackAsFloat - * @skipline return - * @skipline prepend - * @until val2.getSize - * @skipline return - * @skipline __main__ - * @skipline addOperation - * @skipline addFunction - * @skipline valueMap - * @until evaluateExpression - * - * @param expression a string containing the expresion to be evaluated - * @param variables a map of strings to their XdmfArray equivalent - * @return a shared pointer to the XdmfArray resulting from the expression - */ - static shared_ptr evaluateExpression(std::string expression, std::map > variables); - - /** - * Evaluates the operation specified using the two shared pointers to XdmfArrays provided. - * A list of valid operations is retrievable from the getSupportedOperations static method. - * None of the XdmfArrays provided are modified during the evaluation process. - * - * Example of Use: - * - * C++ - * - * @dontinclude ExampleXdmfArray.cpp - * @skipline prepend - * @skipline main - * @skipline answerArray - * @skipline addOperation - * @until evaluateOperation - * @skipline return - * @until } - * @skipline prepend - * @until } - * - * Python - * - * @dontinclude XdmfExampleArray.py - * @skipline prepend - * @until val2.getSize - * @skipline return - * @skipline __main__ - * @skipline addOperation - * @until evaluateOperation - * - * @param val1 the first array being evaluated - * @param val2 the second array being evaluated - * @param operation a character specifying the operation performed - * @return a shared pointer to the Xdmf Array that results from the calculation - */ - static shared_ptr evaluateOperation(shared_ptr val1, shared_ptr val2, char operation); - - /** - * Evaluates the function specified using the vector of XdmfArrays provided. - * None of the XdmfArrays provided are modified during the evaluation process. - * - * C++ - * - * @dontinclude ExampleXdmfArray.cpp - * @skipline maximum - * @skipline main - * @skipline addFunction - * @until evaluateFunction - * @skipline return - * @until } - * @skipline maximum - * @until else - * @skipline { - * @until returnArray; - * @skipline } - * @until } - * - * Python - * - * @dontinclude XdmfExampleArray.py - * @skipline maximum - * @until else - * @skipline maxVal - * @until pushBackAsFloat - * @skipline return - * @skipline __main__ - * @skipline addFunction - * @until evaluateFunction - * - * @param valueVector a vector containing the arrays to be used - * @param functionName the string associated with the function being called - * @return the result of the function being called, a scalar will be returned as an XdmfArray with one value - */ - static shared_ptr evaluateFunction(std::vector > valueVector, std::string functionName); - /** * Get the data type of this array. * @@ -413,14 +184,18 @@ public: * C++ * * @dontinclude ExampleXdmfArray.cpp - * @skipline Assuming - * @skipline getArrayType + * @skipline //#initialization + * @until //#initialization + * @skipline //#getArrayType + * @until //#getArrayType * * Python * * @dontinclude XdmfExampleArray.py - * @skipline Assuming - * @skipline getArrayType + * @skipline #//initialization + * @until #//initialization + * @skipline #//getArrayType + * @until #//getArrayType * * @return a XdmfArrayType containing the data type for the array. */ @@ -435,14 +210,18 @@ public: * C++ * * @dontinclude ExampleXdmfArray.cpp - * @skipline Assuming - * @skipline getCapacity + * @skipline //#initialization + * @until //#initialization + * @skipline //#getCapacity + * @until //#getCapacity * * Python * * @dontinclude XdmfExampleArray.py - * @skipline Assuming - * @skipline getCapacity + * @skipline #//initialization + * @until #//initialization + * @skipline #//getCapacity + * @until #//getCapacity * * @return the capacity of this array. */ @@ -458,14 +237,18 @@ public: * C++ * * @dontinclude ExampleXdmfArray.cpp - * @skipline Assuming - * @skipline exampleDimensions + * @skipline //#initialization + * @until //#initialization + * @skipline //#getDimensions + * @until //#getDimensions * * Python * * @dontinclude XdmfExampleArray.py - * @skipline Assuming - * @skipline exampleDimensions + * @skipline #//initialization + * @until #//initialization + * @skipline #//getDimensions + * @until #//getDimensions * * @return the dimensions of the array. */ @@ -479,14 +262,18 @@ public: * C++ * * @dontinclude ExampleXdmfArray.cpp - * @skipline Assuming - * @skipline exampleDimensionString + * @skipline //#initialization + * @until //#initialization + * @skipline //#getDimensionsString + * @until //#getDimensionsString * * Python * * @dontinclude XdmfExampleArray.py - * @skipline Assuming - * @skipline exampleDimensionString + * @skipline #//initialization + * @until #//initialization + * @skipline #//getDimensionsString + * @until #//getDimensionsString * * @return the dimensions of the array as a string. */ @@ -504,40 +291,27 @@ public: * C++ * * @dontinclude ExampleXdmfArray.cpp - * @skipline Assuming - * @skipline exampleName + * @skipline //#initialization + * @until //#initialization + * @skipline //#setName + * @until //#setName + * @skipline //#getName + * @until //#getName * * Python * * @dontinclude XdmfExampleArray.py - * @skipline Assuming - * @skipline exampleName + * @skipline #//initialization + * @until #//initialization + * @skipline #//setName + * @until #//setName + * @skipline #//getName + * @until #//getName * * @return a string containing the name of the array. */ std::string getName() const; - /** - * Gets the priority of operation whose associated character is provided. Returns -1 if the operation is not supported. - * The higher the value the earlier that operation is evaluated during evaluateExpression. - * - * Example of Use: - * - * C++ - * - * @dontinclude ExampleXdmfArray.cpp - * @skipline getOperationPriority - * - * Python - * - * @dontinclude XdmfExampleArray.py - * @skipline getOperationPriority - * - * @param operation the character associated with the operation to be checked - * @return the priority of the operation - */ - static int getOperationPriority(char operation); - /** * Get the number of values stored in this array. * @@ -546,99 +320,23 @@ public: * C++ * * @dontinclude ExampleXdmfArray.cpp - * @skipline Assuming - * @skipline exampleSize + * @skipline //#initialization + * @until //#initialization + * @skipline //#getSize + * @until //#getSize * * Python * * @dontinclude XdmfExampleArray.py - * @skipline Assuming - * @skipline exampleSize + * @skipline #//initialization + * @until #//initialization + * @skipline #//getSize + * @until #//getSize * * @return the number of values stored in this array. */ unsigned int getSize() const; - /** - * Gets a string that contains all the characters of the supported operations. - * Parenthesis are included for grouping purposes in expressions. - * - * Example of Use: - * - * C++ - * - * @dontinclude ExampleXdmfArray.cpp - * @skipline getSupportedOperations - * - * Python - * - * @dontinclude XdmfExampleArray.py - * @skipline getSupportedOperations - * - * @return a string containing the characters for all supported operations - */ - static const std::string getSupportedOperations(); - - /** - * Gets a string that contains all the characters of the supported operations. - * Parenthesis are included for grouping purposes in expressions. - * - * Example of Use: - * - * C++ - * - * @dontinclude ExampleXdmfArray.cpp - * @skipline getSupportedFunctions - * - * Python - * - * @dontinclude XdmfExampleArray.py - * @skipline getSupportedFunctions - * - * @return a vector containing the strings associated with all valid functions - */ - static const std::vector getSupportedFunctions(); - - /** - * Gets a string that contains all strings that are viable for use when mapping - * to scalars (which are stored in XdmfArrays of size 1) for the evaluateExpression function. - * - * Example of Use: - * - * C++ - * - * @dontinclude ExampleXdmfArray.cpp - * @skipline getValidDigitChars - * - * Python - * - * @dontinclude XdmfExampleArray.py - * @skipline getValidDigitChars - * - * @return a string containing all valid variable characters - */ - static const std::string getValidDigitChars(); - - /** - * Gets a string that contains all strings that are viable for use when mapping - * to shared pointers of XdmfArrays for the evaluateExpression function. - * - * Example of Use: - * - * C++ - * - * @dontinclude ExampleXdmfArray.cpp - * @skipline getValidVariableChars - * - * Python - * - * @dontinclude XdmfExampleArray.py - * @skipline getValidVariableChars - * - * @return a string containing all valid variable characters - */ - static const std::string getValidVariableChars(); - /** * Get a copy of a single value stored in this array. * @@ -647,18 +345,24 @@ public: * C++ * * @dontinclude ExampleXdmfArray.cpp - * @skipline Assuming - * @skip XdmfHeavyDataController - * @skipline if - * @until index + * @skipline //#initialization + * @until //#initialization + * @skipline //#datapointersetup + * @until //#datapointersetup + * @skipline //#initsharedvector + * @until //#initsharedvector + * @skipline //#getValueindex + * @until //#getValueindex * * Python * * @dontinclude XdmfExampleArray.py - * @skipline Assuming - * @skip [0, - * @skipline 7] - * @until Variations + * @skipline #//initialization + * @until #//initialization + * @skipline #//arraydefaultvalues + * @until #//arraydefaultvalues + * @skipline #//getValueindex + * @until #//getValueindex * * @return the requested value. */ @@ -673,18 +377,20 @@ public: * C++ * * @dontinclude ExampleXdmfArray.cpp - * @skipline New - * @skipline storeArray - * @skipline exampleArray - * @until {0,2,4,6,8,5,3,7,4,9} + * @skipline //#initialization + * @until //#initialization + * @skipline //#getValues + * @until //#getValues * * Python: This function is not supported in Python, it is replaced by the getNumpyArray function * * @dontinclude XdmfExampleArray.py - * @skipline New - * @skipline initArray - * @skipline exampleArray - * @skipline getNumpyArray + * @skipline #//initialization + * @until #//initialization + * @skipline #//arraydefaultvalues + * @until #//arraydefaultvalues + * @skipline #//getNumpyArray + * @until #//getNumpyArray * * @param startIndex the index in this array to begin copying from. * @param valuesPointer a pointer to an array to copy into. @@ -709,10 +415,10 @@ public: * C++ * * @dontinclude ExampleXdmfArray.cpp - * @skipline Assuming - * @skip getValuesString - * @skipline // - * @until exampleInternalVector + * @skipline //#initialization + * @until //#initialization + * @skipline //#getValuesInternalvector + * @until //#getValuesInternalvector * * Python: * Python does not support this version of the getValuesInternal function, it defaults to the version that returns a void pointer @@ -731,15 +437,18 @@ public: * C++ * * @dontinclude ExampleXdmfArray.cpp - * @skipline Assuming - * @skipline exampleInternalPointer + * @skipline //#initialization + * @until //#initialization + * @skipline //#getValuesInternalvoid + * @until //#getValuesInternalvoid * * Python * * @dontinclude XdmfExampleArray.py - * @skipline Assuming - * @skipline getValuesInternal - * @until used + * @skipline //#initialization + * @until //#initialization + * @skipline #//getValuesInternal + * @until #//getValuesInternal * * @return a void pointer to the first value stored in this array. */ @@ -752,8 +461,10 @@ public: * Example of use: * * @dontinclude ExampleXdmfArray.cpp - * @skipline Assuming - * @skipline exampleInternalPointerConst + * @skipline //#initialization + * @until //#initialization + * @skipline //#getValuesInternalvoidconst + * @until //#getValuesInternalvoidconst * * Python: * Python does not support this version of the getValuesInternal function, it defaults to the version that returns a void pointer @@ -770,15 +481,18 @@ public: * C++ * * @dontinclude ExampleXdmfArray.cpp - * @skipline Assuming - * @skipline getValuesString + * @skipline //#initialization + * @until //#initialization + * @skipline //#getValuesString + * @until //#getValuesString * * Python * * @dontinclude XdmfExampleArray.py - * @skipline Assuming - * @skipline exampleValueString - * @until contained + * @skipline #//initialization + * @until #//initialization + * @skipline #//getValuesparse + * @until #//getValuesparse * * @return a string containing the contents of the array. */ @@ -792,9 +506,12 @@ public: * C++ * * @dontinclude ExampleXdmfArray.cpp - * @skipline Assuming - * @skipline newSize - * @skipline exampleVector + * @skipline //#initialization + * @until //#initialization + * @skipline //#sizedeclaration + * @until //#sizedeclaration + * @skipline //#initializesingletemplate + * @until //#initializesingletemplate * * Python: Does not support this version of initialize * @@ -814,9 +531,12 @@ public: * C++ * * @dontinclude ExampleXdmfArray.cpp - * @skipline Assuming - * @skipline newSizeVector - * @until exampleVector + * @skipline //#initialization + * @until //#initialization + * @skipline //#sizevectordeclaration + * @until //#sizevectordeclaration + * @skipline //#initializevectortemplate + * @until //#initializevectortemplate * * Python: Does not support this version of initialize * @@ -837,16 +557,20 @@ public: * C++ * * @dontinclude ExampleXdmfArray.cpp - * @skipline Assuming - * @skipline newSize - * @skipline XdmfArrayType + * @skipline //#initialization + * @until //#initialization + * @skipline //#sizedeclaration + * @until //#sizedeclaration + * @skipline //#initializesingletype + * @until //#initializesingletype * * Python * * @dontinclude XdmfExampleArray.py - * @skipline Assuming - * @skipline newSize - * @skipline XdmfArrayType + * @skipline #//initialization + * @until #//initialization + * @skipline #//initializesingle + * @until #//initializesingle * * @param arrayType the type of array to initialize. * @param size the number of values in the initialized array. @@ -862,17 +586,20 @@ public: * C++ * * @dontinclude ExampleXdmfArray.cpp - * @skipline Assuming - * @skipline newSizeVector - * @until 5 - * @skipline XdmfArrayType + * @skipline //#initialization + * @until //#initialization + * @skipline //#sizevectordeclaration + * @until //#sizevectordeclaration + * @skipline //#initializevectortype + * @until //#initializevectortype * * Python * * @dontinclude XdmfExampleArray.py - * @skipline Assuming - * @skipline UInt32Vector - * @until initialize + * @skipline #//initialization + * @until #//initialization + * @skipline #//initializevector + * @until #//initializevector * * @param arrayType the type of array to initialize. * @param dimensions the number dimensions of the initialized array. @@ -890,17 +617,20 @@ public: * C++ * * @dontinclude ExampleXdmfArray.cpp - * @skipline New - * @skipline newIndex - * @until newValue - * @skipline insert + * @skipline //#initialization + * @until //#initialization + * @skipline //#pointinsertvalues + * @until //#pointinsertvalues + * @skipline //#pointinsert + * @until //#pointinsert * * Python * * @dontinclude XdmfExampleArray.py - * @skipline New - * @skipline newIndex - * @until insertAsInt32 + * @skipline #//initialization + * @until #//initialization + * @skipline #//pointinsert + * @until #//pointinsert * * @param index the index in this array to insert. * @param value the value to insert @@ -917,18 +647,22 @@ public: * C++ * * @dontinclude ExampleXdmfArray.cpp - * @skipline New - * @skipline initArray - * @until insert - * @skipline tempArray - * @until {0,2,4,6,8,5,3,7,4,9} + * @skipline //#initialization + * @until //#initialization + * @skipline //#datapointersetup + * @until //#datapointersetup + * @skipline //#pointerinsert + * @until //#pointerinsert + * @skipline //#arrayinsert + * @until //#arrayinsert * * Python * * @dontinclude XdmfExampleArray.py - * @skipline New - * @skipline initArray - * @until {0,2,4,6,8,5,3,7,4,9} + * @skipline #//initialization + * @until #//initialization + * @skipline #//insertarray + * @until #//insertarray * * @param startIndex the index in this array to begin insertion. * @param values a shared pointer to an XdmfArray to copy into this array. @@ -954,14 +688,14 @@ public: * C++ * * @dontinclude ExampleXdmfArray.cpp - * @skipline writtenArray - * @until writeStrides) + * @skipline //#insertmultidim + * @until //#insertmultidim * * Python * * @dontinclude XdmfExampleArray.py - * @skipline writtenArray - * @until writeStrides) + * @skipline #//insertmultidim + * @until #//insertmultidim * * @param startIndex the index in this array to begin insertion for each dimension * @param values a shared pointer to an XdmfArray to copy into this array. @@ -987,18 +721,20 @@ public: * C++ * * @dontinclude ExampleXdmfArray.cpp - * @skipline New - * @skipline initArray - * @skipline insert - * @until {0,2,4,6,8,5,3,7,4,9} + * @skipline //#initialization + * @until //#initialization + * @skipline //#datapointersetup + * @until //#datapointersetup + * @skipline //#pointerinsert + * @until //#pointerinsert * * Python * * @dontinclude XdmfExampleArray.py - * @skipline New - * @skipline initArray - * @skipline insertAsInt32 - * @until Sublists + * @skipline #//initialization + * @until #//initialization + * @skipline #//insertlist + * @until #//insertlist * * @param startIndex the index in this array to begin insertion. * @param valuesPointer a pointer to the values to copy into this array. @@ -1015,30 +751,6 @@ public: const unsigned int arrayStride = 1, const unsigned int valuesStride = 1); - /** - * Joins the two provided arrays while interspercing their values evenly. - * Example of Use: - * - * C++ - * - * @dontinclude ExampleXdmfArray.cpp - * @skipline valueArray1 - * @until (6) - * @skipline interlace - * - * Python - * - * @dontinclude XdmfExampleArray.py - * @skipline valueArray1 - * @until (6) - * @skipline interlace - * - * @param val1 the first array being evaluated - * @param val2 the second array being evaluated - * @return the interlaced arrays - */ - static shared_ptr interlace(shared_ptr val1, shared_ptr val2); - /** * Returns whether the array is initialized (contains values in * memory). @@ -1048,16 +760,18 @@ public: * C++ * * @dontinclude ExampleXdmfArray.cpp - * @skipline Assuming - * @skipline isInitialized - * @until } + * @skipline //#initialization + * @until //#initialization + * @skipline //#isInitialized + * @until //#isInitialized * * Python * * @dontinclude XdmfExampleArray.py - * @skipline Assuming - * @skipline isInitialized - * @until read + * @skipline #//initialization + * @until #//initialization + * @skipline #//isInitialized + * @until #//isInitialized */ bool isInitialized() const; @@ -1069,16 +783,22 @@ public: * C++ * * @dontinclude ExampleXdmfArray.cpp - * @skipline New - * @skipline newValue - * @skipline pushBack + * @skipline //#initialization + * @until //#initialization + * @skipline //#pointinsertvalues + * @until //#pointinsertvalues + * @skipline //#pushBack + * @until //#pushBack * * Python * * @dontinclude XdmfExampleArray.py - * @skipline New - * @skipline newValue - * @until pushBackAsFloat64 + * @skipline #//initialization + * @until #//initialization + * @skipline #//pushBack + * @until #//pushBack + * + * @param value The value to be inserted */ template void pushBack(const T & value); @@ -1091,14 +811,18 @@ public: * C++ * * @dontinclude ExampleXdmfArray.cpp - * @skipline Assuming - * @skipline exampleController + * @skipline //#initialization + * @until //#initialization + * @skipline //#getHeavyDataController + * @until //#getHeavyDataController * * Python * * @dontinclude XdmfExampleArray.py - * @skipline Assuming - * @skipline exampleController + * @skipline #//initialization + * @until #//initialization + * @skipline #//getHeavyDataController + * @until #//getHeavyDataController * * @return the heavy data controller attached to this array. */ @@ -1113,8 +837,10 @@ public: * C++ * * @dontinclude ExampleXdmfArray.cpp - * @skipline Assuming - * @skipline exampleControllerConst + * @skipline //#initialization + * @until //#initialization + * @skipline //#getHeavyDataControllerconst + * @until //#getHeavyDataControllerconst * * Python: Doesn't support a constant version of this function * @@ -1131,16 +857,22 @@ public: * C++ * * @dontinclude ExampleXdmfArray.cpp - * @skipline Assuming - * @skipline exampleController - * @until setHeaveyDataController + * @skipline //#initialization + * @until //#initialization + * @skipline //#getHeavyDataController + * @until //#getHeavyDataController + * @skipline //#setHeavyDataController + * @until //#setHeavyDataController * * Python * * @dontinclude XdmfExampleArray.py - * @skipline Assuming - * @skipline exampleController - * @until setHeaveyDataController + * @skipline #//initialization + * @until #//initialization + * @skipline #//getHeavyDataController + * @until #//getHeavyDataController + * @skipline #//setHeavyDataController + * @until #//setHeavyDataController * * @param newController the heavy data controller to attach to this array. */ @@ -1155,16 +887,18 @@ public: * C++ * * @dontinclude ExampleXdmfArray.cpp - * @skipline Assuming - * @skipline !exampleArray - * @until } + * @skipline //#initialization + * @until //#initialization + * @skipline //#read + * @until //#read * * Python * * @dontinclude XdmfExampleArray.py - * @skipline Assuming - * @skipline isInitialized - * @until read + * @skipline #//initialization + * @until #//initialization + * @skipline #//isInitialized + * @until #//isInitialized */ void read(); @@ -1176,14 +910,18 @@ public: * C++ * * @dontinclude ExampleXdmfArray.cpp - * @skipline Assuming - * @skipline release + * @skipline //#initialization + * @until //#initialization + * @skipline //#release + * @until //#release * * Python * * @dontinclude XdmfExampleArray.py - * @skipline Assuming - * @skipline release + * @skipline #//initialization + * @until #//initialization + * @skipline #//release + * @until #//release */ void release(); @@ -1195,16 +933,20 @@ public: * C++ * * @dontinclude ExampleXdmfArray.cpp - * @skipline New - * @skipline newSize - * @skipline reserve + * @skipline //#initialization + * @until //#initialization + * @skipline //#sizedeclaration + * @until //#sizedeclaration + * @skipline //#reserve + * @until //#reserve * * Python * * @dontinclude XdmfExampleArray.py - * @skipline New - * @skipline newSize - * @skipline reserve + * @skipline #//initialization + * @until #//initialization + * @skipline #//reserve + * @until #//reserve * * @param size the capacity to set this array to. */ @@ -1221,23 +963,22 @@ public: * C++ * * @dontinclude ExampleXdmfArray.cpp - * @skipline New - * @skipline newSize - * @skipline initArray - * @skipline insert - * @until // - * @skipline newSize - * @until 4} + * @skipline //#initialization + * @until //#initialization + * @skipline //#sizedeclaration + * @until //#sizedeclaration + * @skipline //#resizesingle + * @until //#resizesingle * * Python * * @dontinclude XdmfExampleArray.py - * @skipline New - * @skipline initArray - * @skipline insert - * @until # - * @skipline newSize - * @until resizeAsFloat64 + * @skipline #//initialization + * @until #//initialization + * @skipline #//arraydefaultvalues + * @until #//arraydefaultvalues + * @skipline #//resizesingle + * @until #//resizesingle * * @param numValues the number of values to resize this array to. * @param value the number to initialize newly created values to, if needed. @@ -1258,25 +999,22 @@ public: * C++ * * @dontinclude ExampleXdmfArray.cpp - * @skipline New - * @skipline newSizeVector - * @until push_back(5) - * @skipline initArray - * @skipline insert - * @until // - * @skip resize - * @skipline newSizeVector - * @until 4} + * @skipline //#initialization + * @until //#initialization + * @skipline //#sizevectordeclaration + * @until //#sizevectordeclaration + * @skipline //#resizevector + * @until //#resizevector * * Python * * @dontinclude XdmfExampleArray.py - * @skipline New - * @skipline initArray - * @skipline insertAsInt32 - * @until # - * @skipline newSizeArray - * @until resizeAsFloat64 + * @skipline #//initialization + * @until #//initialization + * @skipline #//arraydefaultvalues + * @until #//arraydefaultvalues + * @skipline #//resizevector + * @until #//resizevector * * @param dimensions the dimensions to resize the array to. * @param value the number to intialize newly created values to, if needed. @@ -1293,16 +1031,18 @@ public: * C++ * * @dontinclude ExampleXdmfArray.cpp - * @skipline New - * @skipline newName - * @until setName + * @skipline //#initialization + * @until //#initialization + * @skipline //#setName + * @until //#setName * * Python * * @dontinclude XdmfExampleArray.py - * @skipline New - * @skipline newName - * @until setName + * @skipline #//initialization + * @until #//initialization + * @skipline #//setName + * @until #//setName * * @param name of the array to set. */ @@ -1328,8 +1068,12 @@ public: * C++ * * @dontinclude ExampleXdmfArray.cpp - * @skipline initArray - * @skipline setValuesInternal + * @skipline //#initialization + * @until //#initialization + * @skipline //#datapointersetup + * @until //#datapointersetup + * @skipline //#setValuesInternalpointer + * @until //#setValuesInternalpointer * * Python: does not support setValuesInternal * @@ -1354,9 +1098,12 @@ public: * C++ * * @dontinclude ExampleXdmfArray.cpp - * @skipline New - * @skipline initVector - * @skipline setValuesInternal + * @skipline //#initialization + * @until //#initialization + * @skipline //#initinternalvector + * @until //#initinternalvector + * @skipline //#setValuesInternalvector + * @until //#setValuesInternalvector * * Python: does not support setValuesInternal * @@ -1378,11 +1125,14 @@ public: * C++ * * @dontinclude ExampleXdmfArray.cpp - * @skipline New - * @skipline initVector - * @until push_back(5) - * @skipline storeVector - * @until setValuesInternal + * @skipline //#initialization + * @until //#initialization + * @skipline //#initinternalvector + * @until //#initinternalvector + * @skipline //#initsharedvector + * @until //#initsharedvector + * @skipline //#setValuesInternalsharedvector + * @until //#setValuesInternalsharedvector * * Python: does not support setValuesInternal * @@ -1391,32 +1141,6 @@ public: template void setValuesInternal(const shared_ptr > array); - /** - * Adds together all the values contained in the provided arrays. - * - * C++ - * - * @dontinclude ExampleXdmfArray.cpp - * @skipline valueArray1 - * @until valueVector - * @skipline valueArray1 - * @until valueArray2 - * @skipline sum - * - * Python - * - * @dontinclude XdmfExampleArray.py - * @skipline valueArray1 - * @until valueVector - * @skipline valueArray1 - * @until valueArray2 - * @skipline sum - * - * @param values a vector containing the arrays to be used - * @return an XdmfArray containing one value which is the total of all the values contained within the provided arrays - */ - static shared_ptr sum(std::vector > values); - /** * Exchange the contents of the vector with the contents of this * array. No copy is made. The internal arrays are swapped. @@ -1426,13 +1150,12 @@ public: * C++ * * @dontinclude ExampleXdmfArray.cpp - * @skipline New - * @skipline initArray - * @skipline insert - * @skipline initVector - * @until push_back(5) - * @skipline // - * @until // + * @skipline //#initialization + * @until //#initialization + * @skipline //#initinternalvector + * @until //#initinternalvector + * @skipline //#swapvector + * @until //#swapvector * * Python: The Python version only supports swapping XdmfArrays * @@ -1451,14 +1174,14 @@ public: * C++ * * @dontinclude ExampleXdmfArray.cpp - * @skipline New - * @skipline initArray - * @skipline insert - * @skipline initVector - * @until push_back(5) - * @skipline // - * @skipline storeSwapSucceded - * @until // + * @skipline //#initialization + * @until //#initialization + * @skipline //#initinternalvector + * @until //#initinternalvector + * @skipline //#initsharedvector + * @until //#initsharedvector + * @skipline //#swapsharedvector + * @until //#swapsharedvector * * Python: The Python version only supports swapping XdmfArrays * @@ -1477,22 +1200,20 @@ public: * C++ * * @dontinclude ExampleXdmfArray.cpp - * @skipline New - * @skipline initArray - * @skipline insert - * @skipline swapArray - * @until swap( - * @skipline // + * @skipline //#initialization + * @until //#initialization + * @skipline //#swaparray + * @until //#swaparray * * Python * * @dontinclude XdmfExampleArray.py - * @skipline New - * @skipline initArray - * @skipline insert - * @skipline swapArray - * @until swap( - * @skipline # + * @skipline #//initialization + * @until #//initialization + * @skipline #//arraydefaultvalues + * @until #//arraydefaultvalues + * @skipline //#swap + * @until //#swap * * @param array a smart pointer to a vector to exchange values with. */ @@ -1569,13 +1290,6 @@ private: std::string mName; unsigned int mTmpReserveSize; - static std::string mSupportedOperations; - static const std::string mValidVariableChars; - static const std::string mValidDigitChars; - static int mOperationPriority[]; - - static std::map(*)(std::vector >)> arrayFunctions; - static std::map(*)(shared_ptr, shared_ptr)> operations; }; #include "XdmfArray.tpp" diff --git a/core/XdmfArrayType.cpp b/core/XdmfArrayType.cpp index 54bdd3da..83dfedc6 100644 --- a/core/XdmfArrayType.cpp +++ b/core/XdmfArrayType.cpp @@ -187,6 +187,171 @@ XdmfArrayType::New(const std::map & itemProperties) return shared_ptr(); } +shared_ptr +XdmfArrayType::comparePrecision(shared_ptr type1, shared_ptr type2) +{ + std::string type1Name = type1->getName(); + std::string type2Name = type2->getName(); + + if (type2Name.compare(type1Name) == 0) { + if (type1->getElementSize() >= type2->getElementSize()) { + return type1; + } + else { + return type2; + } + } + + bool firstIsSigned = false; + if (type1Name.compare("UChar") != 0 && type1Name.compare("UShort") != 0 && type1Name.compare("UInt") != 0) { + firstIsSigned = true; + } + + bool secondIsSigned = false; + if (type2Name.compare("UChar") != 0 && type2Name.compare("UShort") != 0 && type2Name.compare("UInt") != 0) { + secondIsSigned = true; + } + + std::map controlmap; + controlmap["Char"] = 1; + controlmap["UChar"] = 2; + controlmap["Short"] = 3; + controlmap["UShort"] = 4; + controlmap["Int"] = 5; + controlmap["UInt"] = 6; + controlmap["Float"] = 7; + controlmap["String"] = 8; + + int control = controlmap[type1Name]; + + + // In this switch the starting location is determined by + // the first type and then the algorithm cascades + // until it finds the second type + switch (control) { + case 1: + // Char + case 2: + // UChar + if (type2Name.compare("Char") == 0 || type2Name.compare("UChar") == 0) { + // This statement would be called in the case + // where there is a mixed type of Char and UChar + // The resulting type should be a Short + return Int16(); + break; + } + case 3: + // Short + if (type2Name.compare("Char") == 0 || type2Name.compare("UChar") == 0 || type2Name.compare("Short") == 0) { + // This will be called for any combination of + // Char/UChar and Short + // In all of these cases the result shoule be a Short + return Int16(); + break; + } + case 4: + // UShort + if (type2Name.compare("Char") == 0 || type2Name.compare("Short") == 0) { + // When mixing UShort with a signed type that has a lower precision + // the resulting type should be an int + return Int32(); + break; + } + else if (type2Name.compare("UChar") == 0 || type2Name.compare("UShort") == 0) { + // When mixing UShort with an unsigned type that has a lower precision + // a Ushort should be the resulting type + if (!firstIsSigned) { + return UInt16(); + } + else { + return Int32(); + } + break; + } + case 5: + // Int + if (type2Name.compare("Int") != 0 && type2Name.compare("UInt") != 0 && type2Name.compare("Float") != 0 && type2Name.compare("String") != 0) { + // When mixing an Int with a type of lower precision + // the resulting type should match the Int's precision + if (type1->getElementSize() == 4) { + return Int32(); + } + else { + return Int64(); + } + break; + } + if (type2Name.compare("Int") == 0) { + if (type2->getElementSize() == 4) { + return Int32(); + } + else { + return Int64(); + } + break; + } + case 6: + // UInt + if (type2Name.compare("UInt") != 0 && type2Name.compare("Int") != 0 && type2Name.compare("Float") != 0 && type2Name.compare("String") != 0) { + // When mixing UInt with another non-floating-point type + // the result should be either long or unsigned int + // depending on the if the mixed type is signed or not + if (!secondIsSigned) { + return UInt32(); + } + else { + return Int64(); + } + break; + } + else if (type2Name.compare("UInt") == 0) { + if (firstIsSigned) { + return Int64(); + } + else { + return UInt32(); + } + break; + } + else if (type2Name.compare("Int") == 0) { + return Int64(); + break; + } + case 7: + // Float + if (type2Name.compare("String") != 0 && type2Name.compare("Float") != 0 && type2Name.compare("UInt") != 0) { + // String is the only type that has priority over a float + // This case occurs when type1 is a float + return type1; + break; + } + else if (type2Name.compare("UInt") == 0) { + return Float64(); + } + else if (type2Name.compare("Float") == 0) { + // Since there was a check earlier to see if the type names matched + // This is the case when type2 is a float + if (type1Name.compare("UInt") == 0) { + return Float64(); + } + else { + return type2; + } + break; + } + case 8: + // String + // String has priority over everything + return String(); + break; + default: + break; + } + // Double is the default value + // Should all of the above manage to fail to return a value + return Float64(); +} + unsigned int XdmfArrayType::getElementSize() const { diff --git a/core/XdmfArrayType.hpp b/core/XdmfArrayType.hpp index 36e9ba5b..04d6875d 100644 --- a/core/XdmfArrayType.hpp +++ b/core/XdmfArrayType.hpp @@ -41,14 +41,14 @@ * C++ * * @dontinclude ExampleXdmfArrayType.cpp - * @skipline XdmfArrayType - * @until } + * @skipline //#getType + * @until //#getType * * Python * * @dontinclude XdmfExampleArrayType.py - * @skipline exampleType - * @until do + * @skipline #//getType + * @until #//getType * * Xdmf supports the following attribute types: * Uninitialized @@ -84,6 +84,27 @@ public: static shared_ptr UInt32(); static shared_ptr String(); + /** + * Compares the two types given and returns a type that is compatible with both. + * + * Example of use: + * + * C++ + * + * @skipline //#comparePrecision + * @until //#comparePrecision + * + * Python + * + * @skipline #//comparePrecision + * @until #//comparePrecision + * + * @param type1 The first type to be compared + * @param type2 The second type to be compared + * @return The type that is compatible with both provided types + */ + static shared_ptr comparePrecision(shared_ptr type1, shared_ptr type2); + /** * Get the data size, in bytes, of the value associated with this * array type. @@ -93,12 +114,14 @@ public: * C++ * * @dontinclude ExampleXdmfArrayType.cpp - * @skipline getElementSize + * @skipline //#getElementSize + * @until //#getElementSize * * Python * * @dontinclude XdmfExampleArrayType.py - * @skipline getElementSize + * @skipline #//getElementSize + * @until #//getElementSize * * @return the data size, in bytes. */ @@ -112,12 +135,14 @@ public: * C++ * * @dontinclude ExampleXdmfArrayType.cpp - * @skipline getName + * @skipline //#getName + * @until //#getName * * Python * * @dontinclude XdmfExampleArrayType.py - * @skipline getName + * @skipline #//getName + * @until #//getName * * @return the name of the data type. */ diff --git a/core/XdmfCore.i b/core/XdmfCore.i index f5a76c87..1c905150 100644 --- a/core/XdmfCore.i +++ b/core/XdmfCore.i @@ -185,9 +185,6 @@ swig -v -c++ -python -o XdmfCorePython.cpp XdmfCore.i #endif -/*This causes it to avoid throwing a warning for redefining fuctions that are defined for XdmfArray. - I do this because doing so was intentional.*/ -#pragma SWIG nowarn=302 /*This causes it to avoid throwing a warning about overloaded functions. We are doing this intentionally so suppressing the warning makes sense.*/ #pragma SWIG nowarn=509 @@ -195,15 +192,6 @@ swig -v -c++ -python -o XdmfCorePython.cpp XdmfCore.i // Provide accessors from python lists to XdmfArrays %extend XdmfArray { -%{ - #include - static std::map pythonFunctions; - static std::map pythonOperations; - static int pythonOperationPriority [4]; - static std::string pythonSupportedOperations = ""; -%} -/*These can't be accessed from python so don't worry about security issues.*/ - PyObject * getBuffer() { void *vp = $self->getValuesInternal(); Py_ssize_t sz = @@ -328,558 +316,6 @@ swig -v -c++ -python -o XdmfCorePython.cpp XdmfCore.i } -/*Note, the things in this block are defined twice for a reason. - If they are not defined here they can not be referenced by other functions in swig.*/ -%{ - /*trying to transfer python funcitons*/ - /*note, accessing private members is impossible from swig.*/ - - /*to generate new static functions mark them as static here.*/ - static shared_ptr evaluateFunction(std::vector > functValues, std::string functName) - { - if (pythonFunctions.find(functName)!= pythonFunctions.end()) { - swig_type_info * paramType = SWIG_TypeQuery("_p_std__vectorT_boost__shared_ptrT_XdmfArray_t_std__allocatorT_boost__shared_ptrT_XdmfArray_t_t_t"); - PyObject * pyVector = SWIG_NewPointerObj(static_cast(& functValues), paramType, SWIG_POINTER_NEW); - PyObject * args = PyTuple_New(1); - PyTuple_SetItem(args, 0, pyVector);/*In this case you could also cast a pointer to the vector into the PyObject * type, but that doesn't work for all types*/ - PyObject * resultObject = PyObject_CallObject(pythonFunctions[functName], args); - void * resultPointer = 0; - swig_type_info * returnType = SWIG_TypeQuery("_p_boost__shared_ptrT_XdmfArray_t"); - SWIG_ConvertPtr(resultObject, &resultPointer, returnType, 0); - shared_ptr * returnArrayPointer = reinterpret_cast *>(resultPointer); - shared_ptr returnArray = returnArrayPointer[0]; - return returnArray; - } - else { - /*this does not actually cause an infinte recursive loop, it sends the values to the version of the function defined in XdmfArray.cpp*/ - return XdmfArray::evaluateFunction(functValues, functName); - } - } - - static shared_ptr evaluateOperation(shared_ptr val1, shared_ptr val2, char functName) - { - if (pythonOperations.find(functName)!= pythonOperations.end()) { - swig_type_info * paramType = SWIG_TypeQuery("_p_boost__shared_ptrT_XdmfArray_t"); - PyObject * pyVal1 = SWIG_NewPointerObj(static_cast(& val1), paramType, SWIG_POINTER_NEW); - PyObject * pyVal2 = SWIG_NewPointerObj(static_cast(& val2), paramType, SWIG_POINTER_NEW); - PyObject * args = PyTuple_New(2); - PyTuple_SetItem(args, 0, pyVal1); - PyTuple_SetItem(args, 1, pyVal2); - PyObject * resultObject = PyObject_CallObject(pythonOperations[functName], args); - void * resultPointer = 0; - swig_type_info * returnType = SWIG_TypeQuery("_p_boost__shared_ptrT_XdmfArray_t"); - SWIG_ConvertPtr(resultObject, &resultPointer, returnType, 0); - shared_ptr * returnArrayPointer = reinterpret_cast *>(resultPointer); - shared_ptr returnArray = returnArrayPointer[0]; - return returnArray; - } - else { - /*this does not actually cause an infinte recursive loop, it sends the values to the version of the function defined in XdmfArray.cpp*/ - return XdmfArray::evaluateOperation(val1, val2, functName); - } - } - - static shared_ptr evaluateExpression(std::string expression, std::map > variables) - { - std::stack > valueStack; - std::stack operationStack; - - /*string is parsed left to right - elements of the same priority are evaluated right to left*/ - for (unsigned int i = 0; i < expression.size(); i++) { - if (XdmfArray::getValidDigitChars().find(expression[i]) != std::string::npos) {/*found to be a digit*/ - /*progress until a non-digit is found*/ - int valueStart = i; - while (XdmfArray::getValidDigitChars().find(expression[i + 1]) != std::string::npos) { - i++; - } - /*push back to the value stack*/ - shared_ptr 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 (XdmfArray::getValidVariableChars().find(expression[i]) != std::string::npos) {/*found to be a variable*/ - int valueStart = i; - /*progress until a nonvariable value is found*/ - while (XdmfArray::getValidVariableChars().find(expression[i + 1]) != std::string::npos) { - i++; - } - /*convert to equivalent*/ - if (variables.find(expression.substr(valueStart, i + 1 - valueStart)) == variables.end()) { - std::vector functionList = XdmfArray::getSupportedFunctions(); - bool functionExists = false; - for (unsigned int j = 0; j < functionList.size() && !functionExists; j++) { - if (functionList[j] == expression.substr(valueStart, i + 1 - valueStart)) { - functionExists = true; - } - } - if (functionExists) { - 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 > 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 (XdmfArray::getSupportedOperations().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 val2 = valueStack.top(); - valueStack.pop(); - shared_ptr 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 block*/ - } - else { - int operationLocation = XdmfArray::getOperationPriority(expression[i]); - int topOperationLocation = XdmfArray::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 val2 = valueStack.top(); - valueStack.pop(); - shared_ptr val1 = valueStack.top(); - valueStack.pop(); - valueStack.push(evaluateOperation(val1, val2, operationStack.top())); - operationStack.pop(); - if (operationStack.size() == 0) { - break; - } - topOperationLocation = XdmfArray::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 val2 = valueStack.top(); - valueStack.pop(); - shared_ptr 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(); - } - -%} - - /*trying to transfer python funcitons*/ - /*note, accessing private members is impossible from swig.*/ - static int addFunction(std::string newName, PyObject * functionref) - { - /*check if the object is callable*/ - if (PyCallable_Check(functionref) == 1) { - pythonFunctions[newName] = functionref; - return pythonFunctions.size(); - } - else { - XdmfError::message(XdmfError::FATAL, - "Error: Function is not callable"); - return -1; - } - } - - /*to generate new static functions mark them as static here.*/ - static std::vector getSupportedFunctions() - { - std::vector returnVector = XdmfArray::getSupportedFunctions(); - for (std::map::iterator functionWalker = pythonFunctions.begin(); functionWalker != pythonFunctions.end(); functionWalker++) { - returnVector.push_back(functionWalker->first); - } - return returnVector; - } - - static shared_ptr evaluateFunction(std::vector > functValues, std::string functName) - { - if (pythonFunctions.find(functName)!= pythonFunctions.end()) { - swig_type_info * paramType = SWIG_TypeQuery("_p_std__vectorT_boost__shared_ptrT_XdmfArray_t_std__allocatorT_boost__shared_ptrT_XdmfArray_t_t_t"); - PyObject * pyVector = SWIG_NewPointerObj(static_cast(& functValues), paramType, SWIG_POINTER_NEW); - PyObject * args = PyTuple_New(1); - PyTuple_SetItem(args, 0, pyVector);/*In this case you could also cast a pointer to the vector into the PyObject * type, but that doesn't work for all types*/ - PyObject * resultObject = PyObject_CallObject(pythonFunctions[functName], args); - void * resultPointer = 0; - swig_type_info * returnType = SWIG_TypeQuery("_p_boost__shared_ptrT_XdmfArray_t"); - SWIG_ConvertPtr(resultObject, &resultPointer, returnType, 0); - shared_ptr * returnArrayPointer = reinterpret_cast *>(resultPointer); - shared_ptr returnArray = returnArrayPointer[0]; - return returnArray; - } - else { - /*this does not actually cause an infinte recursive loop, it sends the values to the version of the function defined in XdmfArray.cpp*/ - return XdmfArray::evaluateFunction(functValues, functName); - } - } - - static int addOperation(char newName, PyObject * calcref, int priority) - { - if (newName == '(' || newName == ')') { - XdmfError::message(XdmfError::FATAL, - "Error: Parenthesis can not be redefined"); - } - /*check if the object is callable*/ - if (PyCallable_Check(calcref) == 1) { - if (pythonOperations.find(newName) != pythonOperations.end() || XdmfArray::getSupportedOperations().find(newName) != std::string::npos) { - XdmfError::message(XdmfError::WARNING, - "Warning: Operation Redefined");/*It's a good idea to warn users when they're doing this*/ - size_t operationLocation = pythonSupportedOperations.find(newName); - /*if not an already defined python function*/ - if (pythonOperations.find(newName) == pythonOperations.end()) { - pythonSupportedOperations.push_back(newName); - unsigned int priorityArraySize = sizeof(pythonOperationPriority)/sizeof(int); - if (pythonSupportedOperations.size()-1 > priorityArraySize) { - int newArray [priorityArraySize*2]; - std::copy(pythonOperationPriority, pythonOperationPriority+(priorityArraySize-1), newArray); - *pythonOperationPriority = *newArray; - } - } - pythonOperationPriority[operationLocation] = priority; - /*if defined on the c++ side same as adding a new one*/ - } - else { - pythonSupportedOperations += newName; - if (XdmfArray::getValidVariableChars().find(newName) != std::string::npos || XdmfArray::getValidDigitChars().find(newName) != std::string::npos) { - XdmfError::message(XdmfError::FATAL, - "Error: Operation Overlaps with Variables"); - } - else { - pythonSupportedOperations.push_back(newName); - unsigned int priorityArraySize = sizeof(pythonOperationPriority)/sizeof(int); - if (pythonSupportedOperations.size()-1 > priorityArraySize) - { - int newArray [priorityArraySize*2]; - std::copy(pythonOperationPriority, pythonOperationPriority+(priorityArraySize-1), newArray); - *pythonOperationPriority = *newArray; - } - } - } - pythonOperations[newName] = calcref; - return pythonOperations.size(); - } - else { - XdmfError::message(XdmfError::FATAL, - "Error: Operation is not callable"); - return -1; - } - } - - static std::string getSupportedOperations() - { - std::string returnVector = XdmfArray::getSupportedOperations(); - for (std::map::iterator functionWalker = pythonOperations.begin(); functionWalker != pythonOperations.end(); functionWalker++) { - returnVector += functionWalker->first; - } - return returnVector; - } - - static shared_ptr evaluateOperation(shared_ptr val1, shared_ptr val2, char functName) - { - if (pythonOperations.find(functName)!= pythonOperations.end()) { - swig_type_info * paramType = SWIG_TypeQuery("_p_boost__shared_ptrT_XdmfArray_t"); - PyObject * pyVal1 = SWIG_NewPointerObj(static_cast(& val1), paramType, SWIG_POINTER_NEW); - PyObject * pyVal2 = SWIG_NewPointerObj(static_cast(& val2), paramType, SWIG_POINTER_NEW); - PyObject * args = PyTuple_New(2); - PyTuple_SetItem(args, 0, pyVal1); - PyTuple_SetItem(args, 1, pyVal2); - PyObject * resultObject = PyObject_CallObject(pythonOperations[functName], args); - void * resultPointer = 0; - swig_type_info * returnType = SWIG_TypeQuery("_p_boost__shared_ptrT_XdmfArray_t"); - SWIG_ConvertPtr(resultObject, &resultPointer, returnType, 0); - shared_ptr * returnArrayPointer = reinterpret_cast *>(resultPointer); - shared_ptr returnArray = returnArrayPointer[0]; - return returnArray; - } - else { - /*this does not actually cause an infinte recursive loop, it sends the values to the version of the function defined in XdmfArray.cpp*/ - return XdmfArray::evaluateOperation(val1, val2, functName); - } - } - - static shared_ptr evaluateExpression(std::string expression, std::map > variables) - { - std::stack > valueStack; - std::stack operationStack; - - /*string is parsed left to right - elements of the same priority are evaluated right to left*/ - for (unsigned int i = 0; i < expression.size(); i++) { - if (XdmfArray::getValidDigitChars().find(expression[i]) != std::string::npos) { /*found to be a digit*/ - /*progress until a non-digit is found*/ - int valueStart = i; - while (XdmfArray::getValidDigitChars().find(expression[i + 1]) != std::string::npos) { - i++; - } - /*push back to the value stack*/ - shared_ptr 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 (XdmfArray::getValidVariableChars().find(expression[i]) != std::string::npos) {/*found to be a variable*/ - int valueStart = i; - /*progress until a nonvariable value is found*/ - while (XdmfArray::getValidVariableChars().find(expression[i + 1]) != std::string::npos) { - i++; - } - /*convert to equivalent*/ - if (variables.find(expression.substr(valueStart, i + 1 - valueStart)) == variables.end()) { - std::vector functionList = XdmfArray::getSupportedFunctions(); - bool functionExists = false; - for (unsigned int j = 0; j < functionList.size() && !functionExists; j++) { - if (functionList[j] == expression.substr(valueStart, i + 1 - valueStart)) { - functionExists = true; - } - } - if (functionExists) { - 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 > 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 (XdmfArray::getSupportedOperations().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 val2 = valueStack.top(); - valueStack.pop(); - shared_ptr 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 = XdmfArray::getOperationPriority(expression[i]); - int topOperationLocation = XdmfArray::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 val2 = valueStack.top(); - valueStack.pop(); - shared_ptr val1 = valueStack.top(); - valueStack.pop(); - valueStack.push(evaluateOperation(val1, val2, operationStack.top())); - operationStack.pop(); - if (operationStack.size() == 0) { - break; - } - topOperationLocation = XdmfArray::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 val2 = valueStack.top(); - valueStack.pop(); - shared_ptr 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(); - } - - - static shared_ptr XdmfArrayPtr(PyObject * obj) { void * resultPointer = 0; diff --git a/core/XdmfCoreItemFactory.hpp b/core/XdmfCoreItemFactory.hpp index 348994fb..43365d2d 100644 --- a/core/XdmfCoreItemFactory.hpp +++ b/core/XdmfCoreItemFactory.hpp @@ -50,14 +50,14 @@ public: * Example of use: * * @dontinclude ExampleXdmfCoreItemFactory.cpp - * @skipline // - * @until collections + * @skipline //#createItem + * @until //#createItem * * Python * * @dontinclude XdmfExampleCoreItemFactory.py - * @skipline # - * @until collections + * @skipline #//createItem + * @until #//createItem * * @param itemTag a string containing the tag of the XdmfItem to create. * @param itemProperties a map of key/value properties for the the XdmfItem. diff --git a/core/XdmfCoreReader.cpp b/core/XdmfCoreReader.cpp index b8b85958..28b1cfb2 100644 --- a/core/XdmfCoreReader.cpp +++ b/core/XdmfCoreReader.cpp @@ -181,358 +181,6 @@ public: } } - else if (xmlStrcmp(currNode->name, (xmlChar*)"Function") == 0) { - // Function handling goes here - xmlNodePtr childNode = currNode->children; - - std::string arraySubType = ""; - // Gget Array Subtype, if any - xmlAttrPtr currAttribute = currNode->properties; - while (currAttribute != NULL) { - if (xmlStrcmp(currAttribute->name, (xmlChar*)"Type") == 0 ) { - arraySubType = (char*)currAttribute->children->content; - break; - // Uses the first type found - } - } - - std::string expressionToParse = ""; - - while (childNode != NULL) { - if (xmlStrcmp(childNode->name, (xmlChar*)"Expression") == 0){ - // Store expression - xmlAttrPtr childAttribute = childNode->properties; - while (childAttribute != NULL) { - if(xmlStrcmp(childAttribute->name, (xmlChar*)"Value") == 0) { - expressionToParse = (char*)childAttribute->children->content; - break; - } - childAttribute = childAttribute->next; - } - break; - } - childNode = childNode->next; - } - - if (expressionToParse.compare("") == 0) { - try { - XdmfError::message(XdmfError::FATAL, - "Error: No Expression in Function"); - } - catch (XdmfError e) { - throw e; - } - } - - // Two seperate loops to allow for different orders and multiple variable sets - childNode = currNode->children; - - std::map > variableCollection; - while (childNode != NULL) { - if (xmlStrcmp(childNode->name, (xmlChar*)"Variable") == 0) { - // Store child variables - xmlNodePtr childVariable = childNode->children; - - while (childVariable != NULL) { - if (xmlStrcmp(childVariable->name, (xmlChar*)"DataItem") == 0) { - xmlAttrPtr childAttribute = childVariable->properties; - std::string childKey = ""; - shared_ptr childArray = XdmfArray::New(); - std::string dataString = ""; - shared_ptr dataType; - xmlChar * childXPointer = NULL; - xmlChar * childhref = NULL; - std::string childhdf5 = ""; - std::map typeMap; - - while (childAttribute != NULL) { - // The variable type of the array - if (xmlStrcmp(childAttribute->name, (xmlChar*)"DataType") == 0) { - typeMap["DataType"] = (char*)childAttribute->children->content; - } - // The precision of the variable type (only used for long and double) - else if (xmlStrcmp(childAttribute->name, (xmlChar*)"Precision") == 0) { - typeMap["Precision"] = (char*)childAttribute->children->content; - } - // The key or mapped string for the variable - else if (xmlStrcmp(childAttribute->name, (xmlChar*)"Key") == 0) { - childKey = (char*)childAttribute->children->content; - } - // Text based xml data - else if (xmlStrcmp(childAttribute->name, (xmlChar*)"Value") == 0) { - dataString = (char*)childAttribute->children->content; - } - // An x pointer to another XdmfArray - else if (xmlStrcmp(childAttribute->name, (xmlChar*)"XPointer") == 0) { - childXPointer = childAttribute->children->content; - } - // Used in conjunction with Xpointers to reference objects in a different file - else if (xmlStrcmp(childAttribute->name, (xmlChar*)"href") == 0) { - childhref = childAttribute->children->content; - } - // Path to hdf5 data sets and the dimensions of those sets - else if (xmlStrcmp(childAttribute->name, (xmlChar*)"hdf5") == 0) { - childhdf5 = (char*)childAttribute->children->content; - } - childAttribute = childAttribute->next; - } - - if (typeMap["DataType"].compare("Float") == 0) { - if (typeMap["Precision"].compare("8") == 0) { - dataType = XdmfArrayType::Float64(); - } - else { - dataType = XdmfArrayType::Float32(); - } - } - else if (typeMap["DataType"].compare("Int") == 0) { - if (typeMap["Precision"].compare("8") == 0) { - dataType = XdmfArrayType::Int64(); - } - else { - dataType = XdmfArrayType::Int32(); - } - } - else if (typeMap["DataType"].compare("String") == 0) { - dataType = XdmfArrayType::String(); - } - else if (typeMap["DataType"].compare("Char") == 0) { - dataType = XdmfArrayType::Int8(); - } - else if (typeMap["DataType"].compare("Short") == 0) { - dataType = XdmfArrayType::Int16(); - } - else if (typeMap["DataType"].compare("UChar") == 0) { - dataType = XdmfArrayType::UInt8(); - } - else if (typeMap["DataType"].compare("UShort") == 0) { - dataType = XdmfArrayType::UInt16(); - } - else if (typeMap["DataType"].compare("UInt") == 0) { - dataType = XdmfArrayType::UInt32(); - } - else { - dataType = XdmfArrayType::Uninitialized(); - } - - // If xpointer grab item at that location - if (childXPointer) { - xmlXPathContextPtr context = mXPathContext; - - if(childhref) { - xmlDocPtr document; - xmlChar * filePath = xmlBuildURI(childhref, mDocument->URL); - std::map::const_iterator iter = - mDocuments.find((char*)filePath); - if(iter == mDocuments.end()) { - document = xmlReadFile((char*)filePath, NULL, 0); - mDocuments.insert(std::make_pair((char*)document->URL, document)); - } - else { - document = iter->second; - } - context = xmlXPtrNewContext(document, NULL, NULL); - } - - if(childXPointer) { - xmlXPathObjectPtr result = xmlXPtrEval(childXPointer, context); - if(result && !xmlXPathNodeSetIsEmpty(result->nodesetval)) { - for(int i=0; inodesetval->nodeNr; ++i) { - // There should only be one item being returned here - // Place into a new vector - std::vector > pointedItems; - this->readSingleNode(result->nodesetval->nodeTab[i], pointedItems); - try { - // Try to cast it as an array - childArray = shared_dynamic_cast(pointedItems[0]); - } - catch (...) { - // If that doesn't work throw an error - try { - // Because we should only be working with arrays - XdmfError::message(XdmfError::FATAL, - "Error: Variable not Equivalent to an Array"); - } - catch (XdmfError e) { - throw e; - } - } - } - } - xmlXPathFreeObject(result); - } - - if(childhref) { - xmlXPathFreeContext(context); - } - } - // If hdf5 create controllers and attach it - else if (childhdf5.compare("") != 0) { - // Parse the hdf5 controllers - std::vector controllerParts; - // Split the content based on "|" characters - size_t barSplit = 0; - std::string splitString(childhdf5); - std::string subcontent; - - while (barSplit != std::string::npos) { - barSplit = 0; - barSplit = splitString.find_first_of("|", barSplit); - if (barSplit == std::string::npos) { - subcontent = splitString; - } - else { - subcontent = splitString.substr(0, barSplit); - splitString = splitString.substr(barSplit+1); - barSplit++; - } - controllerParts.push_back(subcontent); - } - - // Insert those controllers into the childArray - int hdf5step = 2; - for (unsigned int i = 0; i < controllerParts.size(); i = i + hdf5step) { - size_t colonLocation = controllerParts[i].find(":"); - if(colonLocation == std::string::npos) { - try { - XdmfError::message(XdmfError::FATAL, - "':' not found in function variable content in " - "read -- double check an HDF5 " - "data set is specified for the file"); - } - catch (XdmfError e) { - throw e; - } - } - - std::string hdf5Path = controllerParts[i].substr(0, colonLocation); - std::string dataSetPath = controllerParts[i].substr(colonLocation+1); - std::vector contentDims; - - if (i + 1 < controllerParts.size()){ - // This is the string that contains the dimensions - boost::tokenizer<> dimtokens(controllerParts[i + 1]); - for(boost::tokenizer<>::const_iterator iter = dimtokens.begin(); - iter != dimtokens.end(); - ++iter) { - contentDims.push_back(atoi((*iter).c_str())); - } - hdf5step = 2;// If this works then the dimension content should be skipped over - } - else { - // If it fails then it means that the next content is not a dimension string - // In this case an error should be thrown, formatting error - // because there is no base array to pull dimensions from - try { - XdmfError::message(XdmfError::FATAL, - "Error: Improper HDF5 Format"); - } - catch (XdmfError e) { - throw e; - } - } - - childArray->insert(XdmfHDF5Controller::New(hdf5Path, - dataSetPath, - dataType, - std::vector(contentDims.size(), 0), - std::vector(contentDims.size(), 1), - contentDims, - contentDims)); - } - } - // If xml parse strait to insert - else if (dataString.compare("") != 0) { - // Parse the data into tokens - childArray->initialize(dataType, 0); - unsigned int index = 0; - boost::char_separator sep(" \t\n"); - boost::tokenizer > tokens(dataString, sep); - if(dataType == XdmfArrayType::String()) { - for(boost::tokenizer >::const_iterator - iter = tokens.begin(); - iter != tokens.end(); - ++iter, ++index) { - // Insert those tokens into the childArray - childArray->insert(index, *iter); - } - } - else { - for(boost::tokenizer >::const_iterator - iter = tokens.begin(); - iter != tokens.end(); - ++iter, ++index) { - // Insert those tokens into the childArray - childArray->insert(index, atof((*iter).c_str())); - } - } - } - - // Parse the value into the array - if (childKey.compare("") != 0){ - if (variableCollection.find(childKey) != variableCollection.end()) { - try { - XdmfError::message(XdmfError::WARNING, - "Warning: Variable Redefined"); - } - catch (XdmfError e) { - throw e; - } - } - childArray->read(); - variableCollection[childKey] = childArray; - } - else { - try { - XdmfError::message(XdmfError::WARNING, - "Warning: Value Unpaired to Key"); - } - catch (XdmfError e) { - throw e; - } - } - } - childVariable = childVariable->next; - } - } - childNode = childNode->next; - } - shared_ptr parsedArray = shared_ptr(); - try { - parsedArray = XdmfArray::evaluateExpression(expressionToParse, variableCollection); - } - catch (XdmfError e) { - throw e; - } - // The properties and children aren't really needed to generate the object, but the factory still requires them. - std::map newArrayProperties; - std::vector > newArrayChildren; - shared_ptr returnArray = XdmfArray::New(); - - if (arraySubType.compare("") == 0) { - // If no type is specified an array is generated - arraySubType = "DataItem"; - } - - // This should generate an item that corresponds to the tag provided, the casting ensures that it is a subtype of array - // Using a factory to be able to build things outside of core - returnArray = shared_dynamic_cast(mItemFactory->createItem( - arraySubType, - newArrayProperties, - newArrayChildren)); - - if (!returnArray) { - // If the specified tag fails to generate an item then reclass as an array - arraySubType = "DataItem"; - returnArray = shared_dynamic_cast(mItemFactory->createItem( - arraySubType, - newArrayProperties, - newArrayChildren)); - } - - returnArray->insert(0, parsedArray, 0, parsedArray->getSize()); - myItems.push_back(returnArray); - } else { // Normal reading try { @@ -570,7 +218,6 @@ public: xmlNodePtr childNode = currNode->children; if (XdmfArray::ItemTag.compare((char *)currNode->name) == 0) { - unsigned int childContentIndex = 0; while(childNode != NULL) { if(childNode->type == XML_TEXT_NODE && childNode->content) { const char * content = (char*)childNode->content; @@ -589,30 +236,9 @@ public: } if(!whitespace) { - if (childContentIndex == 0) { - itemProperties.insert(std::make_pair("XMLDir", mXMLDir)); - } - - // Split the content based on "|" characters - size_t barSplit = 0; - std::string splitString(content); - std::string subcontent; - while (barSplit != std::string::npos) { - barSplit = 0; - barSplit = splitString.find_first_of("|", barSplit); - if (barSplit == std::string::npos) { - subcontent = splitString; - } - else { - subcontent = splitString.substr(0, barSplit); - splitString = splitString.substr(barSplit+1); - barSplit++; - } - std::stringstream contentString; - contentString << "Content" << childContentIndex; - itemProperties.insert(std::make_pair(contentString.str(), subcontent)); - childContentIndex++; - } + itemProperties.insert(std::make_pair("Content", content)); + itemProperties.insert(std::make_pair("XMLDir", mXMLDir)); + break; } } childNode = childNode->next; @@ -644,7 +270,12 @@ public: throw e; } } - newItem->populateItem(itemProperties, childItems, mCoreReader); + if (newItem->getItemTag().compare((const char *)currNode->name) != 0) { + newItem->populateItem(itemProperties, std::vector >(), mCoreReader); + } + else { + newItem->populateItem(itemProperties, childItems, mCoreReader); + } myItems.push_back(newItem); mXPathMap.insert(std::make_pair(currNode, newItem)); } diff --git a/core/XdmfCoreReader.hpp b/core/XdmfCoreReader.hpp index 13909b29..74b8832d 100644 --- a/core/XdmfCoreReader.hpp +++ b/core/XdmfCoreReader.hpp @@ -59,18 +59,18 @@ public: * C++ * * @dontinclude ExampleXdmfCoreReader.cpp - * @skipline using - * @skipline New - * @skipline readLight - * @until parse + * @skipline //#initialization + * @until //#initialization + * @skipline //#parse + * @until //#parse * * Python * * @dontinclude XdmfExampleCoreReader.py - * @skipline using - * @skipline New - * @skipline readLight - * @until parse + * @skipline #//initialization + * @until #//initialization + * @skipline #//parse + * @until #//parse * * @param lightData a string containing light data description of an * Xdmf file. @@ -87,19 +87,22 @@ public: * C++ * * @dontinclude ExampleXdmfCoreReader.cpp - * @skipline using - * @skipline New - * @skipline readPath - * @skipline Assuming - * @until exampleDomain + * @skipline //#initialization + * @until //#initialization + * @skipline //#readpath + * @until //#readpath + * @skipline //#readroot + * @until //#readroot * * Python * * @dontinclude XdmfExampleCoreReader.py - * @skipline using - * @skipline New - * @skipline readPath - * @skipline exampleItem + * @skipline #//initialization + * @until #//initialization + * @skipline #//readpath + * @until #//readpath + * @skipline #//readroot + * @until #//readroot * * @param filePath the path of the Xdmf file to read in from disk. * @@ -115,20 +118,22 @@ public: * C++ * * @dontinclude ExampleXdmfCoreReader.cpp - * @skipline using - * @skipline New - * @skipline readPath - * @skipline readXPath - * @skipline exampleItems + * @skipline //#initialization + * @until //#initialization + * @skipline //#readpath + * @until //#readpath + * @skipline //#readXPath + * @until //#readXPath * * Python * * @dontinclude XdmfExampleCoreReader.py - * @skipline using - * @skipline New - * @skipline readPath - * @skipline readXPath - * @skipline exampleItems + * @skipline #//initialization + * @until #//initialization + * @skipline #//readpath + * @until #//readpath + * @skipline #//readXPath + * @until #//readXPath * * @param filePath the path of the Xdmf file to read in from disk. * @param xPath an XPath corresponding to the portion of the file to read. @@ -147,19 +152,22 @@ public: * C++ * * @dontinclude ExampleXdmfCoreReader.cpp - * @skipline using - * @skipline New - * @skipline readPath - * @skipline exampleCollection - * @until // + * @skipline //#initialization + * @until //#initialization + * @skipline //#readpath + * @until //#readpath + * @skipline //#readItems + * @until //#readItems * * Python * * @dontinclude XdmfExampleCoreReader.py - * @skipline using - * @skipline New - * @skipline readPath - * @skipline exampleCollection + * @skipline #//initialization + * @until #//initialization + * @skipline #//readpath + * @until #//readpath + * @skipline #//readItems + * @until #//readItems * * @param filePath the path of the Xdmf file to read in from disk. * diff --git a/core/XdmfDSMBuffer.cpp b/core/XdmfDSMBuffer.cpp index 986ae2cc..d22176ee 100644 --- a/core/XdmfDSMBuffer.cpp +++ b/core/XdmfDSMBuffer.cpp @@ -102,6 +102,217 @@ class XdmfDSMBuffer::InfoMsg int end_server_id; }; +int +XdmfDSMBuffer::AddressToId(int Address) +{ + int ServerId = XDMF_DSM_FAIL; + + switch(this->DsmType) { + case XDMF_DSM_TYPE_UNIFORM : + case XDMF_DSM_TYPE_UNIFORM_RANGE : + // All Servers have same length + // This finds out which server the address provided starts on + ServerId = this->StartServerId + (Address / this->Length); + if(ServerId > this->EndServerId ){ + try { + std::stringstream message; + message << "ServerId " << ServerId << " for Address " << Address << " is larger than EndServerId " << this->EndServerId; + XdmfError::message(XdmfError::FATAL, message.str()); + } + catch (XdmfError e) { + throw e; + } + } + break; + default : + // Not Implemented + try { + std::stringstream message; + message << "DsmType " << this->DsmType << " not yet implemented"; + XdmfError::message(XdmfError::FATAL, message.str()); + } + catch (XdmfError e) { + throw e; + } + break; + } + return(ServerId); +} + +void +XdmfDSMBuffer::BroadcastComm(int *comm, int root) +{ + int status; + + status = MPI_Bcast(comm, sizeof(int), MPI_UNSIGNED_CHAR, root, this->Comm->GetIntraComm()); + if (status != MPI_SUCCESS) { + try { + XdmfError(XdmfError::FATAL, "Broadcast of Comm failed"); + } + catch (XdmfError e) { + throw e; + } + } +} + +int +XdmfDSMBuffer::BufferService(int *returnOpcode) +{ + int opcode, who, status = XDMF_DSM_FAIL; + int aLength; + int address; + char *datap; + static int syncId = -1; + + if (this->CommChannel == XDMF_DSM_ANY_COMM) { + if (this->Comm->GetId() == 0) { + try { + this->ProbeCommandHeader(&this->CommChannel); + } + catch (XdmfError e) { + throw e; + } + } + try { + this->BroadcastComm(&this->CommChannel, 0); + } + catch (XdmfError e) { + throw e; + } + } + + try { + this->ReceiveCommandHeader(&opcode, &who, &address, &aLength, this->CommChannel, syncId); + } + catch (XdmfError e) { + throw e; + } + + // Connection is an ID for client or server, + int communicatorId = this->CommChannel; + + switch(opcode) { + + // H5FD_DSM_OPCODE_PUT + case XDMF_DSM_OPCODE_PUT: + if (((unsigned int) aLength + address) > this->Length) { + try { + std::stringstream message; + message << "Length " << aLength << " too long for Address " << address << "\n" << + "Server Start = " << this->StartAddress << " End = " << this->EndAddress; + XdmfError::message(XdmfError::FATAL, message.str()); + } + catch (XdmfError e) { + throw e; + } + } + if ((datap = this->DataPointer) == NULL) { + try { + XdmfError::message(XdmfError::FATAL, "Null Data Pointer when trying to put data"); + } + catch (XdmfError e) { + throw e; + } + } + datap += address; + try { + this->ReceiveData(who, datap, aLength, XDMF_DSM_PUT_DATA_TAG, 0, this->CommChannel); + } + catch (XdmfError e) { + throw e; + } + break; + + // H5FD_DSM_OPCODE_GET + case XDMF_DSM_OPCODE_GET: + if (((unsigned int) aLength + address) > this->Length) { + try { + std::stringstream message; + message << "Length " << aLength << " too long for Address " << address << "\n" << + "Server Start = " << this->StartAddress << " End = " << this->EndAddress; + XdmfError::message(XdmfError::FATAL, message.str()); + } + catch (XdmfError e) { + throw e; + } + } + if ((datap = this->DataPointer) == NULL) { + try { + XdmfError::message(XdmfError::FATAL, "Null Data Pointer when trying to put data"); + } + catch (XdmfError e) { + throw e; + } + } + datap += address; + try { + this->SendData(who, datap, aLength, XDMF_DSM_GET_DATA_TAG, 0, this->CommChannel); + } + catch (XdmfError e) { + throw e; + } + break; + +// H5FD_DSM_ACCEPT + // Comes from client + case XDMF_DSM_ACCEPT: + int numConnections; + this->ReceiveAcknowledgment(who, numConnections, XDMF_DSM_EXCHANGE_TAG, XDMF_DSM_INTER_COMM); + this->Comm->Accept(numConnections); + this->SendInfo(); + break; + + // H5FD_DSM_LOCK_ACQUIRE + // Comes from client or server depending on communicator + case XDMF_DSM_LOCK_ACQUIRE: + // Currently unsupported + break; + + // H5FD_DSM_LOCK_RELEASE + // Comes from client or server depending on communicator + case XDMF_DSM_LOCK_RELEASE: + // Currently unsupported + break; + + // H5FD_DSM_OPCODE_DONE + // Always received on server + case XDMF_DSM_OPCODE_DONE: + break; + + // DEFAULT + default : + try { + std::stringstream message; + message << "Error: Unknown Opcode " << opcode; + XdmfError::message(XdmfError::FATAL, message.str()); + } + catch (XdmfError e) { + throw e; + } + } + + if (returnOpcode) *returnOpcode = opcode; + return(XDMF_DSM_SUCCESS); +} + +void +XdmfDSMBuffer::BufferServiceLoop(int *returnOpcode) +{ + int op, status = XDMF_DSM_SUCCESS; + while (status == XDMF_DSM_SUCCESS) { + try { + status = this->BufferService(&op); + } + catch (XdmfError e) { + throw e; + } + if (returnOpcode) *returnOpcode = op; + if (op == XDMF_DSM_OPCODE_DONE) { + break; + } + } +} + void XdmfDSMBuffer::ConfigureUniform(XdmfDSMCommMPI *aComm, long aLength, int startId, int endId, long aBlockLength, @@ -156,245 +367,285 @@ XdmfDSMBuffer::ConfigureUniform(XdmfDSMCommMPI *aComm, long aLength, this->TotalLength = this->GetLength() * (endId - startId + 1); } -bool -XdmfDSMBuffer::GetIsConnected() -{ - return IsConnected; -} - -void -XdmfDSMBuffer::SetIsConnected(bool newStatus) -{ - IsConnected = newStatus; -} - -char * -XdmfDSMBuffer::GetDataPointer() -{ - return this->DataPointer; -} - -int -XdmfDSMBuffer::GetDsmType() -{ - return this->DsmType; -} - -void -XdmfDSMBuffer::SetDsmType(int newDsmType) -{ - this->DsmType = newDsmType; -} - -bool -XdmfDSMBuffer::GetIsServer() -{ - return this->IsServer; -} - void -XdmfDSMBuffer::SetIsServer(bool newIsServer) -{ - this->IsServer = newIsServer; -} - -int -XdmfDSMBuffer::GetEndAddress() +XdmfDSMBuffer::Get(long Address, long aLength, void *Data) { - return this->EndAddress; -} + int who, MyId = this->Comm->GetInterId(); + int astart, aend, len; + char *datap = (char *)Data; -int -XdmfDSMBuffer::GetStartAddress() -{ - return this->StartAddress; + // While there is length left + while(aLength) { + // Figure out what server core the address is located on + who = this->AddressToId(Address); + if(who == XDMF_DSM_FAIL){ + try { + XdmfError::message(XdmfError::FATAL, "Address Error"); + } + catch (XdmfError e) { + throw e; + } + } + // Get the start and end of the block listed + this->GetAddressRangeForId(who, &astart, &aend); + // Determine the amount of data to be written to that core + // Basically, it's how much data will fit from the starting point of the address to the end + len = std::min(aLength, aend - Address + 1); + // If the data is on the core running this code, then the put is simple + if(who == MyId){ + char *dp; + dp = this->DataPointer; + dp += Address - this->StartAddress; + memcpy(datap, dp, len); + } + else{ + // Otherwise send it to the appropriate core to deal with + int status; + int dataComm = XDMF_DSM_INTRA_COMM; + if (this->Comm->GetInterComm() != MPI_COMM_NULL) { + dataComm = XDMF_DSM_INTER_COMM; + } + try { + this->SendCommandHeader(XDMF_DSM_OPCODE_GET, who, Address - astart, len, dataComm); + } + catch (XdmfError e) { + throw e; + } + try { + this->ReceiveData(who, datap, len, XDMF_DSM_GET_DATA_TAG, Address - astart, dataComm); + } + catch (XdmfError e) { + throw e; + } + } + // Shift all the numbers by the length of the data written + // Until aLength = 0 + aLength -= len; + Address += len; + datap += len; + } } -int -XdmfDSMBuffer::GetStartServerId() +void +XdmfDSMBuffer::GetAddressRangeForId(int Id, int *Start, int *End){ + switch(this->DsmType) { + case XDMF_DSM_TYPE_UNIFORM : + case XDMF_DSM_TYPE_UNIFORM_RANGE : + // All Servers have same length + // Start index is equal to the id inside the servers times the length of the block per server + // It is the starting index of the server's data block relative to the entire block + *Start = (Id - this->StartServerId) * this->Length; + // End index is simply the start index + the length of the server's data block. + // The range produced is the start of the server's data block to its end. + *End = *Start + Length - 1; + break; + default : + // Not Implemented + try { + std::stringstream message; + message << "DsmType " << this->DsmType << " not yet implemented"; + XdmfError::message(XdmfError::FATAL, message.str()); + } + catch (XdmfError e) { + throw e; + } + break; + } +} + +long +XdmfDSMBuffer::GetBlockLength() { - return this->StartServerId; + return this->BlockLength; } -int -XdmfDSMBuffer::GetEndServerId() +XdmfDSMCommMPI * +XdmfDSMBuffer::GetComm() { - return this->EndServerId; + return this->Comm; } -long -XdmfDSMBuffer::GetLength() +char * +XdmfDSMBuffer::GetDataPointer() { - return this->Length; + return this->DataPointer; } -long -XdmfDSMBuffer::GetTotalLength() +int +XdmfDSMBuffer::GetDsmType() { - return this->TotalLength; + return this->DsmType; } -long -XdmfDSMBuffer::GetBlockLength() +int +XdmfDSMBuffer::GetEndAddress() { - return this->BlockLength; + return this->EndAddress; } -void -XdmfDSMBuffer::SetBlockLength(long newBlock) +int +XdmfDSMBuffer::GetEndServerId() { - this->BlockLength = newBlock; + return this->EndServerId; } -XdmfDSMCommMPI * -XdmfDSMBuffer::GetComm() +bool +XdmfDSMBuffer::GetIsConnected() { - return this->Comm; + return IsConnected; } -void -XdmfDSMBuffer::SetComm(XdmfDSMCommMPI * newComm) +bool +XdmfDSMBuffer::GetIsServer() { - this->Comm = newComm; + return this->IsServer; } -void -XdmfDSMBuffer::SetLength(long aLength) +long +XdmfDSMBuffer::GetLength() { - this->Length = aLength; - if (this->DataPointer) { - // Try to reallocate - // This should not be called in most cases - this->DataPointer = static_cast(realloc(this->DataPointer, this->Length*sizeof(char))); - } - else { -#ifdef _WIN32 - this->DataPointer = calloc(this->Length, sizeof(char)); -#else - posix_memalign((void **)(&this->DataPointer), getpagesize(), this->Length); - memset(this->DataPointer, 0, this->Length); -#endif - } + return this->Length; +} - if (this->DataPointer == NULL) { - std::stringstream message; - message << "Allocation Failed, unable to allocate " << this->Length; - XdmfError::message(XdmfError::FATAL, message.str()); - } +int +XdmfDSMBuffer::GetStartAddress() +{ + return this->StartAddress; } -void -XdmfDSMBuffer::SendCommandHeader(int opcode, int dest, int address, int aLength, int comm) +int +XdmfDSMBuffer::GetStartServerId() { - int status; - CommandMsg cmd; - memset(&cmd, 0, sizeof(CommandMsg)); - cmd.Opcode = opcode; - cmd.Source = this->Comm->GetId(); - cmd.Target = dest; - cmd.Address = address; - cmd.Length = aLength; + return this->StartServerId; +} - if (comm == XDMF_DSM_INTRA_COMM) { - status = MPI_Send(&cmd, sizeof(CommandMsg), MPI_UNSIGNED_CHAR, dest, XDMF_DSM_COMMAND_TAG, static_cast(this->Comm)->GetIntraComm()); - } - else if (comm == XDMF_DSM_INTER_COMM) { - int interSource = 0; - MPI_Comm_rank(static_cast(this->Comm)->GetInterComm(), &interSource); - cmd.Source = interSource; - status = MPI_Send(&cmd, sizeof(CommandMsg), MPI_UNSIGNED_CHAR, dest, XDMF_DSM_COMMAND_TAG, static_cast(this->Comm)->GetInterComm()); - } - else { - // In this case the comm should be a pointer to an MPI_Comm object - status = MPI_Send(&cmd, sizeof(CommandMsg), MPI_UNSIGNED_CHAR, dest, XDMF_DSM_COMMAND_TAG, comm); - } - if (status != MPI_SUCCESS) { - try { - XdmfError::message(XdmfError::FATAL, "Error: Failed to send command header"); - } - catch (XdmfError e) { - throw e; - } - } +long +XdmfDSMBuffer::GetTotalLength() +{ + return this->TotalLength; } void -XdmfDSMBuffer::ReceiveCommandHeader(int *opcode, int *source, int *address, int *aLength, int comm, int remoteSource) +XdmfDSMBuffer::ProbeCommandHeader(int *comm) { - CommandMsg cmd; - memset(&cmd, 0, sizeof(CommandMsg)); - int status = MPI_ERR_OTHER; + // Used for finding a comm that has a waiting command, then sets the comm + int status = XDMF_DSM_FAIL; MPI_Status signalStatus; - if (remoteSource < 0) { - remoteSource = MPI_ANY_SOURCE; - } + int flag; + MPI_Comm probeComm = static_cast(this->Comm)->GetIntraComm(); - if (comm == XDMF_DSM_INTRA_COMM) { - status = MPI_Recv(&cmd, sizeof(CommandMsg), MPI_UNSIGNED_CHAR, remoteSource, XDMF_DSM_COMMAND_TAG, static_cast(this->Comm)->GetIntraComm(), &signalStatus); - } - else if (comm == XDMF_DSM_INTER_COMM) { - status = MPI_Recv(&cmd, sizeof(CommandMsg), MPI_UNSIGNED_CHAR, remoteSource, XDMF_DSM_COMMAND_TAG, static_cast(this->Comm)->GetInterComm(), &signalStatus); + // Spin until a message is found on one of the communicators + while (status != XDMF_DSM_SUCCESS) { + status = MPI_Iprobe(XDMF_DSM_ANY_SOURCE, XDMF_DSM_ANY_TAG, probeComm, &flag, &signalStatus); + if (status != MPI_SUCCESS) + { + try { + XdmfError::message(XdmfError::FATAL, "Error: Failed to probe for command header"); + } + catch (XdmfError e) { + throw e; + } + } + if (flag) { + status = XDMF_DSM_SUCCESS; + } + else { + if (static_cast(this->Comm)->GetInterComm() != MPI_COMM_NULL) { + if (probeComm == static_cast(this->Comm)->GetIntraComm()) { + probeComm = static_cast(this->Comm)->GetInterComm(); } else { - // In this case the integer is probably a pointer to an MPI_Comm object - status = MPI_Recv(&cmd, sizeof(CommandMsg), MPI_UNSIGNED_CHAR, remoteSource, XDMF_DSM_COMMAND_TAG, comm, &signalStatus); + probeComm = static_cast(this->Comm)->GetIntraComm(); } - - if (status != MPI_SUCCESS) { - try { - XdmfError::message(XdmfError::FATAL, "Error: Failed to receive command header"); - } - catch (XdmfError e) { - throw e; + } } } - else { - *opcode = cmd.Opcode; - *source = cmd.Source; - *address = cmd.Address; - *aLength = cmd.Length; + if (probeComm == static_cast(this->Comm)->GetInterComm()) { + *comm = XDMF_DSM_INTER_COMM; + } + else + { + *comm = XDMF_DSM_INTRA_COMM; } -} + probeComm = MPI_COMM_NULL; +} void -XdmfDSMBuffer::SendData(int dest, char * data, int aLength, int tag, int aAddress, int comm) +XdmfDSMBuffer::Put(long Address, long aLength, const void *Data) { - int status; - if (comm == XDMF_DSM_INTRA_COMM) { - status = MPI_Send(data, aLength, MPI_UNSIGNED_CHAR, dest, tag, static_cast(this->Comm)->GetIntraComm()); - } - else if (comm == XDMF_DSM_INTER_COMM) { - status = MPI_Send(data, aLength, MPI_UNSIGNED_CHAR, dest, tag, static_cast(this->Comm)->GetInterComm()); - } - else { - status = MPI_Send(data, aLength, MPI_UNSIGNED_CHAR, dest, tag, comm); - } - if (status != MPI_SUCCESS) { - try { - XdmfError::message(XdmfError::FATAL, "Error: Failed to send data"); + int who, MyId = this->Comm->GetInterId(); + int astart, aend, len; + char *datap = (char *)Data; + + // While there is length left + while(aLength){ + // Figure out what server core the address is located on + who = this->AddressToId(Address); + if(who == XDMF_DSM_FAIL){ + try { + XdmfError::message(XdmfError::FATAL, "Address Error"); + } + catch (XdmfError e) { + throw e; + } } - catch (XdmfError e) { - throw e; + // Get the start and end of the block listed + this->GetAddressRangeForId(who, &astart, &aend); + // Determine the amount of data to be written to that core + // Basically, it's how much data will fit from the starting point of the address to the end + len = std::min(aLength, aend - Address + 1); + // If the data is on the core running this code, then the put is simple + if(who == MyId){ + char *dp; + dp = this->DataPointer; + dp += Address - this->StartAddress; + memcpy(dp, datap, len); + } + else{ + // Otherwise send it to the appropriate core to deal with + int status; + int dataComm = XDMF_DSM_INTRA_COMM; + if (this->Comm->GetInterComm() != MPI_COMM_NULL) { + dataComm = XDMF_DSM_INTER_COMM; + } + try { + this->SendCommandHeader(XDMF_DSM_OPCODE_PUT, who, Address - astart, len, dataComm); + } + catch (XdmfError e) { + throw e; + } + try { + this->SendData(who, datap, len, XDMF_DSM_PUT_DATA_TAG, Address - astart, dataComm); + } + catch (XdmfError e) { + throw e; + } } + // Shift all the numbers by the length of the data written + // Until aLength = 0 + aLength -= len; + Address += len; + datap += len; } } void -XdmfDSMBuffer::ReceiveData(int source, char * data, int aLength, int tag, int aAddress, int comm) +XdmfDSMBuffer::ReceiveAcknowledgment(int source, int &data, int tag, int comm) { int status; MPI_Status signalStatus; if (comm == XDMF_DSM_INTRA_COMM) { - status = MPI_Recv(data, aLength, MPI_UNSIGNED_CHAR, source, tag, static_cast(this->Comm)->GetIntraComm(), &signalStatus); + status = MPI_Recv(&data, sizeof(int), MPI_UNSIGNED_CHAR, source, tag, static_cast(this->Comm)->GetIntraComm(), &signalStatus); } else if (comm == XDMF_DSM_INTER_COMM) { - status = MPI_Recv(data, aLength, MPI_UNSIGNED_CHAR, source, tag, static_cast(this->Comm)->GetInterComm(), &signalStatus); + status = MPI_Recv(&data, sizeof(int), MPI_UNSIGNED_CHAR, source, tag, static_cast(this->Comm)->GetInterComm(), &signalStatus); } else { - status = MPI_Recv(data, aLength, MPI_UNSIGNED_CHAR, source, tag, comm, &signalStatus); + status = MPI_Recv(&data, sizeof(int), MPI_UNSIGNED_CHAR, source, tag, comm, &signalStatus); } + if (status != MPI_SUCCESS) { try { XdmfError::message(XdmfError::FATAL, "Error: Failed to receive data"); @@ -406,44 +657,58 @@ XdmfDSMBuffer::ReceiveData(int source, char * data, int aLength, int tag, int aA } void -XdmfDSMBuffer::SendAcknowledgment(int dest, int data, int tag, int comm) +XdmfDSMBuffer::ReceiveCommandHeader(int *opcode, int *source, int *address, int *aLength, int comm, int remoteSource) { - int status; + CommandMsg cmd; + memset(&cmd, 0, sizeof(CommandMsg)); + int status = MPI_ERR_OTHER; + MPI_Status signalStatus; + + if (remoteSource < 0) { + remoteSource = MPI_ANY_SOURCE; + } if (comm == XDMF_DSM_INTRA_COMM) { - status = MPI_Send(&data, sizeof(int), MPI_UNSIGNED_CHAR, dest, tag, static_cast(this->Comm)->GetIntraComm()); + status = MPI_Recv(&cmd, sizeof(CommandMsg), MPI_UNSIGNED_CHAR, remoteSource, XDMF_DSM_COMMAND_TAG, static_cast(this->Comm)->GetIntraComm(), &signalStatus); } else if (comm == XDMF_DSM_INTER_COMM) { - status = MPI_Send(&data, sizeof(int), MPI_UNSIGNED_CHAR, dest, tag, static_cast(this->Comm)->GetInterComm()); + status = MPI_Recv(&cmd, sizeof(CommandMsg), MPI_UNSIGNED_CHAR, remoteSource, XDMF_DSM_COMMAND_TAG, static_cast(this->Comm)->GetInterComm(), &signalStatus); } else { - status = MPI_Send(&data, sizeof(int), MPI_UNSIGNED_CHAR, dest, tag, comm); + // In this case the integer is probably a pointer to an MPI_Comm object + status = MPI_Recv(&cmd, sizeof(CommandMsg), MPI_UNSIGNED_CHAR, remoteSource, XDMF_DSM_COMMAND_TAG, comm, &signalStatus); } + if (status != MPI_SUCCESS) { try { - XdmfError::message(XdmfError::FATAL, "Error: Failed to receive data"); + XdmfError::message(XdmfError::FATAL, "Error: Failed to receive command header"); } catch (XdmfError e) { throw e; } } + else { + *opcode = cmd.Opcode; + *source = cmd.Source; + *address = cmd.Address; + *aLength = cmd.Length; + } } void -XdmfDSMBuffer::ReceiveAcknowledgment(int source, int &data, int tag, int comm) +XdmfDSMBuffer::ReceiveData(int source, char * data, int aLength, int tag, int aAddress, int comm) { int status; MPI_Status signalStatus; if (comm == XDMF_DSM_INTRA_COMM) { - status = MPI_Recv(&data, sizeof(int), MPI_UNSIGNED_CHAR, source, tag, static_cast(this->Comm)->GetIntraComm(), &signalStatus); + status = MPI_Recv(data, aLength, MPI_UNSIGNED_CHAR, source, tag, static_cast(this->Comm)->GetIntraComm(), &signalStatus); } else if (comm == XDMF_DSM_INTER_COMM) { - status = MPI_Recv(&data, sizeof(int), MPI_UNSIGNED_CHAR, source, tag, static_cast(this->Comm)->GetInterComm(), &signalStatus); + status = MPI_Recv(data, aLength, MPI_UNSIGNED_CHAR, source, tag, static_cast(this->Comm)->GetInterComm(), &signalStatus); } else { - status = MPI_Recv(&data, sizeof(int), MPI_UNSIGNED_CHAR, source, tag, comm, &signalStatus); + status = MPI_Recv(data, aLength, MPI_UNSIGNED_CHAR, source, tag, comm, &signalStatus); } - if (status != MPI_SUCCESS) { try { XdmfError::message(XdmfError::FATAL, "Error: Failed to receive data"); @@ -455,60 +720,32 @@ XdmfDSMBuffer::ReceiveAcknowledgment(int source, int &data, int tag, int comm) } void -XdmfDSMBuffer::SendInfo() +XdmfDSMBuffer::ReceiveInfo() { InfoMsg dsmInfo; int status; + MPI_Status signalStatus; memset(&dsmInfo, 0, sizeof(InfoMsg)); - dsmInfo.type = this->GetDsmType(); - dsmInfo.length = this->GetLength(); - dsmInfo.total_length = this->GetTotalLength(); - dsmInfo.block_length = this->GetBlockLength(); - dsmInfo.start_server_id = this->GetStartServerId(); - dsmInfo.end_server_id = this->GetEndServerId(); + + int infoStatus = 0; + if (this->Comm->GetId() == 0) { - status = MPI_Send(&dsmInfo, sizeof(InfoMsg), MPI_UNSIGNED_CHAR, 0, XDMF_DSM_EXCHANGE_TAG, static_cast(this->Comm)->GetInterComm()); - if (status != MPI_SUCCESS) { - try { - XdmfError::message(XdmfError::FATAL, "Error: Failed to send info"); - } - catch (XdmfError e) { - throw e; - } - } - } - status = MPI_Barrier(this->Comm->GetIntraComm()); - if (status != MPI_SUCCESS) { - try { - XdmfError::message(XdmfError::FATAL, "Error: Failed to send info"); - } - catch (XdmfError e) { - throw e; - } + infoStatus = 1; } -} -void -XdmfDSMBuffer::ReceiveInfo() -{ - InfoMsg dsmInfo; - int status; - MPI_Status signalStatus; + int groupInfoStatus[this->Comm->GetInterSize()]; - memset(&dsmInfo, 0, sizeof(InfoMsg)); - if (this->Comm->GetId() == 0) { - status = MPI_Recv(&dsmInfo, sizeof(InfoMsg), MPI_UNSIGNED_CHAR, XDMF_DSM_ANY_SOURCE, XDMF_DSM_EXCHANGE_TAG, static_cast(this->Comm)->GetInterComm(), &signalStatus); - if (status != MPI_SUCCESS) { - try { - XdmfError::message(XdmfError::FATAL, "Error: Failed to receive info"); - } - catch (XdmfError e) { - throw e; - } + MPI_Allgather(&infoStatus, 1, MPI_INT, &groupInfoStatus, 1, MPI_INT, this->Comm->GetInterComm()); + + int sendCore = 0; + + for (int i = 0; i < this->Comm->GetInterSize(); ++i) { + if (groupInfoStatus[i] == 2) { + sendCore = i; } } - status = MPI_Bcast(&dsmInfo, sizeof(InfoMsg), MPI_UNSIGNED_CHAR, 0, static_cast(this->Comm)->GetIntraComm()); + status = MPI_Bcast(&dsmInfo, sizeof(InfoMsg), MPI_UNSIGNED_CHAR, sendCore, static_cast(this->Comm)->GetInterComm()); if (status != MPI_SUCCESS) { try { XdmfError::message(XdmfError::FATAL, "Error: Failed to broadcast info"); @@ -527,14 +764,37 @@ XdmfDSMBuffer::ReceiveInfo() } void -XdmfDSMBuffer::BroadcastComm(int *comm, int root) +XdmfDSMBuffer::SendAccept(unsigned int numConnections) +{ + if (this->Comm->GetId() == 0) { + for (int i = this->StartServerId; i <= this->EndServerId; ++i) { + if (i != this->Comm->GetId()){ + this->SendCommandHeader(XDMF_DSM_ACCEPT, i, 0, 0, XDMF_DSM_INTER_COMM); + this->SendAcknowledgment(i, numConnections, XDMF_DSM_EXCHANGE_TAG, XDMF_DSM_INTER_COMM); + } + } + } + this->Comm->Accept(numConnections); + this->SendInfo(); +} + +void +XdmfDSMBuffer::SendAcknowledgment(int dest, int data, int tag, int comm) { int status; - status = MPI_Bcast(comm, sizeof(int), MPI_UNSIGNED_CHAR, root, this->Comm->GetIntraComm()); + if (comm == XDMF_DSM_INTRA_COMM) { + status = MPI_Send(&data, sizeof(int), MPI_UNSIGNED_CHAR, dest, tag, static_cast(this->Comm)->GetIntraComm()); + } + else if (comm == XDMF_DSM_INTER_COMM) { + status = MPI_Send(&data, sizeof(int), MPI_UNSIGNED_CHAR, dest, tag, static_cast(this->Comm)->GetInterComm()); + } + else { + status = MPI_Send(&data, sizeof(int), MPI_UNSIGNED_CHAR, dest, tag, comm); + } if (status != MPI_SUCCESS) { try { - XdmfError(XdmfError::FATAL, "Broadcast of Comm failed"); + XdmfError::message(XdmfError::FATAL, "Error: Failed to receive data"); } catch (XdmfError e) { throw e; @@ -542,170 +802,71 @@ XdmfDSMBuffer::BroadcastComm(int *comm, int root) } } -//redefined from H5FDBufferService - void -XdmfDSMBuffer::BufferServiceLoop(int *returnOpcode) +XdmfDSMBuffer::SendCommandHeader(int opcode, int dest, int address, int aLength, int comm) { - int op, status = XDMF_DSM_SUCCESS; - while (status == XDMF_DSM_SUCCESS) { + int status; + CommandMsg cmd; + memset(&cmd, 0, sizeof(CommandMsg)); + cmd.Opcode = opcode; + cmd.Source = this->Comm->GetId(); + cmd.Target = dest; + cmd.Address = address; + cmd.Length = aLength; + + if (comm == XDMF_DSM_INTRA_COMM) { + status = MPI_Send(&cmd, sizeof(CommandMsg), MPI_UNSIGNED_CHAR, dest, XDMF_DSM_COMMAND_TAG, static_cast(this->Comm)->GetIntraComm()); + } + else if (comm == XDMF_DSM_INTER_COMM) { + int interSource = 0; + MPI_Comm_rank(static_cast(this->Comm)->GetInterComm(), &interSource); + cmd.Source = interSource; + status = MPI_Send(&cmd, sizeof(CommandMsg), MPI_UNSIGNED_CHAR, dest, XDMF_DSM_COMMAND_TAG, static_cast(this->Comm)->GetInterComm()); + } + else { + // In this case the comm should be a pointer to an MPI_Comm object + status = MPI_Send(&cmd, sizeof(CommandMsg), MPI_UNSIGNED_CHAR, dest, XDMF_DSM_COMMAND_TAG, comm); + } + if (status != MPI_SUCCESS) { try { - status = this->BufferService(&op); + XdmfError::message(XdmfError::FATAL, "Error: Failed to send command header"); } catch (XdmfError e) { throw e; } - if (returnOpcode) *returnOpcode = op; - if (op == XDMF_DSM_OPCODE_DONE) { - break; - } } } - - -int -XdmfDSMBuffer::BufferService(int *returnOpcode) +void +XdmfDSMBuffer::SendData(int dest, char * data, int aLength, int tag, int aAddress, int comm) { - int opcode, who, status = XDMF_DSM_FAIL; - int aLength; - int address; - char *datap; - static int syncId = -1; - - if (this->CommChannel == XDMF_DSM_ANY_COMM) { - if (this->Comm->GetId() == 0) { - try { - this->ProbeCommandHeader(&this->CommChannel); - } - catch (XdmfError e) { - throw e; - } - } + int status; + if (comm == XDMF_DSM_INTRA_COMM) { + status = MPI_Send(data, aLength, MPI_UNSIGNED_CHAR, dest, tag, static_cast(this->Comm)->GetIntraComm()); + } + else if (comm == XDMF_DSM_INTER_COMM) { + status = MPI_Send(data, aLength, MPI_UNSIGNED_CHAR, dest, tag, static_cast(this->Comm)->GetInterComm()); + } + else { + status = MPI_Send(data, aLength, MPI_UNSIGNED_CHAR, dest, tag, comm); + } + if (status != MPI_SUCCESS) { try { - this->BroadcastComm(&this->CommChannel, 0); + XdmfError::message(XdmfError::FATAL, "Error: Failed to send data"); } catch (XdmfError e) { throw e; } } +} - - try { - this->ReceiveCommandHeader(&opcode, &who, &address, &aLength, this->CommChannel, syncId); - } - catch (XdmfError e) { - throw e; - } - - - - // Connection is an ID for client or server, - int communicatorId = this->CommChannel; - - switch(opcode) { - - // H5FD_DSM_OPCODE_PUT - case XDMF_DSM_OPCODE_PUT: - if (((unsigned int) aLength + address) > this->Length) { - try { - std::stringstream message; - message << "Length " << aLength << " too long for Address " << address << "\n" << - "Server Start = " << this->StartAddress << " End = " << this->EndAddress; - XdmfError::message(XdmfError::FATAL, message.str()); - } - catch (XdmfError e) { - throw e; - } - } - if ((datap = this->DataPointer) == NULL) { - try { - XdmfError::message(XdmfError::FATAL, "Null Data Pointer when trying to put data"); - } - catch (XdmfError e) { - throw e; - } - } - datap += address; - try { - this->ReceiveData(who, datap, aLength, XDMF_DSM_PUT_DATA_TAG, 0, this->CommChannel); - } - catch (XdmfError e) { - throw e; - } - break; - - // H5FD_DSM_OPCODE_GET - case XDMF_DSM_OPCODE_GET: - if (((unsigned int) aLength + address) > this->Length) { - try { - std::stringstream message; - message << "Length " << aLength << " too long for Address " << address << "\n" << - "Server Start = " << this->StartAddress << " End = " << this->EndAddress; - XdmfError::message(XdmfError::FATAL, message.str()); - } - catch (XdmfError e) { - throw e; - } - } - if ((datap = this->DataPointer) == NULL) { - try { - XdmfError::message(XdmfError::FATAL, "Null Data Pointer when trying to put data"); - } - catch (XdmfError e) { - throw e; - } - } - datap += address; - try { - this->SendData(who, datap, aLength, XDMF_DSM_GET_DATA_TAG, 0, this->CommChannel); - } - catch (XdmfError e) { - throw e; - } - break; - - // H5FD_DSM_LOCK_ACQUIRE - // Comes from client or server depending on communicator - case XDMF_DSM_LOCK_ACQUIRE: - // Currently unsupported - break; - - // H5FD_DSM_LOCK_RELEASE - // Comes from client or server depending on communicator - case XDMF_DSM_LOCK_RELEASE: - // Currently unsupported - break; - - // H5FD_DSM_OPCODE_DONE - // Always received on server - case XDMF_DSM_OPCODE_DONE: - break; - - // DEFAULT - default : - try { - std::stringstream message; - message << "Error: Unknown Opcode " << opcode; - XdmfError::message(XdmfError::FATAL, message.str()); - } - catch (XdmfError e) { - throw e; - } - } - - if (returnOpcode) *returnOpcode = opcode; - return(XDMF_DSM_SUCCESS); -} - - -void -XdmfDSMBuffer::SendDone() -{ +void +XdmfDSMBuffer::SendDone() +{ try { if (static_cast(this->Comm)->GetInterComm() == MPI_COMM_NULL) { - for (int i = this->StartServerId; i < this->EndServerId; ++i) { + for (int i = this->StartServerId; i <= this->EndServerId; ++i) { if (i != this->Comm->GetId()){ this->SendCommandHeader(XDMF_DSM_OPCODE_DONE, i, 0, 0, XDMF_DSM_INTRA_COMM); } @@ -713,7 +874,7 @@ XdmfDSMBuffer::SendDone() } else { - for (int i = this->StartServerId; i < this->EndServerId; ++i) { + for (int i = this->StartServerId; i <= this->EndServerId; ++i) { if (i != this->Comm->GetId()){ this->SendCommandHeader(XDMF_DSM_OPCODE_DONE, i, 0, 0, XDMF_DSM_INTER_COMM); } @@ -726,231 +887,98 @@ XdmfDSMBuffer::SendDone() } void -XdmfDSMBuffer::ProbeCommandHeader(int *comm) +XdmfDSMBuffer::SendInfo() { - // Used for finding a comm that has a waiting command, then sets the comm - int status = XDMF_DSM_FAIL; - MPI_Status signalStatus; + InfoMsg dsmInfo; + int status; - int flag; - MPI_Comm probeComm = static_cast(this->Comm)->GetIntraComm(); + memset(&dsmInfo, 0, sizeof(InfoMsg)); + dsmInfo.type = this->GetDsmType(); + dsmInfo.length = this->GetLength(); + dsmInfo.total_length = this->GetTotalLength(); + dsmInfo.block_length = this->GetBlockLength(); + dsmInfo.start_server_id = this->GetStartServerId(); + dsmInfo.end_server_id = this->GetEndServerId(); - // Spin until a message is found on one of the communicators - while (status != XDMF_DSM_SUCCESS) { - status = MPI_Iprobe(XDMF_DSM_ANY_SOURCE, XDMF_DSM_ANY_TAG, probeComm, &flag, &signalStatus); - if (status != MPI_SUCCESS) - { - try { - XdmfError::message(XdmfError::FATAL, "Error: Failed to probe for command header"); - } - catch (XdmfError e) { - throw e; - } - } - if (flag) { - status = XDMF_DSM_SUCCESS; - } - else { - if (static_cast(this->Comm)->GetInterComm() != MPI_COMM_NULL) { - if (probeComm == static_cast(this->Comm)->GetIntraComm()) { - probeComm = static_cast(this->Comm)->GetInterComm(); - } - else { - probeComm = static_cast(this->Comm)->GetIntraComm(); + int infoStatus = 3; + if (this->Comm->GetId() == 0) { + infoStatus = 2; } - } + + int groupInfoStatus[this->Comm->GetInterSize()]; + + MPI_Allgather(&infoStatus, 1, MPI_INT, &groupInfoStatus, 1, MPI_INT, this->Comm->GetInterComm()); + + int sendCore = 0; + + for (int i = 0; i < this->Comm->GetInterSize(); ++i) { + if (groupInfoStatus[i] == 2) { + sendCore = i; } } - if (probeComm == static_cast(this->Comm)->GetInterComm()) { - *comm = XDMF_DSM_INTER_COMM; - } - else - { - *comm = XDMF_DSM_INTRA_COMM; - } - probeComm = MPI_COMM_NULL; + status = MPI_Bcast(&dsmInfo, sizeof(InfoMsg), MPI_UNSIGNED_CHAR, sendCore, static_cast(this->Comm)->GetInterComm()); + if (status != MPI_SUCCESS) { + try { + XdmfError::message(XdmfError::FATAL, "Error: Failed to send info"); + } + catch (XdmfError e) { + throw e; + } + } } - -int -XdmfDSMBuffer::AddressToId(int Address) +void +XdmfDSMBuffer::SetBlockLength(long newBlock) { - int ServerId = XDMF_DSM_FAIL; + this->BlockLength = newBlock; +} - switch(this->DsmType) { - case XDMF_DSM_TYPE_UNIFORM : - case XDMF_DSM_TYPE_UNIFORM_RANGE : - // All Servers have same length - // This finds out which server the address provided starts on - ServerId = this->StartServerId + (Address / this->Length); - if(ServerId > this->EndServerId ){ - try { - std::stringstream message; - message << "ServerId " << ServerId << " for Address " << Address << " is larger than EndServerId " << this->EndServerId; - XdmfError::message(XdmfError::FATAL, message.str()); - } - catch (XdmfError e) { - throw e; - } - } - break; - default : - // Not Implemented - try { - std::stringstream message; - message << "DsmType " << this->DsmType << " not yet implemented"; - XdmfError::message(XdmfError::FATAL, message.str()); - } - catch (XdmfError e) { - throw e; - } - break; - } - return(ServerId); +void +XdmfDSMBuffer::SetComm(XdmfDSMCommMPI * newComm) +{ + this->Comm = newComm; } void -XdmfDSMBuffer::GetAddressRangeForId(int Id, int *Start, int *End){ - switch(this->DsmType) { - case XDMF_DSM_TYPE_UNIFORM : - case XDMF_DSM_TYPE_UNIFORM_RANGE : - // All Servers have same length - // Start index is equal to the id inside the servers times the length of the block per server - // It is the starting index of the server's data block relative to the entire block - *Start = (Id - this->StartServerId) * this->Length; - // End index is simply the start index + the length of the server's data block. - // The range produced is the start of the server's data block to its end. - *End = *Start + Length - 1; - break; - default : - // Not Implemented - try { - std::stringstream message; - message << "DsmType " << this->DsmType << " not yet implemented"; - XdmfError::message(XdmfError::FATAL, message.str()); - } - catch (XdmfError e) { - throw e; - } - break; - } +XdmfDSMBuffer::SetDsmType(int newDsmType) +{ + this->DsmType = newDsmType; } void -XdmfDSMBuffer::Get(long Address, long aLength, void *Data) +XdmfDSMBuffer::SetIsConnected(bool newStatus) { - int who, MyId = this->Comm->GetId(); - int astart, aend, len; - char *datap = (char *)Data; + IsConnected = newStatus; +} - // While there is length left - while(aLength) { - // Figure out what server core the address is located on - who = this->AddressToId(Address); - if(who == XDMF_DSM_FAIL){ - try { - XdmfError::message(XdmfError::FATAL, "Address Error"); - } - catch (XdmfError e) { - throw e; - } - } - // Get the start and end of the block listed - this->GetAddressRangeForId(who, &astart, &aend); - // Determine the amount of data to be written to that core - // Basically, it's how much data will fit from the starting point of the address to the end - len = std::min(aLength, aend - Address + 1); - // If the data is on the core running this code, then the put is simple - if(who == MyId){ - char *dp; - dp = this->DataPointer; - dp += Address - this->StartAddress; - memcpy(datap, dp, len); - } - else{ - // Otherwise send it to the appropriate core to deal with - int status; - int dataComm = XDMF_DSM_INTRA_COMM; - if (this->Comm->GetInterComm() != MPI_COMM_NULL) { - dataComm = XDMF_DSM_INTER_COMM; - } - try { - this->SendCommandHeader(XDMF_DSM_OPCODE_GET, who, Address - astart, len, dataComm); - } - catch (XdmfError e) { - throw e; - } - try { - this->ReceiveData(who, datap, len, XDMF_DSM_GET_DATA_TAG, Address - astart, dataComm); - } - catch (XdmfError e) { - throw e; - } - } - // Shift all the numbers by the length of the data written - // Until aLength = 0 - aLength -= len; - Address += len; - datap += len; - } +void +XdmfDSMBuffer::SetIsServer(bool newIsServer) +{ + this->IsServer = newIsServer; } void -XdmfDSMBuffer::Put(long Address, long aLength, const void *Data) +XdmfDSMBuffer::SetLength(long aLength) { - int who, MyId = this->Comm->GetId(); - int astart, aend, len; - char *datap = (char *)Data; + this->Length = aLength; + if (this->DataPointer) { + // Try to reallocate + // This should not be called in most cases + this->DataPointer = static_cast(realloc(this->DataPointer, this->Length*sizeof(char))); + } + else { +#ifdef _WIN32 + this->DataPointer = calloc(this->Length, sizeof(char)); +#else + posix_memalign((void **)(&this->DataPointer), getpagesize(), this->Length); + memset(this->DataPointer, 0, this->Length); +#endif + } - // While there is length left - while(aLength){ - // Figure out what server core the address is located on - who = this->AddressToId(Address); - if(who == XDMF_DSM_FAIL){ - try { - XdmfError::message(XdmfError::FATAL, "Address Error"); - } - catch (XdmfError e) { - throw e; - } - } - // Get the start and end of the block listed - this->GetAddressRangeForId(who, &astart, &aend); - // Determine the amount of data to be written to that core - // Basically, it's how much data will fit from the starting point of the address to the end - len = std::min(aLength, aend - Address + 1); - // If the data is on the core running this code, then the put is simple - if(who == MyId){ - char *dp; - dp = this->DataPointer; - dp += Address - this->StartAddress; - memcpy(dp, datap, len); - } - else{ - // Otherwise send it to the appropriate core to deal with - int status; - int dataComm = XDMF_DSM_INTRA_COMM; - if (this->Comm->GetInterComm() != MPI_COMM_NULL) { - dataComm = XDMF_DSM_INTER_COMM; - } - try { - this->SendCommandHeader(XDMF_DSM_OPCODE_PUT, who, Address - astart, len, dataComm); - } - catch (XdmfError e) { - throw e; - } - try { - this->SendData(who, datap, len, XDMF_DSM_PUT_DATA_TAG, Address - astart, dataComm); - } - catch (XdmfError e) { - throw e; - } - } - // Shift all the numbers by the length of the data written - // Until aLength = 0 - aLength -= len; - Address += len; - datap += len; + if (this->DataPointer == NULL) { + std::stringstream message; + message << "Allocation Failed, unable to allocate " << this->Length; + XdmfError::message(XdmfError::FATAL, message.str()); } } diff --git a/core/XdmfDSMBuffer.hpp b/core/XdmfDSMBuffer.hpp index 231421e8..3abccb88 100644 --- a/core/XdmfDSMBuffer.hpp +++ b/core/XdmfDSMBuffer.hpp @@ -87,6 +87,9 @@ #define XDMF_DSM_LOCK_ACQUIRE 0x03 #define XDMF_DSM_LOCK_RELEASE 0x05 +#define XDMF_DSM_ACCEPT 0x10 +#define XDMF_DSM_DISCONNECT 0x11 + #define XDMF_DSM_OPCODE_DONE 0xFF #define XDMF_DSM_SUCCESS 1 @@ -977,30 +980,44 @@ public: * @until cfree * @skipline exampleController * @until size-1 - * @skipline if - * @until { - * @skipline XdmfDSMBuffer - * @skipline exampleController - * @skipline readComm - * @until cfree - * @skipline if - * @until workerComm * @skip Section - * @skipline } + * @skipline id + * @until } + * @skipline numServersCores + * @until } + * @skipline else + * @until } * * Python * * @dontinclude XdmfExampleDSMNoThread.py * @skipline total * @until exampleWriter - * @skipline if - * @skipline exampleBuffer - * @skipline ServerIds - * @until (workerComm) + * @skip Section + * @skipline id + * @until stopDSM + * @skipline numServersCores + * @until ReceiveInfo * */ void ReceiveInfo(); + /** + * + * + * Example of use: + * + * C++ + * + * + * + * Python + * + * + * + */ + void SendAccept(unsigned int numConnects); + /** * Sends an integer as an acknowledgement to the specified core. * It is not advised to use this function manually. @@ -1178,32 +1195,30 @@ public: * @until cfree * @skipline exampleController * @until size-1 - * @skipline if - * @until { - * @skipline XdmfDSMBuffer - * @skipline exampleController - * @skipline readComm - * @until cfree - * @skipline if - * @until workerComm * @skip Section - * @skipline } + * @skipline id + * @until } + * @skipline numServersCores + * @until } + * @skipline else + * @until } * * Python * * @dontinclude XdmfExampleDSMNoThread.py * @skipline total * @until exampleWriter - * @skipline if - * @skipline exampleBuffer - * @skipline ServerIds - * @until (workerComm) + * @skip Section + * @skipline id + * @until stopDSM + * @skipline numServersCores + * @until ReceiveInfo * */ void SendInfo(); /** - * Sets the DSM type to the provided type. + * Sets the size of the blocks used in the data buffer. * * Example of use: * @@ -1218,7 +1233,7 @@ public: * @until { * @skipline XdmfDSMBuffer * @skipline exampleController - * @skipline SetDsmType + * @skipline SetBlockLength * @skip Section * @skipline } * @@ -1229,14 +1244,14 @@ public: * @until exampleWriter * @skipline if * @skipline exampleBuffer - * @skipline SetDsmType + * @skipline SetBlockLength * - * @param newDsmType The Dsm type that the buffer will be changed to + * @param newBlock The new block size to be used */ - void SetDsmType(int newDsmType); + void SetBlockLength(long newBlock); /** - * Sets the size of the blocks used in the data buffer. + * Sets the Comm to be used to facilitate the communications for the DSM * * Example of use: * @@ -1251,7 +1266,8 @@ public: * @until { * @skipline XdmfDSMBuffer * @skipline exampleController - * @skipline SetBlockLength + * @skipline XdmfDSMCommMPI + * @skipline SetComm * @skip Section * @skipline } * @@ -1262,14 +1278,15 @@ public: * @until exampleWriter * @skipline if * @skipline exampleBuffer - * @skipline SetBlockLength + * @skipline exampleDSMComm + * @skipline SetComm * - * @param newBlock The new block size to be used + * @param newComm The communicator that is to be used by the DSM */ - void SetBlockLength(long newBlock); + void SetComm(XdmfDSMCommMPI * newComm); /** - * Sets the Comm to be used to facilitate the communications for the DSM + * Sets the DSM type to the provided type. * * Example of use: * @@ -1284,8 +1301,7 @@ public: * @until { * @skipline XdmfDSMBuffer * @skipline exampleController - * @skipline XdmfDSMCommMPI - * @skipline SetComm + * @skipline SetDsmType * @skip Section * @skipline } * @@ -1296,12 +1312,11 @@ public: * @until exampleWriter * @skipline if * @skipline exampleBuffer - * @skipline exampleDSMComm - * @skipline SetComm + * @skipline SetDsmType * - * @param newComm The communicator that is to be used by the DSM + * @param newDsmType The Dsm type that the buffer will be changed to */ - void SetComm(XdmfDSMCommMPI * newComm); + void SetDsmType(int newDsmType); /** * Sets the Buffer's connection status. Used if the XdmfDSMCommMPI is connected or disconnected manually. diff --git a/core/XdmfDSMCommMPI.cpp b/core/XdmfDSMCommMPI.cpp index 1131e7fe..f8b6e9c3 100644 --- a/core/XdmfDSMCommMPI.cpp +++ b/core/XdmfDSMCommMPI.cpp @@ -55,6 +55,8 @@ #include #include #include +#include +#include XdmfDSMCommMPI::XdmfDSMCommMPI() { @@ -62,8 +64,10 @@ XdmfDSMCommMPI::XdmfDSMCommMPI() Id = -1; IntraSize = -1; InterComm = MPI_COMM_NULL; + InterId = -1; InterSize = -1; - SetDsmMasterHostName(""); + SetDsmPortName(""); + DsmFileName = "dsmconnect.cfg"; InterCommType = XDMF_DSM_COMM_MPI; } @@ -94,75 +98,82 @@ XdmfDSMCommMPI::~XdmfDSMCommMPI() } void -XdmfDSMCommMPI::SetDsmMasterHostName(const char *hostName) +XdmfDSMCommMPI::Accept(unsigned int numConnections) { - strcpy(DsmMasterHostName, hostName); -} - -char * -XdmfDSMCommMPI::GetDsmMasterHostName() -{ - return DsmMasterHostName; -} - -int -XdmfDSMCommMPI::GetId() -{ - return this->Id; -} - -int -XdmfDSMCommMPI::GetIntraSize() -{ - return this->IntraSize; -} - -int -XdmfDSMCommMPI::GetInterSize() -{ - return this->InterSize; -} - -int -XdmfDSMCommMPI::GetInterCommType() -{ - return this->InterCommType; -} - -void -XdmfDSMCommMPI::Init() -{ - int size, rank; - if (MPI_Comm_size(this->IntraComm, &size) != MPI_SUCCESS) { - try { - XdmfError::message(XdmfError::FATAL, "Failed to initialize size"); - } - catch (XdmfError e) { - throw e; - } - } - if (MPI_Comm_rank(this->IntraComm, &rank) != MPI_SUCCESS) { - try { - XdmfError::message(XdmfError::FATAL, "Failed to initialize rank"); + while (numConnections > 0) { + if (InterComm == MPI_COMM_NULL) { + // If there is no InterComm, then accept from IntraComm and merge into InterComm + MPI_Comm tempComm; + int status = MPI_Comm_accept(DsmPortName, MPI_INFO_NULL, 0, IntraComm, &tempComm); + if (status != MPI_SUCCESS) { + try { + std::string message = "Failed to accept port "; + message = message + DsmPortName; + XdmfError::message(XdmfError::FATAL, message); + } + catch (XdmfError e) { + throw e; + } + } + // False is specified for high so that the index of the cores doesn't change + status = MPI_Intercomm_merge(tempComm, false, &InterComm); + if (status != MPI_SUCCESS) { + try { + XdmfError::message(XdmfError::FATAL, "Failed to merge intercomm"); + } + catch (XdmfError e) { + throw e; + } + } + else { + MPI_Comm_rank(InterComm, &InterId); + MPI_Comm_size(InterComm, &InterSize); + } } - catch (XdmfError e) { - throw e; + else { + // If there is an InterComm, accept into the InterComm and merge + MPI_Comm tempComm; + int status = MPI_Comm_accept(DsmPortName, MPI_INFO_NULL, 0, InterComm, &tempComm); + if (status != MPI_SUCCESS) { + try { + std::string message = "Failed to accept port "; + message = message + DsmPortName; + XdmfError::message(XdmfError::FATAL, message); + } + catch (XdmfError e) { + throw e; + } + } + // False is specified for high so that the index of the cores doesn't change + status = MPI_Intercomm_merge(tempComm, false, &InterComm); + if (status != MPI_SUCCESS) { + try { + XdmfError::message(XdmfError::FATAL, "Failed to merge InterComm"); + } + catch (XdmfError e) { + throw e; + } + } + else { + MPI_Comm_rank(InterComm, &InterId); + MPI_Comm_size(InterComm, &InterSize); + } } + --numConnections; + MPI_Bcast(&numConnections, 1, MPI_INT, 0, InterComm); } - - this->Id = rank; - this->IntraSize = size; } void -XdmfDSMCommMPI::OpenPort() +XdmfDSMCommMPI::ClosePort() { if (Id == 0) { - int status = MPI_Open_port(MPI_INFO_NULL, DsmMasterHostName); + int status; + status = MPI_Open_port(MPI_INFO_NULL, DsmPortName); if (status != MPI_SUCCESS) { try { - std::string message = "Failed to open port "; - message = message + DsmMasterHostName; + std::string message = "Failed to close port "; + message = message + DsmPortName; XdmfError::message(XdmfError::FATAL, message); } catch (XdmfError e) { @@ -172,72 +183,70 @@ XdmfDSMCommMPI::OpenPort() } } -void -XdmfDSMCommMPI::ClosePort() +int +XdmfDSMCommMPI::Connect() { - if (Id == 0) { - int status; - status = MPI_Open_port(MPI_INFO_NULL, DsmMasterHostName); + if (InterComm == MPI_COMM_NULL) { + MPI_Comm tempComm; + MPI_Errhandler_set(IntraComm, MPI_ERRORS_RETURN); + int status = MPI_Comm_connect(DsmPortName, MPI_INFO_NULL, 0, IntraComm, &tempComm); + MPI_Errhandler_set(IntraComm, MPI_ERRORS_ARE_FATAL); if (status != MPI_SUCCESS) { try { - std::string message = "Failed to close port "; - message = message + DsmMasterHostName; + std::string message = "Failed to connect to port "; + message = message + DsmPortName; XdmfError::message(XdmfError::FATAL, message); } catch (XdmfError e) { throw e; } } - } -} - -void -XdmfDSMCommMPI::Accept() -{ - int status = MPI_Comm_accept(DsmMasterHostName, MPI_INFO_NULL, 0, IntraComm, &InterComm); - if (status != MPI_SUCCESS) { - try { - std::string message = "Failed to accept port "; - message = message + DsmMasterHostName; - XdmfError::message(XdmfError::FATAL, message); + status = MPI_Intercomm_merge(tempComm, true, &InterComm); + if (status != MPI_SUCCESS) { + try { + XdmfError::message(XdmfError::FATAL, "Failed to merge InterComm"); + } + catch (XdmfError e) { + throw e; + } } - catch (XdmfError e) { - throw e; + else { + status = MPI_Comm_rank(InterComm, &InterId); + status = MPI_Comm_size(InterComm, &InterSize); } } else { - MPI_Comm_remote_size(InterComm, &InterSize); - } -} - -int -XdmfDSMCommMPI::Connect() -{ - if (InterComm != MPI_COMM_NULL) { - // If the intercomm already exists, no need to connect - // If you want to reset the intercomm, set it to MPI_COMM_NULL before calling this - // using either SetInterComm or Disconnect - return MPI_SUCCESS; - } - else { - MPI_Errhandler_set(IntraComm, MPI_ERRORS_RETURN); - int status = MPI_Comm_connect(DsmMasterHostName, MPI_INFO_NULL, 0, IntraComm, &InterComm); - MPI_Errhandler_set(IntraComm, MPI_ERRORS_ARE_FATAL); + MPI_Comm tempComm; + MPI_Errhandler_set(InterComm, MPI_ERRORS_RETURN); + int status = MPI_Comm_connect(DsmPortName, MPI_INFO_NULL, 0, InterComm, &tempComm); + MPI_Errhandler_set(InterComm, MPI_ERRORS_ARE_FATAL); if (status != MPI_SUCCESS) { try { std::string message = "Failed to connect to port "; - message = message + DsmMasterHostName; + message = message + DsmPortName; XdmfError::message(XdmfError::FATAL, message); } catch (XdmfError e) { throw e; } } + status = MPI_Intercomm_merge(tempComm, true, &InterComm); + if (status != MPI_SUCCESS) { + try { + XdmfError::message(XdmfError::FATAL, "Failed to merge InterComm"); + } + catch (XdmfError e) { + throw e; + } + } else { - status = MPI_Comm_remote_size(InterComm, &InterSize); - return MPI_SUCCESS; + status = MPI_Comm_rank(InterComm, &InterId); + status = MPI_Comm_size(InterComm, &InterSize); } } + int numAccepts = 0; + MPI_Bcast(&numAccepts, 1, MPI_INT, 0, InterComm); + Accept(numAccepts); return MPI_SUCCESS; } @@ -319,26 +328,147 @@ XdmfDSMCommMPI::DupInterComm(MPI_Comm comm) } } else { + status = MPI_Comm_rank(InterComm, &InterId); status = MPI_Comm_size(InterComm, &InterSize); - if (status != MPI_SUCCESS) { - MPI_Comm_remote_size(InterComm, &InterSize); - } } } else { + InterId = -1; InterSize = -1; } } } +std::string +XdmfDSMCommMPI::GetDsmFileName() +{ + return DsmFileName; +} + +char * +XdmfDSMCommMPI::GetDsmPortName() +{ + return DsmPortName; +} + +int +XdmfDSMCommMPI::GetId() +{ + return this->Id; +} + MPI_Comm XdmfDSMCommMPI::GetInterComm() { return InterComm; } +int +XdmfDSMCommMPI::GetInterCommType() +{ + return this->InterCommType; +} + +int +XdmfDSMCommMPI::GetInterId() +{ + return this->InterId; +} + +int +XdmfDSMCommMPI::GetInterSize() +{ + return this->InterSize; +} + MPI_Comm XdmfDSMCommMPI::GetIntraComm() { return IntraComm; } + +int +XdmfDSMCommMPI::GetIntraSize() +{ + return this->IntraSize; +} + +void +XdmfDSMCommMPI::Init() +{ + int size, rank; + if (MPI_Comm_size(this->IntraComm, &size) != MPI_SUCCESS) { + try { + XdmfError::message(XdmfError::FATAL, "Failed to initialize size"); + } + catch (XdmfError e) { + throw e; + } + } + if (MPI_Comm_rank(this->IntraComm, &rank) != MPI_SUCCESS) { + try { + XdmfError::message(XdmfError::FATAL, "Failed to initialize rank"); + } + catch (XdmfError e) { + throw e; + } + } + + this->Id = rank; + this->IntraSize = size; +} + +void +XdmfDSMCommMPI::OpenPort() +{ + if (Id == 0) { + int status = MPI_Open_port(MPI_INFO_NULL, DsmPortName); + if (status != MPI_SUCCESS) { + try { + std::string message = "Failed to open port "; + message = message + DsmPortName; + XdmfError::message(XdmfError::FATAL, message); + } + catch (XdmfError e) { + throw e; + } + } + std::ofstream connectFile (DsmFileName.c_str()); + if (connectFile.is_open()) { + connectFile << DsmPortName; + connectFile.close(); + } + else { + try { + XdmfError::message(XdmfError::FATAL, "Failed to write port to file"); + } + catch (XdmfError e) { + throw e; + } + } + } + MPI_Bcast(DsmPortName, MPI_MAX_PORT_NAME, MPI_CHAR, 0, IntraComm); +} + +void +XdmfDSMCommMPI::ReadDsmPortName() +{ + std::ifstream connectFile(DsmFileName.c_str()); + std::string connectLine; + if (connectFile.is_open()) { + getline(connectFile, connectLine); + } + strcpy(DsmPortName, connectLine.c_str()); +} + +void +XdmfDSMCommMPI::SetDsmFileName(std::string filename) +{ + DsmFileName = filename; +} + +void +XdmfDSMCommMPI::SetDsmPortName(const char *hostName) +{ + strcpy(DsmPortName, hostName); +} diff --git a/core/XdmfDSMCommMPI.hpp b/core/XdmfDSMCommMPI.hpp index 2d85e9ea..3d556299 100644 --- a/core/XdmfDSMCommMPI.hpp +++ b/core/XdmfDSMCommMPI.hpp @@ -41,6 +41,8 @@ #include +#include + /** * @brief Holds communicators for interacting with H5FD dsm. * @@ -56,7 +58,7 @@ public: ~XdmfDSMCommMPI(); /** - * Accepts connections to the port currently named by DsmMasterHostName. Called on server side, accepts from core 0. + * Accepts connections to the port currently named by DsmPortName. Called on server side, accepts from core 0. * * Example of use: * @@ -92,10 +94,10 @@ public: * @until ClosePort * */ - void Accept(); + void Accept(unsigned int numConnections = 1); /** - * Closes the port currently named by DsmMasterHostName. + * Closes the port currently named by DsmPortName. * * Example of use: * @@ -134,7 +136,7 @@ public: void ClosePort(); /** - * If core ID is 0 then attempts to connect to the port currently named by DsmMasterHostName + * If core ID is 0 then attempts to connect to the port currently named by DsmPortName * * Example of use: * @@ -287,6 +289,11 @@ public: */ void DupInterComm(MPI_Comm comm); + /** + * + */ + std::string GetDsmFileName(); + /** * Gets the port name that will be connected to when Connect/Accept is called. * @@ -325,7 +332,7 @@ public: * * @return a pointer to the character string that specifies the port */ - char * GetDsmMasterHostName(); + char * GetDsmPortName(); /** * Gets the Id with regards to the IntraComm. @@ -431,6 +438,11 @@ public: */ int GetInterCommType(); + /** + * + */ + int GetInterId(); + /** * Gets the number of cores contained in the InterComm. * @@ -571,7 +583,7 @@ public: void Init(); /** - * Opens a port and stores the port name in DsmMasterHostName. + * Opens a port and stores the port name in DsmPortName. * * Example of use: * @@ -609,6 +621,16 @@ public: */ void OpenPort(); + /** + * + */ + void ReadDsmPortName(); + + /** + * + */ + void SetDsmFileName(std::string filename); + /** * Sets the port name that will be connected to when Connect/Accept is called. * Data is copied, so the provided string is not modified. @@ -650,7 +672,7 @@ public: * * @param hostName a pointer to the character string that specifies the port */ - void SetDsmMasterHostName(const char *hostName); + void SetDsmPortName(const char *hostName); protected: @@ -660,9 +682,11 @@ private: int Id; int IntraSize; MPI_Comm InterComm; + int InterId; int InterSize; int InterCommType; - char DsmMasterHostName[MPI_MAX_PORT_NAME]; + char DsmPortName[MPI_MAX_PORT_NAME]; + std::string DsmFileName; }; #endif /* XDMFDSMCOMMMPI_HPP_ */ diff --git a/core/XdmfDSMDriver.cpp b/core/XdmfDSMDriver.cpp index a5e43915..56d6368e 100644 --- a/core/XdmfDSMDriver.cpp +++ b/core/XdmfDSMDriver.cpp @@ -1195,6 +1195,7 @@ xdmf_dsm_update_entry(haddr_t start, haddr_t end) entry.start = start; entry.end = end; + addr = (int) (dsmBuffer->GetTotalLength() - sizeof(XdmfDSMEntry) - 1); // Do not send anything if the end of the file is 0 diff --git a/core/XdmfDSMManager.cpp b/core/XdmfDSMManager.cpp index 706420fd..3c9667ce 100644 --- a/core/XdmfDSMManager.cpp +++ b/core/XdmfDSMManager.cpp @@ -77,134 +77,36 @@ XdmfDSMManager::~XdmfDSMManager() this->Destroy(); } -XdmfDSMBuffer * -XdmfDSMManager::GetDsmBuffer() -{ - return this->DsmBuffer; -} - void -XdmfDSMManager::SetDsmBuffer(XdmfDSMBuffer * newBuffer) -{ - this->DsmBuffer = newBuffer; -} - -int -XdmfDSMManager::GetUpdatePiece() -{ - return this->UpdatePiece; -} - -int -XdmfDSMManager::GetUpdateNumPieces() -{ - return this->UpdateNumPieces; -} - -MPI_Comm -XdmfDSMManager::GetMpiComm() +XdmfDSMManager::Connect(bool persist) { - return this->MpiComm; -} + int status; -void -XdmfDSMManager::SetMpiComm(MPI_Comm comm) -{ - if (comm != this->MpiComm) { - this->MpiComm = comm; - if (this->MpiComm != MPI_COMM_NULL) { - MPI_Comm_size(this->MpiComm, &this->UpdateNumPieces); - MPI_Comm_rank(this->MpiComm, &this->UpdatePiece); + do { + try { + status = this->DsmBuffer->GetComm()->Connect(); } - } -} - -void -XdmfDSMManager::SetLocalBufferSizeMBytes(unsigned int newSize) -{ - this->LocalBufferSizeMBytes = newSize; -} - -unsigned int -XdmfDSMManager::GetLocalBufferSizeMBytes() -{ - return this->LocalBufferSizeMBytes; -} - -void -XdmfDSMManager::SetIsServer(bool newStatus) -{ - this->IsServer = newStatus; -} - -bool -XdmfDSMManager::GetIsServer() -{ - return this->IsServer; -} - -void -XdmfDSMManager::SetDsmType(int newType) -{ - this->DsmType = newType; -} - -int -XdmfDSMManager::GetDsmType() -{ - return this->DsmType; -} - -void -XdmfDSMManager::SetBlockLength(long newSize) -{ - this->BlockLength = newSize; -} - -long -XdmfDSMManager::GetBlockLength() -{ - return this->BlockLength; -} - -void -XdmfDSMManager::SetInterCommType(int newType) -{ - this->InterCommType = newType; -} - -int -XdmfDSMManager::GetInterCommType() -{ - return this->InterCommType; -} - -bool -XdmfDSMManager::GetIsConnected() -{ - if (this->DsmBuffer) { - return this->DsmBuffer->GetIsConnected(); - } - else { - return false; - } -} - -void -XdmfDSMManager::Destroy() -{ - // Watch out that all processes have empty message queues - // Should be already done during the disconnection - if (this->DsmBuffer) { - delete this->DsmBuffer; - this->DsmBuffer = NULL; - // Will be replaced by an Xdmf version - // H5FD_dsm_set_manager(NULL); - } - if (this->DsmComm) { - delete this->DsmComm; - this->DsmComm = NULL; - } + catch (XdmfError e) { + throw e; + } + if (status == MPI_SUCCESS) { + dynamic_cast (this->DsmBuffer)->SetIsConnected(true); + try { + this->DsmBuffer->ReceiveInfo(); + } + catch (XdmfError e) { + throw e; + } + } + else { +#ifdef _WIN32 + Sleep(1000); + // Since windows has a different sleep command +#else + sleep(1); +#endif + } + } while (persist && (status != MPI_SUCCESS)); } void @@ -261,38 +163,20 @@ XdmfDSMManager::Create(int startId, int endId) } } - void -XdmfDSMManager::Connect(bool persist) +XdmfDSMManager::Destroy() { - int status; - - if (!(dynamic_cast (this->DsmBuffer)->GetIsConnected())) { - do { - try { - status = this->DsmBuffer->GetComm()->Connect(); - } - catch (XdmfError e) { - throw e; - } - if (status == MPI_SUCCESS) { - dynamic_cast (this->DsmBuffer)->SetIsConnected(true); - try { - this->DsmBuffer->ReceiveInfo(); - } - catch (XdmfError e) { - throw e; - } - } - else { -#ifdef _WIN32 - Sleep(1000); - // Since windows has a different sleep command -#else - sleep(1); -#endif - } - } while (persist && (status != MPI_SUCCESS)); + // Watch out that all processes have empty message queues + // Should be already done during the disconnection + if (this->DsmBuffer) { + delete this->DsmBuffer; + this->DsmBuffer = NULL; + // Will be replaced by an Xdmf version + // H5FD_dsm_set_manager(NULL); + } + if (this->DsmComm) { + delete this->DsmComm; + this->DsmComm = NULL; } } @@ -308,3 +192,116 @@ XdmfDSMManager::Disconnect() } dynamic_cast (this->DsmBuffer)->SetIsConnected(false); } + +long +XdmfDSMManager::GetBlockLength() +{ + return this->BlockLength; +} + +XdmfDSMBuffer * +XdmfDSMManager::GetDsmBuffer() +{ + return this->DsmBuffer; +} + +int +XdmfDSMManager::GetDsmType() +{ + return this->DsmType; +} + +int +XdmfDSMManager::GetInterCommType() +{ + return this->InterCommType; +} + +bool +XdmfDSMManager::GetIsConnected() +{ + if (this->DsmBuffer) { + return this->DsmBuffer->GetIsConnected(); + } + else { + return false; + } +} + +bool +XdmfDSMManager::GetIsServer() +{ + return this->IsServer; +} + +unsigned int +XdmfDSMManager::GetLocalBufferSizeMBytes() +{ + return this->LocalBufferSizeMBytes; +} + +MPI_Comm +XdmfDSMManager::GetMpiComm() +{ + return this->MpiComm; +} + +int +XdmfDSMManager::GetUpdatePiece() +{ + return this->UpdatePiece; +} + +int +XdmfDSMManager::GetUpdateNumPieces() +{ + return this->UpdateNumPieces; +} + +void +XdmfDSMManager::SetBlockLength(long newSize) +{ + this->BlockLength = newSize; +} + +void +XdmfDSMManager::SetDsmBuffer(XdmfDSMBuffer * newBuffer) +{ + this->DsmBuffer = newBuffer; +} + +void +XdmfDSMManager::SetDsmType(int newType) +{ + this->DsmType = newType; +} + +void +XdmfDSMManager::SetIsServer(bool newStatus) +{ + this->IsServer = newStatus; +} + +void +XdmfDSMManager::SetInterCommType(int newType) +{ + this->InterCommType = newType; +} + +void +XdmfDSMManager::SetLocalBufferSizeMBytes(unsigned int newSize) +{ + this->LocalBufferSizeMBytes = newSize; +} + +void +XdmfDSMManager::SetMpiComm(MPI_Comm comm) +{ + if (comm != this->MpiComm) { + this->MpiComm = comm; + if (this->MpiComm != MPI_COMM_NULL) { + MPI_Comm_size(this->MpiComm, &this->UpdateNumPieces); + MPI_Comm_rank(this->MpiComm, &this->UpdatePiece); + } + } +} diff --git a/core/XdmfDSMManager.hpp b/core/XdmfDSMManager.hpp index 740f9212..01249765 100644 --- a/core/XdmfDSMManager.hpp +++ b/core/XdmfDSMManager.hpp @@ -89,6 +89,8 @@ public: * @until size-1 * @skipline if * @until { + * @skipline XdmfDSMManager + * @skipline exampleController * @skipline XdmfDSMBuffer * @skipline exampleController * @skipline XdmfDSMCommMPI @@ -108,6 +110,7 @@ public: * @skipline total * @until exampleWriter * @skipline if + * @skipline exampleManager * @skipline exampleBuffer * @skipline exampleDSMComm * @skipline connectingGroup @@ -198,6 +201,8 @@ public: * @until size-1 * @skipline if * @until { + * @skipline XdmfDSMManager + * @skipline exampleController * @skipline XdmfDSMBuffer * @skipline exampleController * @skipline XdmfDSMCommMPI @@ -217,6 +222,7 @@ public: * @skipline total * @until exampleWriter * @skipline if + * @skipline exampleManager * @skipline exampleBuffer * @skipline exampleDSMComm * @skipline connectingGroup @@ -423,7 +429,7 @@ public: bool GetIsServer(); /** - * Gets the MpiComm that the manager is currently using. + * Gets the maximum size of the local buffer on server cores. * * Example of use: * @@ -437,7 +443,7 @@ public: * @until { * @skipline exampleManager * @skipline exampleWriter - * @skipline exampleManagerComm + * @skipline MBytes * @skip Section * @skipline } * @@ -448,14 +454,14 @@ public: * @until exampleWriter * @skipline if * @skipline exampleManager - * @skipline exampleManagerComm + * @skipline exampleBufferSize * - * @return The MpiComm that the manager is currently using + * @return the maximum size of the data buffer on server cores */ - MPI_Comm GetMpiComm(); + unsigned int GetLocalBufferSizeMBytes(); /** - * Gets the maximum size of the local buffer on server cores. + * Gets the MpiComm that the manager is currently using. * * Example of use: * @@ -469,7 +475,7 @@ public: * @until { * @skipline exampleManager * @skipline exampleWriter - * @skipline MBytes + * @skipline exampleManagerComm * @skip Section * @skipline } * @@ -480,11 +486,11 @@ public: * @until exampleWriter * @skipline if * @skipline exampleManager - * @skipline exampleBufferSize + * @skipline exampleManagerComm * - * @return the maximum size of the data buffer on server cores + * @return The MpiComm that the manager is currently using */ - unsigned int GetLocalBufferSizeMBytes(); + MPI_Comm GetMpiComm(); /** * Gets the id of the core with regards to the MpiComm diff --git a/core/XdmfError.hpp b/core/XdmfError.hpp index 7a8b4d94..9fc49986 100644 --- a/core/XdmfError.hpp +++ b/core/XdmfError.hpp @@ -20,14 +20,14 @@ public: * C++ * * @dontinclude ExampleXdmfError.cpp - * @skipline DEBUG + * @skipline //#initialization + * @until //#initialization * * Python: * * @dontinclude XdmfExampleError.py - * @skip exampleError - * @skipline try - * @until setLevel + * @skipline #//initialization + * @until #//initialization * * @param level the error level of the exception being constructed * @param message the message to be attached to the exception @@ -44,18 +44,16 @@ public: * C++ * * @dontinclude ExampleXdmfError.cpp - * @skipline try - * @until catch - * @skipline { - * @skipline setLevel - * @skipline } + * @skipline //#initialization + * @until //#initialization + * @skipline //#setLevel + * @until //#setLevel * * Python: * * @dontinclude XdmfExampleError.py - * @skip exampleError - * @skipline try - * @until setLevel + * @skipline #//setLevel + * @until #//setLevel * * @param l the new level of the exception */ @@ -69,18 +67,16 @@ public: * C++ * * @dontinclude ExampleXdmfError.cpp - * @skipline try - * @until catch - * @skipline { - * @skipline getLevel - * @skipline } + * @skipline //#initialization + * @until //#initialization + * @skipline //#getLevel + * @until //#getLevel * * Python: * * @dontinclude XdmfExampleError.py - * @skip exampleError - * @skipline try - * @until getLevel + * @skipline #//getLevel + * @until #//getLevel * * @return the error level of the exception */ @@ -94,12 +90,16 @@ public: * C++ * * @dontinclude ExampleXdmfError.cpp - * @skipline setLevelLimit + * @skipline //#initialization + * @until //#initialization + * @skipline //#setLevelLimit + * @until //#setLevelLimit * * Python * * @dontinclude XdmfExampleError.py - * @skipline setLevelLimit + * @skipline #//setLevelLimit + * @until #//setLevelLimit * * @param l the cutoff level for sending exceptions via message */ @@ -113,12 +113,16 @@ public: * C++ * * @dontinclude ExampleXdmfError.cpp - * @skipline getLevelLimit + * @skipline //#initialization + * @until //#initialization + * @skipline //#getLevelLimit + * @until //#getLevelLimit * * Python * * @dontinclude XdmfExampleError.py - * @skipline getLevelLimit + * @skipline #//getLevelLimit + * @until #//getLevelLimit * * @return gets the cuttof level for sending exceptions via message */ @@ -134,17 +138,16 @@ public: * C++ * * @dontinclude ExampleXdmfError.cpp - * @skipline try - * @until catch - * @skipline { - * @skipline what - * @skipline } + * @skipline //#initialization + * @until //#initialization + * @skipline //#message + * @until //#message * * Python: Generates a RuntimeError instead of an XdmfError in Python * * @dontinclude XdmfExampleError.py - * @skipline try - * @until print + * @skipline #//message + * @until #//message * * @param l the level of the error to be generated * @param msg the message to be associated with the error generated and printed out @@ -159,7 +162,10 @@ public: * C++ * * @dontinclude ExampleXdmfError.cpp - * @skipline setBuffer + * @skipline //#initialization + * @until //#initialization + * @skipline //#setBuffer + * @until //#setBuffer * * Python: Not supported in Python * @@ -175,18 +181,16 @@ public: * C++ * * @dontinclude ExampleXdmfError.cpp - * @skipline try - * @until catch - * @skipline { - * @skipline what - * @skipline } + * @skipline //#initialization + * @until //#initialization + * @skipline //#what + * @until //#what * * Python * * @dontinclude XdmfExampleError.py - * @skip exampleError - * @skipline try - * @until what + * @skipline #//what + * @until #//what * * @return the message associated with the exception */ diff --git a/core/XdmfHDF5Controller.cpp b/core/XdmfHDF5Controller.cpp index 9f91b146..e2d4e8ae 100644 --- a/core/XdmfHDF5Controller.cpp +++ b/core/XdmfHDF5Controller.cpp @@ -170,9 +170,11 @@ XdmfHDF5Controller::read(XdmfArray * const array, const int fapl) if(numVals != array->getSize()) { try { + std::stringstream errOut; + errOut << "Number of values in hdf5 dataset (" << numVals; + errOut << ")\ndoes not match allocated size in XdmfArray (" << array->getSize() << ")."; XdmfError::message(XdmfError::FATAL, - "Number of values in hdf5 dataset does not match " - "allocated size in XdmfArray."); + errOut.str()); } catch (XdmfError e) { throw e; diff --git a/core/XdmfHDF5ControllerDSM.cpp b/core/XdmfHDF5ControllerDSM.cpp index 8dc07aac..6bada26e 100644 --- a/core/XdmfHDF5ControllerDSM.cpp +++ b/core/XdmfHDF5ControllerDSM.cpp @@ -86,9 +86,7 @@ XdmfHDF5ControllerDSM::New(const std::string & hdf5FilePath, const std::vector & stride, const std::vector & dimensions, const std::vector & datspaceDimensions, - XdmfDSMBuffer * const dsmBuffer, - int startCoreIndex, - int endCoreIndex) + XdmfDSMBuffer * const dsmBuffer) { shared_ptr p(new XdmfHDF5ControllerDSM(hdf5FilePath, @@ -98,9 +96,7 @@ XdmfHDF5ControllerDSM::New(const std::string & hdf5FilePath, stride, dimensions, datspaceDimensions, - dsmBuffer, - startCoreIndex, - endCoreIndex)); + dsmBuffer)); return p; } @@ -151,13 +147,7 @@ XdmfHDF5ControllerDSM::XdmfHDF5ControllerDSM(const std::string & hdf5FilePath, mDSMBuffer(dsmBuffer), mDSMServerBuffer(NULL), mDSMServerManager(NULL), - mGroupComm(MPI_COMM_NULL), - mServerComm(MPI_COMM_NULL), mWorkerComm(MPI_COMM_NULL), - mStartCoreIndex(-1), - mEndCoreIndex(-1), - mRank(-1), - mGroupSize(-1), mServerMode(false) { } @@ -180,13 +170,7 @@ XdmfHDF5ControllerDSM::XdmfHDF5ControllerDSM(const std::string & hdf5FilePath, dataspaceDimensions), mDSMServerBuffer(NULL), mDSMServerManager(NULL), - mGroupComm(MPI_COMM_NULL), - mServerComm(MPI_COMM_NULL), mWorkerComm(MPI_COMM_NULL), - mStartCoreIndex(-1), - mEndCoreIndex(-1), - mRank(-1), - mGroupSize(-1), mServerMode(false) { @@ -213,9 +197,7 @@ XdmfHDF5ControllerDSM::XdmfHDF5ControllerDSM(const std::string & hdf5FilePath, const std::vector & stride, const std::vector & dimensions, const std::vector & dataspaceDimensions, - XdmfDSMBuffer * const dsmBuffer, - int startCoreIndex, - int endCoreIndex) : + XdmfDSMBuffer * const dsmBuffer) : XdmfHDF5Controller(hdf5FilePath, dataSetPath, type, @@ -227,20 +209,20 @@ XdmfHDF5ControllerDSM::XdmfHDF5ControllerDSM(const std::string & hdf5FilePath, mDSMBuffer(NULL), mDSMServerBuffer(dsmBuffer), mDSMServerManager(NULL), - mStartCoreIndex(startCoreIndex), - mEndCoreIndex(endCoreIndex), mServerMode(true) { - mGroupComm = mDSMServerBuffer->GetComm()->GetInterComm(); - MPI_Comm_rank(mGroupComm, &mRank); - MPI_Comm_size(mGroupComm, &mGroupSize); - if (mRank >=mStartCoreIndex && mRank <=mEndCoreIndex) { - mServerComm = mDSMServerBuffer->GetComm()->GetIntraComm(); - mWorkerComm = MPI_COMM_NULL; + mWorkerComm = mDSMServerBuffer->GetComm()->GetIntraComm(); + if (xdmf_dsm_get_manager() == NULL) { + mDSMServerManager = new XdmfDSMManager(); + mDSMServerManager->SetLocalBufferSizeMBytes(mDSMServerBuffer->GetLength()); + mDSMServerManager->SetInterCommType(H5FD_DSM_COMM_MPI); + mDSMServerManager->SetIsServer(false); + mDSMServerManager->SetMpiComm(mDSMServerBuffer->GetComm()->GetIntraComm()); + mDSMServerManager->SetDsmBuffer(mDSMServerBuffer); + XDMF_dsm_set_manager(mDSMServerManager); } else { - mServerComm = MPI_COMM_NULL; - mWorkerComm = mDSMServerBuffer->GetComm()->GetIntraComm(); + static_cast(xdmf_dsm_get_manager())->SetDsmBuffer(mDSMServerBuffer); } } @@ -267,12 +249,18 @@ XdmfHDF5ControllerDSM::XdmfHDF5ControllerDSM(const std::string & hdf5FilePath, mServerMode(true) { + + int rank, size; + + MPI_Comm_size(comm, &size); + MPI_Comm_rank(comm, &rank); + // Negative values will be changed to maximum range if (startCoreIndex < 0) { startCoreIndex = 0; } if (endCoreIndex < 0) { - endCoreIndex = mGroupSize - 1; + endCoreIndex = size - 1; } // Ensure start index is less than end index @@ -282,24 +270,19 @@ XdmfHDF5ControllerDSM::XdmfHDF5ControllerDSM(const std::string & hdf5FilePath, endCoreIndex = tempholder; } - mGroupComm = comm; - mStartCoreIndex = startCoreIndex; - mEndCoreIndex = endCoreIndex; - - MPI_Comm_size(comm, &mGroupSize); - MPI_Comm_rank(comm, &mRank); + MPI_Comm serverComm; MPI_Group workers, dsmgroup, serversplit, servergroup; int * ServerIds = (int *)calloc((3), sizeof(int)); unsigned int index = 0; - for(int i=mStartCoreIndex ; i <= mEndCoreIndex ; ++i) { + for(int i=startCoreIndex ; i <= endCoreIndex ; ++i) { ServerIds[index++] = i; } MPI_Comm_group(comm, &serversplit); MPI_Group_incl(serversplit, index, ServerIds, &servergroup); - MPI_Comm_create(comm, servergroup, &mServerComm); + MPI_Comm_create(comm, servergroup, &serverComm); MPI_Comm_group(comm, &dsmgroup); MPI_Group_excl(dsmgroup, index, ServerIds, &workers); MPI_Comm_create(comm, workers, &mWorkerComm); @@ -312,28 +295,37 @@ XdmfHDF5ControllerDSM::XdmfHDF5ControllerDSM(const std::string & hdf5FilePath, mDSMServerManager->SetLocalBufferSizeMBytes(bufferSize); mDSMServerManager->SetInterCommType(H5FD_DSM_COMM_MPI); - if (mRank >=mStartCoreIndex && mRank <=mEndCoreIndex) { - mDSMServerManager->SetMpiComm(mServerComm); + if (rank >= startCoreIndex && rank <= endCoreIndex) { + mDSMServerManager->SetMpiComm(serverComm); mDSMServerManager->Create(); } else { mDSMServerManager->SetMpiComm(mWorkerComm); mDSMServerManager->SetIsServer(false); - mDSMServerManager->Create(mStartCoreIndex, mEndCoreIndex); + mDSMServerManager->Create(startCoreIndex, endCoreIndex); } XDMF_dsm_set_manager(mDSMServerManager); mDSMServerBuffer = mDSMServerManager->GetDsmBuffer(); - mDSMServerBuffer->GetComm()->DupInterComm(mGroupComm); + mDSMServerBuffer->GetComm()->DupInterComm(comm); mDSMServerBuffer->SetIsConnected(true); + if (startCoreIndex < size) { + if (rank >= startCoreIndex && rank <= endCoreIndex) { + mDSMServerManager->GetDsmBuffer()->ReceiveInfo(); + } + else { + mDSMServerManager->GetDsmBuffer()->SendInfo(); + } + } + MPI_Barrier(comm); // Loop needs to be started before anything can be done to the file, since the service is what sets up the file - if (mRank < mStartCoreIndex || mRank > mEndCoreIndex) { + if (rank < startCoreIndex || rank > endCoreIndex) { // Turn off the server designation mDSMServerBuffer->SetIsServer(H5FD_DSM_FALSE); // If this is set to false then the buffer will attempt to connect to the intercomm for DSM stuff @@ -386,13 +378,6 @@ XdmfDSMBuffer * XdmfHDF5ControllerDSM::getServerBuffer() return mDSMServerBuffer; } -MPI_Comm XdmfHDF5ControllerDSM::getServerComm() -{ - MPI_Comm returnComm = MPI_COMM_NULL; - int status = MPI_Comm_dup(mServerComm, &returnComm); - return returnComm; -} - XdmfDSMManager * XdmfHDF5ControllerDSM::getServerManager() { return mDSMServerManager; @@ -434,34 +419,6 @@ void XdmfHDF5ControllerDSM::setBuffer(H5FDdsmBuffer * newBuffer) mDSMBuffer = newBuffer; } -void XdmfHDF5ControllerDSM::setServerComm(MPI_Comm comm) -{ - int status; - if (mServerComm != MPI_COMM_NULL) { - status = MPI_Comm_free(&mServerComm); - if (status != MPI_SUCCESS) { - try { - XdmfError::message(XdmfError::FATAL, "Failed to disconnect Comm"); - } - catch (XdmfError e) { - throw e; - } - } - } - if (comm != MPI_COMM_NULL) { - status = MPI_Comm_dup(comm, &mServerComm); - if (status != MPI_SUCCESS) { - try { - XdmfError::message(XdmfError::FATAL, "Failed to duplicate Comm"); - } - catch (XdmfError e) { - throw e; - } - } - } - mDSMServerBuffer->GetComm()->DupComm(comm); -} - void XdmfHDF5ControllerDSM::setServerMode(bool newMode) { mServerMode = newMode; @@ -498,7 +455,7 @@ void XdmfHDF5ControllerDSM::setWorkerComm(MPI_Comm comm) void XdmfHDF5ControllerDSM::stopDSM() { // Send manually - for (int i = mStartCoreIndex; i <= mEndCoreIndex; ++i) { + for (int i = mDSMServerBuffer->GetStartServerId(); i <= mDSMServerBuffer->GetEndServerId(); ++i) { try { mDSMServerBuffer->SendCommandHeader(H5FD_DSM_OPCODE_DONE, i, 0, 0, H5FD_DSM_INTER_COMM); } @@ -510,7 +467,7 @@ void XdmfHDF5ControllerDSM::stopDSM() void XdmfHDF5ControllerDSM::restartDSM() { - if (mRank >= mStartCoreIndex && mRank <= mEndCoreIndex) { + if (mDSMServerBuffer->GetComm()->GetInterId() >= mDSMServerBuffer->GetStartServerId() && mDSMServerBuffer->GetComm()->GetInterId() <= mDSMServerBuffer->GetEndServerId()) { H5FDdsmInt32 returnOpCode; try { mDSMServerBuffer->BufferServiceLoop(&returnOpCode); diff --git a/core/XdmfHDF5ControllerDSM.hpp b/core/XdmfHDF5ControllerDSM.hpp index 1b36106d..ad17fb64 100644 --- a/core/XdmfHDF5ControllerDSM.hpp +++ b/core/XdmfHDF5ControllerDSM.hpp @@ -195,7 +195,7 @@ public: * @skipline if * @until { * @skipline writeController - * @until size-1 + * @until getServerBuffer * @skip Section * @skipline } * @@ -206,7 +206,7 @@ public: * @until exampleWriter * @skipline if * @skipline writeController - * @until size-1 + * @until getServerBuffer * * @param hdf5FilePath The path to the hdf5 file that the controller will be accessing * @param dataSetPath The location within the file of the data the controller with be accessing @@ -216,8 +216,6 @@ public: * @param dimensions A vector of the number of values read from all dimensions of the data * @param dataspaceDimensions A vecotr containing the total size of the dimension in the data space * @param dsmBuffer A pointer to the dsm buffer - * @param startCoreIndex The index at which the server cores for the buffer start - * @param endCoreIndex The index at which the server cores for the buffer end */ static shared_ptr New(const std::string & hdf5FilePath, @@ -227,9 +225,7 @@ public: const std::vector & stride, const std::vector & dimensions, const std::vector & dataspaceDimensions, - XdmfDSMBuffer * const dsmBuffer, - int startCoreIndex, - int endCoreIndex); + XdmfDSMBuffer * const dsmBuffer); /** * Create a new controller for an DSM data set. @@ -415,39 +411,6 @@ public: */ XdmfDSMBuffer * getServerBuffer(); - /** - * Gets the communicator that the servers use to communicate between themselves. - * Will be MPI_COMM_NULL on worker cores. - * - * Example of use: - * - * C++ - * - * @dontinclude ExampleXdmfDSMNoThread.cpp - * @skipline size - * @until MPI_Comm_size - * @skipline exampleController - * @until size-1 - * @skipline if - * @until { - * @skipline getServerComm - * @skip Section - * @skipline } - * - * Python - * - * @dontinclude XdmfExampleDSMNoThread.py - * @skipline total - * @until workerComm - * @skipline exampleController - * @until size-1 - * @skipline if - * @skipline exampleController - * - * @return The comm that the servers are using. - */ - MPI_Comm getServerComm(); - /** * Gets the manager for the non-threaded version of DSM * @@ -703,40 +666,6 @@ public: */ void setManager(XdmfDSMManager * newManager); - /** - * Sets the comm that the servers will use to communicate with the other server cores. - * - * Example of use: - * - * C++ - * - * @dontinclude ExampleXdmfDSMNoThread.cpp - * @skipline size - * @until MPI_Comm_size - * @skipline exampleController - * @until size-1 - * @skipline if - * @until { - * @skipline getServerComm - * @skipline setServerComm - * @skip Section - * @skipline } - * - * Python - * - * @dontinclude XdmfExampleDSMNoThread.py - * @skipline total - * @until workerComm - * @skipline exampleController - * @until size-1 - * @skipline if - * @skipline exampleController - * @skipline setServerComm - * - * @param comm The communicator that the server will be using to communicate with the other server cores. - */ - void setServerComm(MPI_Comm comm); - /** * Used to switch between server and threaded mode. * True is server mode, false is threaded mode. @@ -913,9 +842,7 @@ protected: const std::vector & stride, const std::vector & dimensions, const std::vector & dataspaceDimensions, - XdmfDSMBuffer * const dsmBuffer, - int startCoreIndex, - int endCoreIndex); + XdmfDSMBuffer * const dsmBuffer); private: @@ -927,13 +854,7 @@ private: XdmfDSMBuffer * mDSMServerBuffer; XdmfDSMManager * mDSMServerManager; - MPI_Comm mGroupComm; - MPI_Comm mServerComm; MPI_Comm mWorkerComm; - int mStartCoreIndex; - int mEndCoreIndex; - int mRank; - int mGroupSize; bool mServerMode; }; diff --git a/core/XdmfHDF5Writer.cpp b/core/XdmfHDF5Writer.cpp index e1ce7860..0a7597ac 100644 --- a/core/XdmfHDF5Writer.cpp +++ b/core/XdmfHDF5Writer.cpp @@ -43,7 +43,7 @@ namespace { /** * PIMPL */ -class XdmfHDF5Writer::XdmfHDF5WriterImpl { +class XdmfHDF5Writer::XdmfHDF5WriterImpl { public: @@ -51,10 +51,7 @@ public: mHDF5Handle(-1), mChunkSize(DEFAULT_CHUNK_SIZE), mOpenFile(""), - mHDF5FileSizeLimit(0), - mAllowSplitDataSets(false), - mDepth(0), - mFileIndex(0) + mDepth(0) { }; @@ -125,10 +122,7 @@ public: hid_t mHDF5Handle; unsigned int mChunkSize; std::string mOpenFile; - unsigned int mHDF5FileSizeLimit; - bool mAllowSplitDataSets; int mDepth; - int mFileIndex; std::set mWrittenItems; }; @@ -145,7 +139,7 @@ XdmfHDF5Writer::New(const std::string & filePath, } XdmfHDF5Writer::XdmfHDF5Writer(const std::string & filePath) : - XdmfHeavyDataWriter(filePath), + XdmfHeavyDataWriter(filePath, 1, 800), mImpl(new XdmfHDF5WriterImpl()) { } @@ -155,8 +149,8 @@ XdmfHDF5Writer::~XdmfHDF5Writer() delete mImpl; } -shared_ptr -XdmfHDF5Writer::createHDF5Controller(const std::string & hdf5FilePath, +shared_ptr +XdmfHDF5Writer::createController(const std::string & hdf5FilePath, const std::string & dataSetPath, const shared_ptr type, const std::vector & start, @@ -178,47 +172,57 @@ XdmfHDF5Writer::createHDF5Controller(const std::string & hdf5FilePath, } } - -void -XdmfHDF5Writer::setFileSizeLimit(int newSize) -{ - mImpl->mHDF5FileSizeLimit = newSize; -} - -int -XdmfHDF5Writer::getFileSizeLimit() -{ - return mImpl->mHDF5FileSizeLimit; -} - -void -XdmfHDF5Writer::setAllowSetSplitting(bool newAllow) +unsigned int +XdmfHDF5Writer::getChunkSize() const { - mImpl->mAllowSplitDataSets = newAllow; + return mImpl->mChunkSize; } int -XdmfHDF5Writer::getAllowSetSplitting() +XdmfHDF5Writer::getDataSetSize(std::string fileName, std::string dataSetName, const int fapl) { - return mImpl->mAllowSplitDataSets; -} - -void -XdmfHDF5Writer::setFileIndex(int newSize) -{ - mImpl->mFileIndex = newSize; -} + hid_t handle = -1; + H5E_auto_t old_func; + void * old_client_data; + H5Eget_auto(0, &old_func, &old_client_data); + H5Eset_auto2(0, NULL, NULL); + if (fileName != mImpl->mOpenFile) { + // Save old error handler and turn off error handling for now -int -XdmfHDF5Writer::getFileIndex() -{ - return mImpl->mFileIndex; -} + if(H5Fis_hdf5(fileName.c_str()) > 0) { + handle = H5Fopen(fileName.c_str(), + H5F_ACC_RDWR, + fapl); + } + else { + // This is where it currently fails + handle = H5Fcreate(fileName.c_str(), + H5F_ACC_TRUNC, + H5P_DEFAULT, + fapl); + } + } + else { + handle = mImpl->mHDF5Handle; + } -unsigned int -XdmfHDF5Writer::getChunkSize() const -{ - return mImpl->mChunkSize; + // Restore previous error handler + H5Eset_auto2(0, old_func, old_client_data); + + hid_t checkset = H5Dopen(handle, + dataSetName.c_str(), + H5P_DEFAULT); + hid_t checkspace = H5S_ALL; + checkspace = H5Dget_space(checkset); + hssize_t checksize = H5Sget_simple_extent_npoints(checkspace); + herr_t status = H5Dclose(checkset); + if(checkspace != H5S_ALL) { + status = H5Sclose(checkspace); + } + if (handle != mImpl->mHDF5Handle) { + H5Fclose(handle); + } + return checksize; } void @@ -388,7 +392,8 @@ XdmfHDF5Writer::write(XdmfArray & array, previousControllers.push_back(array.getHeavyDataController(i)); } - // Remove controllers from the array, they will be replaced by the controllers created by this function. + // Remove controllers from the array + // they will be replaced by the controllers created by this function. while(array.getNumberHeavyDataControllers() != 0) { array.removeHeavyDataController(array.getNumberHeavyDataControllers() -1); } @@ -398,14 +403,14 @@ XdmfHDF5Writer::write(XdmfArray & array, if (previousControllers.size() == 0) { // Create a temporary controller if the array doesn't have one try { - shared_ptr tempDataController = - this->createHDF5Controller(hdf5FilePath, - "Data", - array.getArrayType(), - std::vector(1, 0), - std::vector(1, 1), - std::vector(1, array.getSize()), - std::vector(1, array.getSize())); + shared_ptr tempDataController = + this->createController(hdf5FilePath, + "Data", + array.getArrayType(), + std::vector(1, 0), + std::vector(1, 1), + std::vector(1, array.getSize()), + std::vector(1, array.getSize())); previousControllers.push_back(tempDataController); } catch (XdmfError e) { @@ -415,7 +420,8 @@ XdmfHDF5Writer::write(XdmfArray & array, int controllerIndexOffset = 0; - // It is assumed that the array will have at least one controller, if it didn't have one a temporary one was generated + // It is assumed that the array will have at least one controller + // if it didn't have one a temporary one was generated for(unsigned int i = 0; i < previousControllers.size(); ++i) { if (mMode == Append) { @@ -443,9 +449,12 @@ XdmfHDF5Writer::write(XdmfArray & array, H5Eset_auto2(0, NULL, NULL); bool startedloop = false; - unsigned int origFileIndex = mImpl->mFileIndex; - while ((mMode == Hyperslab && i < previousControllers.size()) || !startedloop) { - // Hyperslab mode wants to assign all data using the current location without writing until all data sets are determined + unsigned int origFileIndex = getFileIndex(); + while ((mMode == Hyperslab + && i < previousControllers.size()) + || !startedloop) { + // Hyperslab mode wants to assign all data using the current location + // without writing until all data sets are determined startedloop = true; @@ -483,1029 +492,32 @@ XdmfHDF5Writer::write(XdmfArray & array, dataSetPath << "Data" << mDataSetId; } - // Check here for if the file would become larger than the limit after the addition. + // Check here for if the file would become + // larger than the limit after the addition. // Then check subsequent files for the same limitation - - // This is the file splitting algorithm - if (mImpl->mHDF5FileSizeLimit > 0) { - // Only if the file limit is positive, disabled if 0 or negative - unsigned int previousDataSize = 0; - - std::vector previousDimensions; - std::vector previousDataSizes; - unsigned int amountAlreadyWritten = 0; - // Even though theoretically this could be an infinite loop - // if all possible files with the specified name are produced - // the chances of that happening are small. - // It can handle up to 65535 different files. - // This value may vary depending on the compiler and platform. - // The variable UINT_MAX holds the value in question. - // If all files are take up it will loop until a file opens up since adding past the max causes overflow. - - - unsigned int containedInController = 1; - for (unsigned int j = 0; j < dataspaceDimensions.size(); ++j) { - containedInController *= dataspaceDimensions[j]; - } - hssize_t hyperslabSize = 0; - while (amountAlreadyWritten < containedInController) { - - - std::vector partialStarts; - std::vector partialStrides; - std::vector partialDimensions; - std::vector partialDataSizes; - - std::stringstream testFile; - if (mImpl->mFileIndex == 0) { - // If sequentially named files need to be created or referenced - testFile << checkFileName << "." << checkFileExt; - } - else { - testFile << checkFileName << mImpl->mFileIndex << "." << checkFileExt; - } - FILE *checkFile = NULL; - unsigned int fileSize = 0; - // If the file doesn't exist the size is 0 because there's no data - // Get the file stream - checkFile = fopen(testFile.str().c_str(), "a"); - if (checkFile != NULL) { - // Set the file pointer to end of file - fseek(checkFile, 0, SEEK_END); - // Get the file size, in bytes - fileSize = ftell(checkFile); - - // If overwrite subtract previous data size. - if (mMode == Overwrite || mMode == Hyperslab) { - // Find previous data size - mImpl->openFile(testFile.str(), - fapl, mDataSetId); - hid_t checkset = H5Dopen(mImpl->mHDF5Handle, - dataSetPath.str().c_str(), - H5P_DEFAULT); - hid_t checkspace = H5S_ALL; - checkspace = H5Dget_space(checkset); - hssize_t checksize = H5Sget_simple_extent_npoints(checkspace); - status = H5Dclose(checkset); - if(checkspace != H5S_ALL) { - status = H5Sclose(checkspace); - } - if (mMode == Overwrite) { - if (checksize > fileSize) { - fileSize = 0; - } - else { - fileSize = fileSize - checksize; - // Remove previous set's size, since it's overwritten - } - if (fileSize == 0) { - fileSize += hdf5Overhead; - } - } - else if (mMode == Hyperslab) { - hyperslabSize = checksize; - } - } - if (fileSize == 0) { - fileSize += hdf5Overhead; - } - fclose(checkFile); - } - else if (previousDataSize == 0) { - fileSize += hdf5Overhead; - } - // Check size to see if it's within range - - if (closeDatatype == true) { - // closeDatatype is only true if strings are being used, it's set at the beginning when types are checked. - // Size needed is equal to the dataspaceDimensions if in hyperslab mode - // Otherwise is equal to the size of the written array - unsigned int remainingValues = 0; - unsigned int sizeArrayIndex = 0; - if (mMode == Hyperslab) { - remainingValues += 1; - sizeArrayIndex += 1; - for (unsigned int j = 0; j < dataspaceDimensions[j]; ++j) { - remainingValues *= dataspaceDimensions[j]; - sizeArrayIndex *= dimensions[j]; - } - } - else { - remainingValues += array.getSize(); - sizeArrayIndex = amountAlreadyWritten; - } - remainingValues -= amountAlreadyWritten; - // Reduce by number of values already written - if (remainingValues == 0) { - // End if no remaining values - break; - } - // If remaining size is less than available space, just write all of what's left - // Calculate remaining size - unsigned int remainingSize = 0; - for (unsigned int j = sizeArrayIndex; j < array.getSize(); ++j) { - remainingSize += array.getValue(j).size() * 8; - } - if (mMode == Hyperslab) { - // Size is estimated based on averages - remainingSize = (remainingSize / (array.getSize() - sizeArrayIndex)) * remainingValues; - } - if (remainingSize + previousDataSize + fileSize < mImpl->mHDF5FileSizeLimit*(1024*1024)) { - // If the array hasn't been split - if (amountAlreadyWritten == 0) { - // Just pass all data to the partial vectors - for (unsigned int j = 0; j < dimensions.size(); ++j) { - // Done using a loop so that data is copied, not referenced - partialStarts.push_back(start[j]); - partialStrides.push_back(stride[j]); - partialDimensions.push_back(dimensions[j]); - partialDataSizes.push_back(dataspaceDimensions[j]); - } - } - else { - // If the array has been split - int dimensionIndex = previousDimensions.size() - 1; - // Loop previous dimensions in - int j = 0; - for (j = 0; j < dimensionIndex; ++j) { - partialStarts.push_back(start[j]); - partialStrides.push_back(stride[j]); - partialDimensions.push_back(dimensions[j]); - partialDataSizes.push_back(dataspaceDimensions[j]); - } - if (mMode == Hyperslab) { - int newStart = (start[j] + stride[j] * previousDimensions[j]) - previousDataSizes[j]; - while (newStart < 0) { - newStart += stride[j]; - } - partialStarts.push_back(newStart); - // Stride should not change in this algorithm - partialStrides.push_back(stride[j]); - // Total up number of blocks for the higher dimesions and subtract the amount already written - unsigned int dimensiontotal = dimensions[j]; - unsigned int dataspacetotal = dataspaceDimensions[j]; - for (unsigned int k = j + 1; k < dimensions.size(); ++k) { - dimensiontotal *= dimensions[k]; - dataspacetotal *= dataspaceDimensions[k]; - } - if (previousDimensions.size() > 0) { - partialDimensions.push_back(dimensiontotal-previousDimensions[j]); - } - else { - partialDimensions.push_back(dimensiontotal); - } - if (previousDataSizes.size() > 0) { - partialDataSizes.push_back(dataspacetotal-previousDataSizes[j]); - } - else { - partialDataSizes.push_back(dataspacetotal); - } - } - else { - // Start and stride are not used outside of hyperslab - partialStarts.push_back(start[j]); - partialStrides.push_back(stride[j]); - // Total up number of blocks for the higher dimesions and subtract the amount already written - // Since it isn't hyperslab dimensions and dataspacedimensions should be the same - unsigned int dimensiontotal = dimensions[j]; - for (unsigned int k = j + 1; k < dimensions.size(); ++k) { - dimensiontotal *= dimensions[k]; - } - if (previousDimensions.size() > 0) { - partialDimensions.push_back(dimensiontotal-previousDimensions[j]); - } - else { - partialDimensions.push_back(dimensiontotal); - } - if (previousDataSizes.size() > 0) { - partialDataSizes.push_back(dimensiontotal-previousDataSizes[j]); - } - else { - partialDataSizes.push_back(dimensiontotal); - } - } - } - } - else { - // Otherwise, take remaining size and start removing dimensions until the dimension block is less, then take a fraction of the dimension - // Calculate the number of values of the data type you're using will fit - unsigned int usableSpace = (mImpl->mHDF5FileSizeLimit*(1024*1024) - fileSize); - if (previousDataSize + fileSize > mImpl->mHDF5FileSizeLimit*(1024*1024)) { - usableSpace = 0; - } - usableSpace += hyperslabSize-previousDataSize; - // If the array hasn't been split - if (amountAlreadyWritten == 0) { - // See if it will fit in the next file - // If it will just go to the next file - // Otherwise split it. - if (remainingSize + hdf5Overhead > mImpl->mHDF5FileSizeLimit*(1024*1024) && usableSpace > 0) { - if (mImpl->mAllowSplitDataSets) { - // Figure out the size of the largest block that will fit. - unsigned int blockSizeSubtotal = 0; - unsigned int dimensionSizeTotal = 1; - unsigned int dimensionIndex = 0; - unsigned int previousBlockSize = 0; - // Find the dimension that was split - while (dimensionIndex < dataspaceDimensions.size() && blockSizeSubtotal <= usableSpace) { - // This is totally different for strings - dimensionSizeTotal *= dimensions[dimensionIndex]; - previousBlockSize = blockSizeSubtotal; - blockSizeSubtotal = 0; - for (unsigned int k = 0; k < dimensionSizeTotal; ++k) { - if (amountAlreadyWritten + k > array.getSize()) { - try { - XdmfError::message(XdmfError::FATAL, - "Error: Invalid Dimension in HDF5 Write.\n"); - } - catch (XdmfError e) { - throw e; - } - } - blockSizeSubtotal += array.getValue(amountAlreadyWritten + k).size(); - } - dimensionIndex++; - } - // It should end on the "blockSizeSubtotal <= usableSpace" statement, the other half is for backup - // move back one dimension so we're working on the dimension that was split, not the one after it - dimensionIndex--; - blockSizeSubtotal = previousBlockSize; - // Determine how many of those blocks will fit - unsigned int numBlocks = usableSpace / blockSizeSubtotal; - // This should be less than the current value for the dimension - // Add dimensions as required - unsigned int j = 0; - for (; j < dimensionIndex; ++j) { - partialStarts.push_back(start[j]); - partialStrides.push_back(stride[j]); - partialDimensions.push_back(dimensions[j]); - partialDataSizes.push_back(dataspaceDimensions[j]); - } - if (start[j] > numBlocks) { - partialStarts.push_back(numBlocks-1); - } - else { - partialStarts.push_back(start[j]); - } - partialStrides.push_back(stride[j]); - partialDataSizes.push_back(numBlocks); - if (dimensions[j] == dataspaceDimensions[j]) {//this is for non-hyperslab and specific cases of hyperslab - partialDimensions.push_back(numBlocks); - } - else { - // For hyperslab in general - // Determine how many values from the array will fit into the blocks being used with the dimensions specified - unsigned int displacement = numBlocks / stride[j]; - if (((int)displacement * (int)stride[j]) + (start[j] % stride[j]) < numBlocks) { - displacement++; - } - displacement -= start[j]/stride[j]; - if (start[j] > numBlocks) { - displacement = 0; - } - if (dimensions[j] <= displacement) { - // If there are less values than there are space for, just write all of them. - partialDimensions.push_back(dimensions[j]); - } - else { - // Otherwise write what space allows for - partialDimensions.push_back(displacement); - } - } - } - else { - // Just pass all data to the partial vectors - for (unsigned int j = 0; j < dimensions.size(); ++j) { - // Done using a loop so that data is copied, not referenced - partialStarts.push_back(start[j]); - partialStrides.push_back(stride[j]); - partialDimensions.push_back(dimensions[j]); - partialDataSizes.push_back(dataspaceDimensions[j]); - } - } - } - } - else { - // If the array has been split - // This case should not come up often as it requires truly gigantic data sets - // See if the remaining data will fit in the next file - // If yes, skip to it - // If no, split - if (remainingSize + hdf5Overhead > mImpl->mHDF5FileSizeLimit*(1024*1024) && usableSpace > 0) { - // Figure out the size of the largest block that will fit. - unsigned int blockSizeSubtotal = 0; - unsigned int tempTotal = 0; - unsigned int dimensionSizeTotal = 1; - unsigned int dimensionIndex = 0; - // Find the dimension that was split - while (dimensionIndex < dataspaceDimensions.size() && blockSizeSubtotal <= usableSpace) { - // This is totally different for strings - dimensionSizeTotal *= dimensions[dimensionIndex]; - tempTotal = blockSizeSubtotal; - blockSizeSubtotal = 0; - for (unsigned int k = 0; k < dimensionSizeTotal; ++k) { - if (amountAlreadyWritten + k > array.getSize()) { - try { - XdmfError::message(XdmfError::FATAL, - "Error: Invalid Dimension in HDF5 Write.\n"); - } - catch (XdmfError e) { - throw e; - } - } - blockSizeSubtotal += array.getValue(amountAlreadyWritten + k).size(); - } - dimensionIndex++; - } - // It should end on the "blockSizeSubtotal <= usableSpace" statement, the other half is for backup - // Move back one dimension so we're working on the dimension that was split, not the one after it - dimensionIndex--; - blockSizeSubtotal = tempTotal; - unsigned int j = 0; - for (; j < dimensionIndex; ++j) { - partialStarts.push_back(start[j]); - partialStrides.push_back(stride[j]); - partialDimensions.push_back(dimensions[j]); - partialDataSizes.push_back(dataspaceDimensions[j]); - } - // Continue if the block is smaller than the available size - if (blockSizeSubtotal <=usableSpace) { - // Find number of blocks that will fit - // This should be less than the current value for the dimension - unsigned int numBlocks = usableSpace / blockSizeSubtotal; - // Add dimensions to the partial vectors - if (mMode == Hyperslab) { - int newStart = (start[j] + stride[j] * previousDimensions[j]) - previousDataSizes[j]; - while (newStart < 0) { - newStart += stride[j]; - } - partialStarts.push_back(newStart); - // Stride should not change in this algorithm - partialStrides.push_back(stride[j]); - partialDataSizes.push_back(numBlocks); - // Determine how many values from the array will fit into the blocks being used - // with the dimensions specified - unsigned int displacement = (numBlocks - newStart) / stride[j]; - if (((int)displacement * (int)stride[j]) + (newStart % stride[j]) < numBlocks) { - displacement++; - } - displacement -= newStart/stride[j]; - if (newStart > (int)numBlocks) { - displacement = 0; - } - if ((dimensions[j] - previousDimensions[j]) <= displacement) { - // If there are less values than there are space for, just write all of them. - partialDimensions.push_back(dimensions[j] - previousDimensions[j]); - } - else { - // Otherwise write what space allows for - partialDimensions.push_back(displacement); - } - } - else { - // Start and stride are only specified in hyperslab - partialStarts.push_back(start[j]); - partialStrides.push_back(stride[j]); - partialDataSizes.push_back(numBlocks); - partialDimensions.push_back(numBlocks); - } - // Place dimensions into previous dimensions for later iterations - } - else { - // If this is larger than usable space, try the next file - // If moving to next file, just do nothing and pass out of the if statement - // but also check if specified file size is too small - if (mImpl->mHDF5FileSizeLimit*(1024*1024) < blockSizeSubtotal) { - // This shouldn't ever trigger, but it's good to cover ourselves - // and throw an error if the block size won't work - try { - XdmfError::message(XdmfError::FATAL, - "Error: Dimension Block size / Maximum File size mismatch.\n"); - } - catch (XdmfError e) { - throw e; - } - } - } - } - } - // Move to next file - mImpl->mFileIndex++; - } - } - else { - // If needed split the written array into smaller arrays based on dimension blocks - // Working with strings has a more resource intensive version of this algorithm - // Size needed is equal to the dataspaceDimensions if in hyperslab mode - // otherwise is equal to the size of the written array - unsigned int remainingValues = 0; - if (mMode == Hyperslab) { - remainingValues += 1; - for (unsigned int j = 0; j < dataspaceDimensions.size(); ++j) { - remainingValues *= dataspaceDimensions[j]; - } - } - else { - remainingValues += 1; - for (unsigned int j = 0; j < dimensions.size(); ++j) { - remainingValues *= dimensions[j]; - } - } - remainingValues -= amountAlreadyWritten; - // Reduce by number of values already written - if (remainingValues == 0) {//end if no remaining values - break; - } - unsigned int dataItemSize = array.getArrayType()->getElementSize(); - // If remaining size is less than available space, just write all of what's left - if ((remainingValues * dataItemSize) + previousDataSize + fileSize < mImpl->mHDF5FileSizeLimit*(1024*1024)) { - // If the array hasn't been split - if (amountAlreadyWritten == 0) { - // Just pass all data to the partial vectors - for (unsigned int j = 0; j < dimensions.size(); ++j) { - // Done using a loop so that data is copied, not referenced - partialStarts.push_back(start[j]); - partialStrides.push_back(stride[j]); - partialDimensions.push_back(dimensions[j]); - partialDataSizes.push_back(dataspaceDimensions[j]); - } - } - else { - // If the array has been split - int dimensionIndex = previousDimensions.size() - 1; - // Loop previous dimensions in - int j = 0; - for (j = 0; j < dimensionIndex; ++j) { - partialStarts.push_back(start[j]); - partialStrides.push_back(stride[j]); - partialDimensions.push_back(dimensions[j]); - partialDataSizes.push_back(dataspaceDimensions[j]); - } - if (mMode == Hyperslab) { - int newStart = (start[j] + stride[j] * previousDimensions[j]) - previousDataSizes[j]; - while (newStart < 0) { - newStart += stride[j]; - } - partialStarts.push_back(newStart); - // Stride should not change in this algorithm - partialStrides.push_back(stride[j]); - // Total up number of blocks for the higher dimesions and subtract the amount already written - unsigned int dimensiontotal = dimensions[j]; - unsigned int dataspacetotal = dataspaceDimensions[j]; - for (unsigned int k = j + 1; k < dimensions.size(); ++k) { - dimensiontotal *= dimensions[k]; - dataspacetotal *= dataspaceDimensions[k]; - } - if (previousDimensions.size() > 0) { - partialDimensions.push_back(dimensiontotal-previousDimensions[j]); - } - else { - partialDimensions.push_back(dimensiontotal); - } - if (previousDataSizes.size() > 0) { - partialDataSizes.push_back(dataspacetotal-previousDataSizes[j]); - } - else { - partialDataSizes.push_back(dataspacetotal); - } - } - else { - // Start and stride are not used outside of hyperslab - partialStarts.push_back(start[j]); - partialStrides.push_back(stride[j]); - // Total up number of blocks for the higher dimesions and subtract the amount already written - // since it isn't hyperslab dimensions and dataspacedimensions should be the same - unsigned int dimensiontotal = dimensions[j]; - for (unsigned int k = j + 1; k < dimensions.size(); ++k) { - dimensiontotal *= dimensions[k]; - } - if (previousDimensions.size() > 0) { - partialDimensions.push_back(dimensiontotal-previousDimensions[j]); - } - else { - partialDimensions.push_back(dimensiontotal); - } - if (previousDataSizes.size() > 0) { - partialDataSizes.push_back(dimensiontotal-previousDataSizes[j]); - } - else { - partialDataSizes.push_back(dimensiontotal); - } - } - } - } - else { - // Otherwise, take remaining size and start removing dimensions until the dimension block is less, then take a fraction of the dimension - // Calculate the number of values of the data type you're using will fit - unsigned int usableSpace = (mImpl->mHDF5FileSizeLimit*(1024*1024) - fileSize) / dataItemSize; - if (mImpl->mHDF5FileSizeLimit*(1024*1024) < fileSize) { - usableSpace = 0; - } - usableSpace += hyperslabSize-previousDataSize; - // If the array hasn't been split - if (amountAlreadyWritten == 0) { - // See if it will fit in the next file - // If it will just go to the next file - // Otherwise split it. - if ((remainingValues * dataItemSize) + hdf5Overhead > mImpl->mHDF5FileSizeLimit*(1024*1024) && usableSpace > 0) { - if (mImpl->mAllowSplitDataSets) { - // Figure out the size of the largest block that will fit. - unsigned int blockSizeSubtotal = 1; - unsigned int dimensionIndex = 0; - // Find the dimension that was split - while (dimensionIndex < dataspaceDimensions.size() && blockSizeSubtotal <= usableSpace) { - blockSizeSubtotal *= dataspaceDimensions[dimensionIndex]; - dimensionIndex++; - } - // It should end on the "blockSizeSubtotal <= arrayStartIndex" statement, the other half is for backup - // Move back one dimension so we're working on the dimension that was split, not the one after it - dimensionIndex--; - blockSizeSubtotal /= dataspaceDimensions[dimensionIndex]; - // Determine how many of those blocks will fit - unsigned int numBlocks = usableSpace / blockSizeSubtotal; - // This should be less than the current value for the dimension - // Add dimensions as required. - unsigned int j = 0; - for (j = 0; j < dimensionIndex; ++j) { - partialStarts.push_back(start[j]); - partialStrides.push_back(stride[j]); - partialDimensions.push_back(dimensions[j]); - partialDataSizes.push_back(dataspaceDimensions[j]); - } - if (start[j] > numBlocks) { - partialStarts.push_back(numBlocks-1); - } - else { - partialStarts.push_back(start[j]); - } - partialStrides.push_back(stride[j]); - partialDataSizes.push_back(numBlocks); - if (dimensions[j] == dataspaceDimensions[j]) { - // This is for non-hyperslab and specific cases of hyperslab - partialDimensions.push_back(numBlocks); - } - else { - // For hyperslab in general - // Determine how many values from the array will fit into the blocks being used with the dimensions specified - unsigned int displacement = numBlocks / stride[j]; - if (((int)displacement * (int)stride[j]) + (start[j] % stride[j]) < numBlocks) { - displacement++; - } - displacement -= start[j]/stride[j]; - if (start[j] > numBlocks) { - displacement = 0; - } - if (dimensions[j] <= displacement) { - // If there are less values than there are space for, just write all of them. - partialDimensions.push_back(dimensions[j]); - } - else { - // Otherwise write what space allows for - partialDimensions.push_back(displacement); - } - } - } - else { - // Just pass all data to the partial vectors - for (unsigned int j = 0; j < dimensions.size(); ++j) { - // Done using a loop so that data is copied, not referenced - partialStarts.push_back(start[j]); - partialStrides.push_back(stride[j]); - partialDimensions.push_back(dimensions[j]); - partialDataSizes.push_back(dataspaceDimensions[j]); - } - } - } - } - else { - // If the array has been split - // This case should not come up often as it requires truly gigantic data sets - // See if it will fit in the next file - // If it will just go to the next file - // Otherwise split it. - if ((remainingValues * dataItemSize) + hdf5Overhead > mImpl->mHDF5FileSizeLimit*(1024*1024) && usableSpace > 0) { - unsigned int blockSizeSubtotal = 1; - unsigned int dimensionIndex = 0; - // Find the dimension that was split - while (dimensionIndex < dataspaceDimensions.size() && blockSizeSubtotal <= amountAlreadyWritten) { - blockSizeSubtotal *= dataspaceDimensions[dimensionIndex]; - dimensionIndex++; - } - // It should end on the "blockSizeSubtotal <= arrayStartIndex" statement, the other half is for backup - // Move back one dimension so we're working on the dimension that was split, not the one after it - dimensionIndex--; - blockSizeSubtotal /= dataspaceDimensions[dimensionIndex]; - unsigned int j = 0; - for (j = 0; j < dimensionIndex; ++j) { - partialStarts.push_back(start[j]); - partialStrides.push_back(stride[j]); - partialDimensions.push_back(dimensions[j]); - partialDataSizes.push_back(dataspaceDimensions[j]); - } - // Continue if the block is smaller than the available size - if (blockSizeSubtotal <=usableSpace) { - // Find number of blocks that will fit - // This should be less than the current value for the dimension - unsigned int numBlocks = usableSpace / blockSizeSubtotal; - // Add dimensions to the partial vectors - if (mMode == Hyperslab) { - int newStart = (start[j] + stride[j] * previousDimensions[j]) - previousDataSizes[j]; - while (newStart < 0) { - newStart += stride[j]; - } - partialStarts.push_back(newStart); - // Stride should not change in this algorithm - partialStrides.push_back(stride[j]); - partialDataSizes.push_back(numBlocks); - //determine how many values from the array will fit into the blocks being used - //with the dimensions specified - unsigned int displacement = numBlocks / stride[j]; - if (((int)displacement * (int)stride[j]) + (newStart % stride[j]) < numBlocks) { - displacement++; - } - displacement -= newStart/stride[j]; - if (newStart > (int)numBlocks) { - displacement = 0; - } - if ((dimensions[j] - previousDimensions[j]) <= displacement) { - // If there are less values than there are space for, just write all of them. - partialDimensions.push_back(dimensions[j] - previousDimensions[j]); - } - else { - // Otherwise write what space allows for - partialDimensions.push_back(displacement); - } - } - else { - // Start and stride are only specified in hyperslab - partialStarts.push_back(start[j]); - partialStrides.push_back(stride[j]); - partialDataSizes.push_back(numBlocks); - partialDimensions.push_back(numBlocks); - } - // Place dimensions into previous dimensions for later iterations - } - else { - // If this is larger than usable space, try the next file - // If moving to next file, just do nothing and pass out of the if statement - // but also check if specified file size is too small - if (mImpl->mHDF5FileSizeLimit*(1024*1024) < blockSizeSubtotal) { - // This shouldn't ever trigger, but it's good to cover ourselves - // Throw an error if the block size won't work - try { - XdmfError::message(XdmfError::FATAL, - "Error: Dimension Block size / Maximum File size mismatch.\n"); - } - catch (XdmfError e) { - throw e; - } - } - } - } - } - // Move to next file - mImpl->mFileIndex++; - } - } - - - if (partialDimensions.size() > 0) { - // Building the array to be written - int containedInDimensions = 1; - // Count moved - for (unsigned int j = 0 ; j < partialDimensions.size(); ++j) { - containedInDimensions *= partialDimensions[j]; - } - // Starting index - int containedInPriorDimensions = controllerIndexOffset; - int startOffset = 1; - for (unsigned int j = 0; j < previousDimensions.size(); ++j) { - startOffset *= previousDimensions[j]; - } - if (previousDimensions.size() == 0) { - startOffset = 0; - } - containedInPriorDimensions += startOffset; - int dimensionTotal = 1; - for (unsigned int j = 0; j < dimensions.size(); ++j) { - dimensionTotal *= dimensions[j]; - } - if (containedInDimensions > 0) { - shared_ptr partialArray = XdmfArray::New(); - if (datatype == H5T_NATIVE_CHAR) { - partialArray->initialize(XdmfArrayType::Int8(), 0); - char movedData [containedInDimensions]; - array.getValues(containedInPriorDimensions, movedData, containedInDimensions); - partialArray->insert(0, movedData, containedInDimensions); - } - else if (datatype == H5T_NATIVE_SHORT) { - partialArray->initialize(XdmfArrayType::Int16(), 0); - short movedData [containedInDimensions]; - array.getValues(containedInPriorDimensions, movedData, containedInDimensions); - partialArray->insert(0, movedData, containedInDimensions); - } - else if (datatype == H5T_NATIVE_INT) { - partialArray->initialize(XdmfArrayType::Int32(), 0); - int movedData [containedInDimensions]; - array.getValues(containedInPriorDimensions, movedData, containedInDimensions); - partialArray->insert(0, movedData, containedInDimensions); - } - else if (datatype == H5T_NATIVE_LONG) { - partialArray->initialize(XdmfArrayType::Int64(), 0); - long movedData [containedInDimensions]; - array.getValues(containedInPriorDimensions, movedData, containedInDimensions); - partialArray->insert(0, movedData, containedInDimensions); - } - else if (datatype == H5T_NATIVE_FLOAT) { - partialArray->initialize(XdmfArrayType::Float32(), 0); - float movedData [containedInDimensions]; - array.getValues(containedInPriorDimensions, movedData, containedInDimensions); - partialArray->insert(0, movedData, containedInDimensions); - } - else if (datatype == H5T_NATIVE_DOUBLE) { - partialArray->initialize(XdmfArrayType::Float64(), 0); - double movedData [containedInDimensions]; - array.getValues(containedInPriorDimensions, movedData, containedInDimensions); - partialArray->insert(0, movedData, containedInDimensions); - } - else if (datatype == H5T_NATIVE_UCHAR) { - partialArray->initialize(XdmfArrayType::UInt8(), 0); - unsigned char movedData [containedInDimensions]; - array.getValues(containedInPriorDimensions, movedData, containedInDimensions); - partialArray->insert(0, movedData, containedInDimensions); - } - else if (datatype == H5T_NATIVE_USHORT) { - partialArray->initialize(XdmfArrayType::UInt16(), 0); - unsigned short movedData [containedInDimensions]; - array.getValues(containedInPriorDimensions, movedData, containedInDimensions); - partialArray->insert(0, movedData, containedInDimensions); - } - else if (datatype == H5T_NATIVE_UINT) { - partialArray->initialize(XdmfArrayType::UInt32(), 0); - unsigned int movedData [containedInDimensions]; - array.getValues(containedInPriorDimensions, movedData, containedInDimensions); - partialArray->insert(0, movedData, containedInDimensions); - } - else if (closeDatatype) { - // closeDatatype is only true if strings are being used - partialArray->initialize(XdmfArrayType::String(), 0); - for (int j = containedInPriorDimensions; j < containedInPriorDimensions + containedInDimensions; ++j) { - partialArray->pushBack(array.getValue(j)); - } - } - arraysWritten.push_back(partialArray); - filesWritten.push_back(testFile.str()); - startsWritten.push_back(partialStarts); - stridesWritten.push_back(partialStrides); - dimensionsWritten.push_back(partialDimensions); - dataSizesWritten.push_back(partialDataSizes); - arrayOffsetsWritten.push_back(containedInPriorDimensions); - } - if (mMode == Hyperslab) { - containedInPriorDimensions -= controllerIndexOffset; - } - if (containedInDimensions + containedInPriorDimensions == dimensionTotal) { - controllerIndexOffset += dimensionTotal; - } - // For hyperslab the space is controlled by the dataspace dimensions - // So use that since the dimensions should be equal to the dataspace dimensions in all other variations - // Total up written data space - unsigned int writtenDataSpace = 1; - for (unsigned int j = 0; j < partialDataSizes.size(); ++j) { - writtenDataSpace *= partialDataSizes[j]; - } - amountAlreadyWritten += writtenDataSpace; - // Generate previous dimensions - if (previousDataSizes.size() == 0) { - previousDataSizes = partialDataSizes; - previousDimensions = partialDimensions; - } - else { - // Determine if the sizes match - // If they do, add the top values together - // Otherwise, compress the higher dimensions and then add them - if (previousDimensions.size() == partialDimensions.size()) { - previousDimensions[previousDimensions.size()-1] += partialDimensions[previousDimensions.size()-1]; - } - else if (previousDimensions.size() < partialDimensions.size()) { - unsigned int overflowDimensions = 1; - for (unsigned int j = previousDimensions.size() - 1; j < partialDimensions.size(); ++j) { - overflowDimensions *= partialDimensions[j]; - } - previousDimensions[previousDimensions.size()-1] += overflowDimensions; - } - else if (previousDimensions.size() > partialDimensions.size()) { - unsigned int overflowDimensions = 1; - for (unsigned int j = partialDimensions.size() - 1; j < previousDimensions.size(); ++j) { - overflowDimensions *= previousDimensions[j]; - } - previousDimensions.resize(partialDimensions.size()); - previousDimensions[partialDimensions.size()-1] = overflowDimensions; - previousDimensions[previousDimensions.size()-1] += partialDimensions[previousDimensions.size()-1]; - } - if (previousDataSizes.size() == partialDataSizes.size()) { - previousDataSizes[previousDataSizes.size()-1] += partialDataSizes[previousDataSizes.size()-1]; - } - else if (previousDataSizes.size() < partialDataSizes.size()) { - unsigned int overflowDataSizes = 1; - for (unsigned int j = previousDataSizes.size() - 1; j < partialDataSizes.size(); ++j) { - overflowDataSizes *= partialDataSizes[j]; - } - previousDataSizes[previousDataSizes.size()-1] += overflowDataSizes; - } - else if (previousDataSizes.size() > partialDataSizes.size()) { - unsigned int overflowDataSizes = 1; - for (unsigned int j = partialDataSizes.size() - 1; j < previousDataSizes.size(); ++j) { - overflowDataSizes *= previousDataSizes[j]; - } - previousDataSizes.resize(partialDataSizes.size()); - previousDataSizes[partialDataSizes.size()-1] = overflowDataSizes; - previousDataSizes[previousDataSizes.size()-1] += partialDataSizes[previousDataSizes.size()-1]; - } - } - } - } - - if (mMode == Append) { - // If the written filename is different write add the previous controller - if (*(filesWritten.rbegin()) != heavyDataController->getFilePath()) { - // Should also be different from previous controller - if (filesWritten.size() > 1) { - if (*(filesWritten.rbegin()) != *((filesWritten.rbegin())++)) { - array.insert(heavyDataController); - } - } - else { - array.insert(heavyDataController); - } - } - } - - - } - else { - // Otherwise work with the full array - shared_ptr partialArray = XdmfArray::New(); - // Need to copy by duplicating the contents of the array - unsigned int j = controllerIndexOffset; - - try { - heavyDataController = - this->createHDF5Controller(hdf5FilePath, - dataSetPath.str(), - array.getArrayType(), - start, - stride, - dimensions, - dataspaceDimensions); - } - catch (XdmfError e) { - throw e; - } - - int movedSize = 0; - if (datatype == H5T_NATIVE_CHAR){ - partialArray->initialize(XdmfArrayType::Int8(), 0); - if ((array.getSize() - controllerIndexOffset) <= heavyDataController->getSize()) { - movedSize = array.getSize() - controllerIndexOffset; - } - else if (heavyDataController->getSize() < (array.getSize() - controllerIndexOffset)) { - movedSize = heavyDataController->getSize(); - } - char movedData [movedSize]; - array.getValues(controllerIndexOffset, movedData, movedSize); - partialArray->insert(0, movedData, movedSize); - j+=movedSize; - } - else if (datatype == H5T_NATIVE_SHORT){ - partialArray->initialize(XdmfArrayType::Int16(), 0); - if ((array.getSize() - controllerIndexOffset) <= heavyDataController->getSize()) { - movedSize = array.getSize() - controllerIndexOffset; - } - else if (heavyDataController->getSize() < (array.getSize() - controllerIndexOffset)) { - movedSize = heavyDataController->getSize(); - } - short movedData [movedSize]; - array.getValues(controllerIndexOffset, movedData, movedSize); - partialArray->insert(0, movedData, movedSize); - j+=movedSize; - } - else if (datatype == H5T_NATIVE_INT){ - partialArray->initialize(XdmfArrayType::Int32(), 0); - if ((array.getSize() - controllerIndexOffset) <= heavyDataController->getSize()) { - movedSize = array.getSize() - controllerIndexOffset; - } - else if (heavyDataController->getSize() < (array.getSize() - controllerIndexOffset)) { - movedSize = heavyDataController->getSize(); - } - int movedData [movedSize]; - array.getValues(controllerIndexOffset, movedData, movedSize); - partialArray->insert(0, movedData, movedSize); - j+=movedSize; - } - else if (datatype == H5T_NATIVE_LONG){ - partialArray->initialize(XdmfArrayType::Int64(), 0); - if ((array.getSize() - controllerIndexOffset) <= heavyDataController->getSize()) { - movedSize = array.getSize() - controllerIndexOffset; - } - else if (heavyDataController->getSize() < (array.getSize() - controllerIndexOffset)) { - movedSize = heavyDataController->getSize(); - } - long movedData [movedSize]; - array.getValues(controllerIndexOffset, movedData, movedSize); - partialArray->insert(0, movedData, movedSize); - j+=movedSize; - } - else if (datatype == H5T_NATIVE_FLOAT){ - partialArray->initialize(XdmfArrayType::Float32(), 0); - if ((array.getSize() - controllerIndexOffset) <= heavyDataController->getSize()) { - movedSize = array.getSize() - controllerIndexOffset; - } - else if (heavyDataController->getSize() < (array.getSize() - controllerIndexOffset)) { - movedSize = heavyDataController->getSize(); - } - float movedData [movedSize]; - array.getValues(controllerIndexOffset, movedData, movedSize); - partialArray->insert(0, movedData, movedSize); - j+=movedSize; - } - else if (datatype == H5T_NATIVE_DOUBLE){ - partialArray->initialize(XdmfArrayType::Float64(), 0); - if ((array.getSize() - controllerIndexOffset) <= heavyDataController->getSize()) { - movedSize = array.getSize() - controllerIndexOffset; - } - else if (heavyDataController->getSize() < (array.getSize() - controllerIndexOffset)) { - movedSize = heavyDataController->getSize(); - } - double movedData [movedSize]; - array.getValues(controllerIndexOffset, movedData, movedSize); - partialArray->insert(0, movedData, movedSize); - j+=movedSize; - } - else if (datatype == H5T_NATIVE_UCHAR){ - partialArray->initialize(XdmfArrayType::UInt8(), 0); - if ((array.getSize() - controllerIndexOffset) <= heavyDataController->getSize()) { - movedSize = array.getSize() - controllerIndexOffset; - } - else if (heavyDataController->getSize() < (array.getSize() - controllerIndexOffset)) { - movedSize = heavyDataController->getSize(); - } - unsigned char movedData [movedSize]; - array.getValues(controllerIndexOffset, movedData, movedSize); - partialArray->insert(0, movedData, movedSize); - j+=movedSize; - } - else if (datatype == H5T_NATIVE_USHORT){ - partialArray->initialize(XdmfArrayType::UInt16(), 0); - if ((array.getSize() - controllerIndexOffset) <= heavyDataController->getSize()) { - movedSize = array.getSize() - controllerIndexOffset; - } - else if (heavyDataController->getSize() < (array.getSize() - controllerIndexOffset)) { - movedSize = heavyDataController->getSize(); - } - unsigned short movedData [movedSize]; - array.getValues(controllerIndexOffset, movedData, movedSize); - partialArray->insert(0, movedData, movedSize); - j+=movedSize; - } - else if (datatype == H5T_NATIVE_UINT) { - partialArray->initialize(XdmfArrayType::UInt32(), 0); - if ((array.getSize() - controllerIndexOffset) <= heavyDataController->getSize()) { - movedSize = array.getSize() - controllerIndexOffset; - } - else if (heavyDataController->getSize() < (array.getSize() - controllerIndexOffset)) { - movedSize = heavyDataController->getSize(); - } - unsigned int movedData [movedSize]; - array.getValues(controllerIndexOffset, movedData, movedSize); - partialArray->insert(0, movedData, movedSize); - j+=movedSize; - } - else if (closeDatatype) { - // closeDatatype is only true if strings are being used - partialArray->initialize(XdmfArrayType::String(), 0); - // Transfering via loop because the getValues function is not fully tested with strings - for (j = controllerIndexOffset; j < controllerIndexOffset + heavyDataController->getSize() && j < array.getSize(); ++j){ - partialArray->pushBack(array.getValue(j)); - } - } - arrayOffsetsWritten.push_back(controllerIndexOffset); - // Set the offset to the point after the end of the current subset - controllerIndexOffset = j; - - arraysWritten.push_back(partialArray); - filesWritten.push_back(hdf5FilePath); - // Also need to push the starts and strides loaded from the HeavyDataController - startsWritten.push_back(start); - stridesWritten.push_back(stride); - dimensionsWritten.push_back(dimensions); - dataSizesWritten.push_back(dataspaceDimensions); - } + controllerSplitting(array, + fapl, + controllerIndexOffset, + heavyDataController, + checkFileName, + checkFileExt, + dataSetPath.str(), + dimensions, + dataspaceDimensions, + start, + stride, + filesWritten, + arraysWritten, + startsWritten, + stridesWritten, + dimensionsWritten, + dataSizesWritten, + arrayOffsetsWritten); if (mMode == Hyperslab) { i++; - mImpl->mFileIndex = origFileIndex; + setFileIndex(origFileIndex); } } @@ -1518,7 +530,6 @@ XdmfHDF5Writer::write(XdmfArray & array, std::list >::iterator dataSizeWalker = dataSizesWritten.begin(); std::list::iterator arrayOffsetWalker = arrayOffsetsWritten.begin(); - // Loop based on the amount of blocks split from the array. for (unsigned int writeIndex = 0; writeIndex < arraysWritten.size(); ++writeIndex) { @@ -1804,14 +815,14 @@ XdmfHDF5Writer::write(XdmfArray & array, insertDataSpaceDimensions.push_back(newSize); try { - newDataController = - this->createHDF5Controller(curFileName, - dataSetPath.str(), - curArray->getArrayType(), - insertStarts, - insertStrides, - insertDimensions, - insertDataSpaceDimensions); + newDataController = + shared_dynamic_cast(this->createController(curFileName, + dataSetPath.str(), + curArray->getArrayType(), + insertStarts, + insertStrides, + insertDimensions, + insertDataSpaceDimensions)); } catch (XdmfError e) { throw e; @@ -1822,13 +833,13 @@ XdmfHDF5Writer::write(XdmfArray & array, // If the controller wasn't generated by append try { newDataController = - this->createHDF5Controller(curFileName, - dataSetPath.str(), - curArray->getArrayType(), - curStart, - curStride, - curDimensions, - curDataSize); + shared_dynamic_cast(this->createController(curFileName, + dataSetPath.str(), + curArray->getArrayType(), + curStart, + curStride, + curDimensions, + curDataSize)); } catch (XdmfError e) { throw e; diff --git a/core/XdmfHDF5Writer.hpp b/core/XdmfHDF5Writer.hpp index 994cf223..417ece6f 100644 --- a/core/XdmfHDF5Writer.hpp +++ b/core/XdmfHDF5Writer.hpp @@ -32,6 +32,8 @@ class XdmfHDF5Controller; // Includes #include "XdmfCore.hpp" #include "XdmfHeavyDataWriter.hpp" +#include "XdmfHeavyDataController.hpp" +#include /** * @brief Traverse the Xdmf graph and write heavy data stored in @@ -79,149 +81,6 @@ public: virtual ~XdmfHDF5Writer(); - /** - * Sets the file size limit of the HDF5 files produced by the writer in MB. Overflow is pushed to a new HDF5 file. - * Using with arrays of string type may reduce performance. - * - * Example of use: - * - * C++ - * - * @dontinclude ExampleXdmfHDF5Writer.cpp - * @skipline newPath - * @until setFileSizeLimit - * - * Python - * - * @dontinclude XdmfExampleHDF5Writer.py - * @skipline newPath - * @until setFileSizeLimit - * - * @param newSize The size limit in MB - */ - void setFileSizeLimit(int newSize); - - /** - * Gets the file size limit of the HDF5 files produced by the writer in MB. Overflow is pushed to a new HDF5 file. - * - * Example of use: - * - * C++ - * - * @dontinclude ExampleXdmfHDF5Writer.cpp - * @skipline newPath - * @until New - * @skipline exampleLimit - * - * Python - * - * @dontinclude XdmfExampleHDF5Writer.py - * @skipline newPath - * @until New - * @skipline exampleLimit - * - * @return The size limit in MB - */ - int getFileSizeLimit(); - - /** - * Sets whether to allow the HDF5 writer to split data sets when writing to hdf5. - * Splitting should only occur for massive data sets. - * Setting to false assures compatibility with previous editions. - * Default setting is false - * - * Example of use: - * - * C++ - * - * @dontinclude ExampleXdmfHDF5Writer.cpp - * @skipline newPath - * @until New - * @skipline newAllow - * @until setAllow - * - * Python - * - * @dontinclude XdmfExampleHDF5Writer.py - * @skipline newPath - * @until New - * @skipline newAllow - * @until setAllow - * - * @param newAllow whether to allow data sets to be split across hdf5 files - */ - void setAllowSetSplitting(bool newAllow); - - /** - * Gets whether the HDF5 Writer is allowed to split data sets when writing to hdf5. - * Splitting should only occur for massive data sets. - * Setting to false assures compatibility with previous editions. - * Default setting is false. - * - * Example of use: - * - * C++ - * - * @dontinclude ExampleXdmfHDF5Writer.cpp - * @skipline newPath - * @until New - * @skipline exampleAllow - * - * Python - * - * @dontinclude XdmfExampleHDF5Writer.py - * @skipline newPath - * @until New - * @skipline exampleAllow - * - * @return whether to allow data sets to be split across hdf5 files - */ - int getAllowSetSplitting(); - - /** - * Sets the file index. Used when file splitting and incremented when the current file is full. Set to 0 before using hyperslab or overwrite. - * - * C++ - * - * @dontinclude ExampleXdmfHDF5Writer.cpp - * @skipline newPath - * @until New - * @skipline newFileIndex - * @until setFileIndex - * - * Python - * - * @dontinclude XdmfExampleHDF5Writer.py - * @skipline newPath - * @until New - * @skipline newFileIndex - * @until setFileIndex - * - * @param newIndex The index that the writer will append to the file name when incorperating file splitting - */ - void setFileIndex(int newIndex); - - /** - * Gets the file index. Used when file splitting and incremented whent he current file is full. - * - * C++ - * - * @dontinclude ExampleXdmfHDF5Writer.cpp - * @skipline newPath - * @until New - * @skipline getFileIndex - * - * Python - * - * @dontinclude XdmfExampleHDF5Writer.py - * @skipline newPath - * @until New - * @skipline getFileIndex - * - * @return The current file index. - */ - int getFileIndex(); - virtual void closeFile(); /** @@ -245,6 +104,8 @@ public: */ unsigned int getChunkSize() const; + virtual int getDataSetSize(std::string fileName, std::string dataSetName, const int fapl); + virtual void openFile(); /** @@ -279,6 +140,28 @@ public: virtual void visit(XdmfItem & item, const shared_ptr visitor); + using XdmfHeavyDataWriter::controllerSplitting; + +/* //TODO temp, going to move to heavydatacontroller + virtual void controllerSplitting(XdmfArray & array, + const int fapl, + int & controllerIndexOffset, + shared_ptr heavyDataController, + std::string checkFileName, + std::string checkFileExt, + std::string dataSetPath, + std::vector dimensions, + std::vector dataspaceDimensions, + std::vector start, + std::vector stride, + std::list & filesWritten, + std::list > & arraysWritten, + std::list > & startsWritten, + std::list > & stridesWritten, + std::list > & dimensionsWritten, + std::list > & dataSizesWritten, + std::list & arrayOffsetsWritten);*/ + protected: XdmfHDF5Writer(const std::string & filePath); @@ -302,14 +185,14 @@ protected: * * @return new HDF5 Controller. */ - virtual shared_ptr - createHDF5Controller(const std::string & hdf5FilePath, - const std::string & dataSetPath, - const shared_ptr type, - const std::vector & start, - const std::vector & stride, - const std::vector & dimensions, - const std::vector & dataspaceDimensions); + virtual shared_ptr + createController(const std::string & hdf5FilePath, + const std::string & dataSetPath, + const shared_ptr type, + const std::vector & start, + const std::vector & stride, + const std::vector & dimensions, + const std::vector & dataspaceDimensions); /** * Open hdf5 file with a fapl. diff --git a/core/XdmfHDF5WriterDSM.cpp b/core/XdmfHDF5WriterDSM.cpp index 3db0edca..c57d29d0 100644 --- a/core/XdmfHDF5WriterDSM.cpp +++ b/core/XdmfHDF5WriterDSM.cpp @@ -46,14 +46,10 @@ XdmfHDF5WriterDSM::New(const std::string & filePath, shared_ptr XdmfHDF5WriterDSM::New(const std::string & filePath, - XdmfDSMBuffer * const dsmBuffer, - int startCoreIndex, - int endCoreIndex) + XdmfDSMBuffer * const dsmBuffer) { shared_ptr p(new XdmfHDF5WriterDSM(filePath, - dsmBuffer, - startCoreIndex, - endCoreIndex)); + dsmBuffer)); return p; } @@ -91,13 +87,7 @@ XdmfHDF5WriterDSM::XdmfHDF5WriterDSM(const std::string & filePath, mFAPL(-1), mDSMServerManager(NULL), mDSMServerBuffer(NULL), - mGroupComm(MPI_COMM_NULL), - mServerComm(MPI_COMM_NULL), mWorkerComm(MPI_COMM_NULL), - mStartCoreIndex(-1), - mEndCoreIndex(-1), - mRank(-1), - mGroupSize(-1), mServerMode(false) { } @@ -109,13 +99,7 @@ XdmfHDF5WriterDSM::XdmfHDF5WriterDSM(const std::string & filePath, mFAPL(-1), mDSMServerManager(NULL), mDSMServerBuffer(NULL), - mGroupComm(MPI_COMM_NULL), - mServerComm(MPI_COMM_NULL), mWorkerComm(MPI_COMM_NULL), - mStartCoreIndex(-1), - mEndCoreIndex(-1), - mRank(-1), - mGroupSize(-1), mServerMode(false) { H5FDdsmManager * newManager = new H5FDdsmManager(); @@ -137,29 +121,27 @@ XdmfHDF5WriterDSM::XdmfHDF5WriterDSM(const std::string & filePath, // The database/nonthreaded version XdmfHDF5WriterDSM::XdmfHDF5WriterDSM(const std::string & filePath, - XdmfDSMBuffer * const dsmBuffer, - int startCoreIndex, - int endCoreIndex) : + XdmfDSMBuffer * const dsmBuffer) : XdmfHDF5Writer(filePath), mDSMManager(NULL), mDSMBuffer(NULL), mFAPL(-1), mDSMServerManager(NULL), mDSMServerBuffer(dsmBuffer), - mServerMode(true), - mStartCoreIndex(startCoreIndex), - mEndCoreIndex(endCoreIndex) + mServerMode(true) { - mGroupComm = mDSMServerBuffer->GetComm()->GetInterComm(); - MPI_Comm_rank(mGroupComm, &mRank); - MPI_Comm_size(mGroupComm, &mGroupSize); - if (mRank >=mStartCoreIndex && mRank <=mEndCoreIndex) { - mServerComm = mDSMServerBuffer->GetComm()->GetIntraComm(); - mWorkerComm = MPI_COMM_NULL; + mWorkerComm = mDSMServerBuffer->GetComm()->GetIntraComm(); + if (xdmf_dsm_get_manager() == NULL) { + mDSMServerManager = new XdmfDSMManager(); + mDSMServerManager->SetLocalBufferSizeMBytes(mDSMServerBuffer->GetLength()); + mDSMServerManager->SetInterCommType(H5FD_DSM_COMM_MPI); + mDSMServerManager->SetIsServer(false); + mDSMServerManager->SetMpiComm(mDSMServerBuffer->GetComm()->GetIntraComm()); + mDSMServerManager->SetDsmBuffer(mDSMServerBuffer); + XDMF_dsm_set_manager(mDSMServerManager); } else { - mServerComm = MPI_COMM_NULL; - mWorkerComm = mDSMServerBuffer->GetComm()->GetIntraComm(); + static_cast(xdmf_dsm_get_manager())->SetDsmBuffer(mDSMServerBuffer); } } @@ -174,12 +156,17 @@ XdmfHDF5WriterDSM::XdmfHDF5WriterDSM(const std::string & filePath, mDSMBuffer(NULL), mServerMode(true) { + int rank, size; + + MPI_Comm_size(comm, &size); + MPI_Comm_rank(comm, &rank); + // Negative values will be changed to maximum range if (startCoreIndex < 0) { startCoreIndex = 0; } if (endCoreIndex < 0) { - endCoreIndex = mGroupSize - 1; + endCoreIndex = size - 1; } // Ensure start index is less than end index @@ -189,24 +176,19 @@ XdmfHDF5WriterDSM::XdmfHDF5WriterDSM(const std::string & filePath, endCoreIndex = tempholder; } - mGroupComm = comm; - mStartCoreIndex = startCoreIndex; - mEndCoreIndex = endCoreIndex; - - MPI_Comm_size(comm, &mGroupSize); - MPI_Comm_rank(comm, &mRank); + MPI_Comm serverComm; MPI_Group workers, dsmgroup, serversplit, servergroup; - int * ServerIds = (int *)calloc((mEndCoreIndex - mStartCoreIndex + 1), sizeof(int)); + int * ServerIds = (int *)calloc((endCoreIndex - startCoreIndex + 1), sizeof(int)); unsigned int index = 0; - for(int i=mStartCoreIndex ; i <= mEndCoreIndex ; ++i) { + for(int i=startCoreIndex ; i <= endCoreIndex ; ++i) { ServerIds[index++] = i; } MPI_Comm_group(comm, &serversplit); MPI_Group_incl(serversplit, index, ServerIds, &servergroup); - MPI_Comm_create(comm, servergroup, &mServerComm); + MPI_Comm_create(comm, servergroup, &serverComm); MPI_Comm_group(comm, &dsmgroup); MPI_Group_excl(dsmgroup, index, ServerIds, &workers); MPI_Comm_create(comm, workers, &mWorkerComm); @@ -219,30 +201,39 @@ XdmfHDF5WriterDSM::XdmfHDF5WriterDSM(const std::string & filePath, mDSMServerManager->SetLocalBufferSizeMBytes(bufferSize); mDSMServerManager->SetInterCommType(H5FD_DSM_COMM_MPI); - MPI_Barrier(mGroupComm); + MPI_Barrier(comm); - if (mRank >=mStartCoreIndex && mRank <=mEndCoreIndex) { - mDSMServerManager->SetMpiComm(mServerComm); + if (rank >= startCoreIndex && rank <= endCoreIndex) { + mDSMServerManager->SetMpiComm(serverComm); mDSMServerManager->Create(); } else { mDSMServerManager->SetMpiComm(mWorkerComm); mDSMServerManager->SetIsServer(false); - mDSMServerManager->Create(mStartCoreIndex, mEndCoreIndex); + mDSMServerManager->Create(startCoreIndex, endCoreIndex); } XDMF_dsm_set_manager(mDSMServerManager); mDSMServerBuffer = mDSMServerManager->GetDsmBuffer(); - mDSMServerBuffer->GetComm()->DupInterComm(mGroupComm); + mDSMServerBuffer->GetComm()->DupInterComm(comm); mDSMServerBuffer->SetIsConnected(true); + if (startCoreIndex < size) { + if (rank >= startCoreIndex && rank <= endCoreIndex) { + mDSMServerManager->GetDsmBuffer()->ReceiveInfo(); + } + else { + mDSMServerManager->GetDsmBuffer()->SendInfo(); + } + } + MPI_Barrier(comm); // Loop needs to be started before anything can be done to the file, since the service is what sets up the file - if (mRank < mStartCoreIndex || mRank > mEndCoreIndex) { + if (rank < startCoreIndex || rank > endCoreIndex) { // Turn off the server designation mDSMServerBuffer->SetIsServer(H5FD_DSM_FALSE); // If this is set to false then the buffer will attempt to connect to the intercomm for DSM communications @@ -266,14 +257,14 @@ XdmfHDF5WriterDSM::~XdmfHDF5WriterDSM() } -shared_ptr -XdmfHDF5WriterDSM::createHDF5Controller(const std::string & hdf5FilePath, - const std::string & dataSetPath, - const shared_ptr type, - const std::vector & start, - const std::vector & stride, - const std::vector & dimensions, - const std::vector & dataspaceDimensions) +shared_ptr +XdmfHDF5WriterDSM::createController(const std::string & hdf5FilePath, + const std::string & dataSetPath, + const shared_ptr type, + const std::vector & start, + const std::vector & stride, + const std::vector & dimensions, + const std::vector & dataspaceDimensions) { if (mDSMServerBuffer != NULL) { return XdmfHDF5ControllerDSM::New(hdf5FilePath, @@ -283,9 +274,7 @@ XdmfHDF5WriterDSM::createHDF5Controller(const std::string & hdf5FilePath, stride, dimensions, dataspaceDimensions, - mDSMServerBuffer, - mStartCoreIndex, - mEndCoreIndex); + mDSMServerBuffer); } else { return XdmfHDF5ControllerDSM::New(hdf5FilePath, @@ -337,13 +326,6 @@ XdmfDSMBuffer * XdmfHDF5WriterDSM::getServerBuffer() return mDSMServerBuffer; } -MPI_Comm XdmfHDF5WriterDSM::getServerComm() -{ - MPI_Comm returnComm; - int status = MPI_Comm_dup(mServerComm, &returnComm); - return returnComm; -} - XdmfDSMManager * XdmfHDF5WriterDSM::getServerManager() { return mDSMServerManager; @@ -361,6 +343,12 @@ MPI_Comm XdmfHDF5WriterDSM::getWorkerComm() return returnComm; } +void XdmfHDF5WriterDSM::setAllowSetSplitting(bool newAllow) +{ + //overrides to disable the parent version + XdmfHDF5Writer::setAllowSetSplitting(false); +} + void XdmfHDF5WriterDSM::setBuffer(H5FDdsmBuffer * newBuffer) { mDSMBuffer = newBuffer; @@ -385,34 +373,6 @@ void XdmfHDF5WriterDSM::setManager(XdmfDSMManager * newManager) mDSMServerBuffer = newBuffer; } -void XdmfHDF5WriterDSM::setServerComm(MPI_Comm comm) -{ - int status; - if (mServerComm != MPI_COMM_NULL) { - status = MPI_Comm_free(&mServerComm); - if (status != MPI_SUCCESS) { - try { - XdmfError::message(XdmfError::FATAL, "Failed to disconnect Comm"); - } - catch (XdmfError e) { - throw e; - } - } - } - if (comm != MPI_COMM_NULL) { - status = MPI_Comm_dup(comm, &mServerComm); - if (status != MPI_SUCCESS) { - try { - XdmfError::message(XdmfError::FATAL, "Failed to duplicate Comm"); - } - catch (XdmfError e) { - throw e; - } - } - } - mDSMServerBuffer->GetComm()->DupComm(comm); -} - void XdmfHDF5WriterDSM::setServerMode(bool newMode) { mServerMode = newMode; @@ -449,7 +409,7 @@ void XdmfHDF5WriterDSM::setWorkerComm(MPI_Comm comm) void XdmfHDF5WriterDSM::stopDSM() { // Send manually - for (int i = mStartCoreIndex; i <= mEndCoreIndex; ++i) { + for (int i = mDSMServerBuffer->GetStartServerId(); i <= mDSMServerBuffer->GetEndServerId(); ++i) { try { mDSMServerBuffer->SendCommandHeader(H5FD_DSM_OPCODE_DONE, i, 0, 0, H5FD_DSM_INTER_COMM); } @@ -461,7 +421,7 @@ void XdmfHDF5WriterDSM::stopDSM() void XdmfHDF5WriterDSM::restartDSM() { - if (mRank >= mStartCoreIndex && mRank <= mEndCoreIndex) { + if (mDSMServerBuffer->GetComm()->GetInterId() >= mDSMServerBuffer->GetStartServerId() && mDSMServerBuffer->GetComm()->GetInterId() <= mDSMServerBuffer->GetEndServerId()) { H5FDdsmInt32 returnOpCode; try { mDSMServerBuffer->BufferServiceLoop(&returnOpCode); diff --git a/core/XdmfHDF5WriterDSM.hpp b/core/XdmfHDF5WriterDSM.hpp index f8c1550f..51d015a5 100644 --- a/core/XdmfHDF5WriterDSM.hpp +++ b/core/XdmfHDF5WriterDSM.hpp @@ -176,15 +176,11 @@ public: * * @param filePath The location of the hdf5 file to output to on disk. * @param dsmBuffer The Buffer to write to. - * @param startCoreIndex The index of the first core in the server block - * @param endCoreIndex The index of the last core in the server block. * @return a New XdmfHDF5WriterDSM */ static shared_ptr New(const std::string & filePath, - XdmfDSMBuffer * const dsmBuffer, - int startCoreIndex, - int endCoreIndex); + XdmfDSMBuffer * const dsmBuffer); /** * Contruct XdmfHDF5WriterDSM, nonthreaded version @@ -354,36 +350,6 @@ public: */ XdmfDSMBuffer * getServerBuffer(); - /** - * Gets the communicator that the servers use to communicate between themselves. - * Will be MPI_COMM_NULL on worker cores. - * - * Example of use: - * - * C++ - * - * @dontinclude ExampleXdmfDSMNoThread.cpp - * @skipline size - * @until MPI_Comm_size - * @skipline exampleWriter - * @skipline if - * @until { - * @skipline getServerComm - * @skip Section - * @skipline } - * - * Python - * - * @dontinclude XdmfExampleDSMNoThread.py - * @skipline total - * @until exampleWriter - * @skipline if - * @skipline getServerComm - * - * @return The comm that the servers are using. - */ - MPI_Comm getServerComm(); - /** * Gets the manager for the non-threaded version of DSM * @@ -473,6 +439,18 @@ public: */ MPI_Comm getWorkerComm(); + /** + * Sets whether to allow the HDF5 writer to split data sets when writing to hdf5. + * Splitting should only occur for massive data sets. + * Setting to false assures compatibility with previous editions. + * Default setting is false + * In DSM this function has no effect because splitting would prevent the algorithm from working + * + * + * @param newAllow whether to allow data sets to be split across hdf5 files + */ + void setAllowSetSplitting(bool newAllow); + /** * Sets the Writer's dsmBuffer to the provided buffer * @@ -614,36 +592,6 @@ public: * @param newManager A pointer the the manager to be set. */ void setManager(XdmfDSMManager * newManager); - /** - * Sets the comm that the servers will use to communicate with the other server cores. - * - * Example of use: - * - * C++ - * - * @dontinclude ExampleXdmfDSMNoThread.cpp - * @skipline size - * @until MPI_Comm_size - * @skipline exampleWriter - * @skipline if - * @until { - * @skipline getServerComm - * @until setServerComm - * @skip Section - * @skipline } - * - * Python - * - * @dontinclude XdmfExampleDSMNoThread.py - * @skipline total - * @until exampleWriter - * @skipline if - * @skipline getServerComm - * @skipline setServerComm - * - * @param comm The communicator that the server will be using to communicate with the other server cores. - */ - void setServerComm(MPI_Comm comm); /** * Used to switch between server and threaded mode. @@ -780,9 +728,7 @@ protected: unsigned int bufferSize); XdmfHDF5WriterDSM(const std::string & filePath, - XdmfDSMBuffer * const dsmBuffer, - int startCoreIndex, - int endCoreIndex); + XdmfDSMBuffer * const dsmBuffer); XdmfHDF5WriterDSM(const std::string & filePath, MPI_Comm comm, @@ -790,8 +736,8 @@ protected: int startCoreIndex, int endCoreIndex); - virtual shared_ptr - createHDF5Controller(const std::string & hdf5FilePath, + virtual shared_ptr + createController(const std::string & hdf5FilePath, const std::string & dataSetPath, const shared_ptr type, const std::vector & start, @@ -810,13 +756,7 @@ private: XdmfDSMBuffer * mDSMServerBuffer; XdmfDSMManager * mDSMServerManager; - MPI_Comm mGroupComm; - MPI_Comm mServerComm; MPI_Comm mWorkerComm; - int mStartCoreIndex; - int mEndCoreIndex; - int mRank; - int mGroupSize; bool mServerMode; }; diff --git a/core/XdmfHeavyDataWriter.cpp b/core/XdmfHeavyDataWriter.cpp index d0910fc1..38b4a5af 100644 --- a/core/XdmfHeavyDataWriter.cpp +++ b/core/XdmfHeavyDataWriter.cpp @@ -22,18 +22,34 @@ /*****************************************************************************/ #include "XdmfHeavyDataWriter.hpp" +#include "XdmfHeavyDataController.hpp" +#include "XdmfArray.hpp" +#include "XdmfArrayType.hpp" +#include "XdmfError.hpp" #include "XdmfSystemUtils.hpp" +#include +#include -XdmfHeavyDataWriter::XdmfHeavyDataWriter() : +XdmfHeavyDataWriter::XdmfHeavyDataWriter(const double compression, const unsigned int overhead) : + mAllowSplitDataSets(false), + mCompressionRatio(compression), mDataSetId(0), + mFileIndex(0), + mFileOverhead(overhead), mFilePath(""), + mFileSizeLimit(0), mMode(Default) { } -XdmfHeavyDataWriter::XdmfHeavyDataWriter(const std::string & filePath) : +XdmfHeavyDataWriter::XdmfHeavyDataWriter(const std::string & filePath, const double compression, const unsigned int overhead) : + mAllowSplitDataSets(false), + mCompressionRatio(compression), mDataSetId(0), + mFileIndex(0), + mFileOverhead(overhead), mFilePath(XdmfSystemUtils::getRealPath(filePath)), + mFileSizeLimit(0), mMode(Default), mReleaseData(false) { @@ -43,12 +59,1189 @@ XdmfHeavyDataWriter::~XdmfHeavyDataWriter() { } +void +XdmfHeavyDataWriter::controllerSplitting(XdmfArray & array, + const int fapl, + int & controllerIndexOffset, + shared_ptr heavyDataController, + std::string checkFileName, + std::string checkFileExt, + std::string dataSetPath, + std::vector dimensions, + std::vector dataspaceDimensions, + std::vector start, + std::vector stride, + std::list & filesWritten, + std::list > & arraysWritten, + std::list > & startsWritten, + std::list > & stridesWritten, + std::list > & dimensionsWritten, + std::list > & dataSizesWritten, + std::list & arrayOffsetsWritten) +{ + // This is the file splitting algorithm + if (getFileSizeLimit() > 0) { + // Only if the file limit is positive, disabled if 0 or negative + unsigned int previousDataSize = 0; + + std::vector previousDimensions; + std::vector previousDataSizes; + unsigned int amountAlreadyWritten = 0; + // Even though theoretically this could be an infinite loop + // if all possible files with the specified name are produced + // the chances of that happening are small. + // It can handle up to 65535 different files. + // This value may vary depending on the compiler and platform. + // The variable UINT_MAX holds the value in question. + // If all files are take up it will loop until a file opens up + // since adding past the max causes overflow. + + unsigned int containedInController = 1; + for (unsigned int j = 0; j < dataspaceDimensions.size(); ++j) { + containedInController *= dataspaceDimensions[j]; + } + int hyperslabSize = 0; + while (amountAlreadyWritten < containedInController) { + + std::vector partialStarts; + std::vector partialStrides; + std::vector partialDimensions; + std::vector partialDataSizes; + + std::stringstream testFile; + if (getFileIndex() == 0) { + // If sequentially named files need to be created or referenced + testFile << checkFileName << "." << checkFileExt; + } + else { + testFile << checkFileName << getFileIndex() << "." << checkFileExt; + } + FILE *checkFile = NULL; + unsigned int fileSize = 0; + // If the file doesn't exist the size is 0 because there's no data + // Get the file stream + checkFile = fopen(testFile.str().c_str(), "a"); + if (checkFile != NULL) { + // Set the file pointer to end of file + fseek(checkFile, 0, SEEK_END); + // Get the file size, in bytes + fileSize = ftell(checkFile); + + // If overwrite subtract previous data size. + if (mMode == Overwrite || mMode == Hyperslab) { + // Find previous data size + int checksize = getDataSetSize(testFile.str(), dataSetPath, fapl); + if (checksize < 0) { + checksize = 0; + } + if (mMode == Overwrite) { + if (checksize > fileSize) { + fileSize = 0; + } + else { + fileSize = fileSize - checksize; + // Remove previous set's size, since it's overwritten + } + if (fileSize == 0) { + fileSize += getFileOverhead(); + } + } + else if (mMode == Hyperslab) { + hyperslabSize = checksize; + } + } + if (fileSize == 0) { + fileSize += getFileOverhead(); + } + fclose(checkFile); + } + else if (previousDataSize == 0) { + fileSize += getFileOverhead(); + } + // Check size to see if it's within range + if (array.getArrayType() == XdmfArrayType::String()) { + // Size needed is equal to the dataspaceDimensions if in hyperslab mode + // Otherwise is equal to the size of the written array + unsigned int remainingValues = 0; + unsigned int sizeArrayIndex = 0; + if (mMode == Hyperslab) { + remainingValues += 1; + sizeArrayIndex += 1; + for (unsigned int j = 0; j < dataspaceDimensions[j]; ++j) { + remainingValues *= dataspaceDimensions[j]; + sizeArrayIndex *= dimensions[j]; + } + } + else { + remainingValues += array.getSize(); + sizeArrayIndex = amountAlreadyWritten; + } + remainingValues -= amountAlreadyWritten; + // Reduce by number of values already written + if (remainingValues == 0) { + // End if no remaining values + break; + } + // If remaining size is less than available space, just write all of what's left + // Calculate remaining size + unsigned int remainingSize = 0; + for (unsigned int j = sizeArrayIndex; j < array.getSize(); ++j) { + remainingSize += array.getValue(j).size() * 8 * mCompressionRatio; + } + if (mMode == Hyperslab) { + // Size is estimated based on averages + remainingSize = (remainingSize / + (array.getSize() - sizeArrayIndex)) * + remainingValues; + } + if (remainingSize + previousDataSize + fileSize + < getFileSizeLimit()*(1024*1024)) { + // If the array hasn't been split + if (amountAlreadyWritten == 0) { + // Just pass all data to the partial vectors + for (unsigned int j = 0; j < dimensions.size(); ++j) { + // Done using a loop so that data is copied, not referenced + partialStarts.push_back(start[j]); + partialStrides.push_back(stride[j]); + partialDimensions.push_back(dimensions[j]); + partialDataSizes.push_back(dataspaceDimensions[j]); + } + } + else { + // If the array has been split + int dimensionIndex = previousDimensions.size() - 1; + // Loop previous dimensions in + int j = 0; + for (j = 0; j < dimensionIndex; ++j) { + partialStarts.push_back(start[j]); + partialStrides.push_back(stride[j]); + partialDimensions.push_back(dimensions[j]); + partialDataSizes.push_back(dataspaceDimensions[j]); + } + if (mMode == Hyperslab) { + int newStart = (start[j] + + stride[j] * previousDimensions[j]) - + previousDataSizes[j]; + while (newStart < 0) { + newStart += stride[j]; + } + partialStarts.push_back(newStart); + // Stride should not change in this algorithm + partialStrides.push_back(stride[j]); + // Total up number of blocks for the higher dimesions + // and subtract the amount already written + unsigned int dimensiontotal = dimensions[j]; + unsigned int dataspacetotal = dataspaceDimensions[j]; + for (unsigned int k = j + 1; k < dimensions.size(); ++k) { + dimensiontotal *= dimensions[k]; + dataspacetotal *= dataspaceDimensions[k]; + } + if (previousDimensions.size() > 0) { + partialDimensions.push_back(dimensiontotal-previousDimensions[j]); + } + else { + partialDimensions.push_back(dimensiontotal); + } + if (previousDataSizes.size() > 0) { + partialDataSizes.push_back(dataspacetotal-previousDataSizes[j]); + } + else { + partialDataSizes.push_back(dataspacetotal); + } + } + else { + // Start and stride are not used outside of hyperslab + partialStarts.push_back(start[j]); + partialStrides.push_back(stride[j]); + // Total up number of blocks for the higher dimesions + // and subtract the amount already written + // Since it isn't hyperslab dimensions + // and dataspacedimensions should be the same + unsigned int dimensiontotal = dimensions[j]; + for (unsigned int k = j + 1; k < dimensions.size(); ++k) { + dimensiontotal *= dimensions[k]; + } + if (previousDimensions.size() > 0) { + partialDimensions.push_back(dimensiontotal-previousDimensions[j]); + } + else { + partialDimensions.push_back(dimensiontotal); + } + if (previousDataSizes.size() > 0) { + partialDataSizes.push_back(dimensiontotal-previousDataSizes[j]); + } + else { + partialDataSizes.push_back(dimensiontotal); + } + } + } + } + else { + // Otherwise, take remaining size and start removing dimensions + // until the dimension block is less, then take a fraction of the dimension + // Calculate the number of values of the data type you're using will fit + unsigned int usableSpace = (getFileSizeLimit()*(1024*1024) - fileSize); + if (previousDataSize + fileSize > getFileSizeLimit()*(1024*1024)) { + usableSpace = 0; + } + usableSpace += hyperslabSize-previousDataSize; + // If the array hasn't been split + if (amountAlreadyWritten == 0) { + // See if it will fit in the next file + // If it will just go to the next file + // Otherwise split it. + if (remainingSize + getFileOverhead() > getFileSizeLimit()*(1024*1024) + && usableSpace > 0) { + if (getAllowSetSplitting()) { + // Figure out the size of the largest block that will fit. + unsigned int blockSizeSubtotal = 0; + unsigned int dimensionSizeTotal = 1; + unsigned int dimensionIndex = 0; + unsigned int previousBlockSize = 0; + // Find the dimension that was split + while (dimensionIndex < dataspaceDimensions.size() + && blockSizeSubtotal <= usableSpace) { + // This is totally different for strings + dimensionSizeTotal *= dimensions[dimensionIndex]; + previousBlockSize = blockSizeSubtotal; + blockSizeSubtotal = 0; + for (unsigned int k = 0; k < dimensionSizeTotal; ++k) { + if (amountAlreadyWritten + k > array.getSize()) { + try { + XdmfError::message(XdmfError::FATAL, + "Error: Invalid Dimension in HDF5 Write.\n"); + } + catch (XdmfError e) { + throw e; + } + } + blockSizeSubtotal += array.getValue(amountAlreadyWritten + k).size(); + } + dimensionIndex++; + } + // It should end on the "blockSizeSubtotal <= usableSpace" statement + // the other half is for backup + // move back one dimension so we're working + // on the dimension that was split, not the one after it + dimensionIndex--; + blockSizeSubtotal = previousBlockSize; + // Determine how many of those blocks will fit + unsigned int numBlocks = usableSpace / blockSizeSubtotal; + // This should be less than the current value for the dimension + // Add dimensions as required + unsigned int j = 0; + for (; j < dimensionIndex; ++j) { + partialStarts.push_back(start[j]); + partialStrides.push_back(stride[j]); + partialDimensions.push_back(dimensions[j]); + partialDataSizes.push_back(dataspaceDimensions[j]); + } + if (start[j] > numBlocks) { + partialStarts.push_back(numBlocks-1); + } + else { + partialStarts.push_back(start[j]); + } + partialStrides.push_back(stride[j]); + partialDataSizes.push_back(numBlocks); + if (dimensions[j] == dataspaceDimensions[j]) { + //this is for non-hyperslab and specific cases of hyperslab + partialDimensions.push_back(numBlocks); + } + else { + // For hyperslab in general + // Determine how many values from the array will fit + // into the blocks being used with the dimensions specified + unsigned int displacement = numBlocks / stride[j]; + if (((int)displacement * (int)stride[j]) + (start[j] % stride[j]) < numBlocks) { + displacement++; + } + displacement -= start[j]/stride[j]; + if (start[j] > numBlocks) { + displacement = 0; + } + if (dimensions[j] <= displacement) { + // If there are less values than there are space for + // just write all of them. + partialDimensions.push_back(dimensions[j]); + } + else { + // Otherwise write what space allows for + partialDimensions.push_back(displacement); + } + } + } + else { + // Just pass all data to the partial vectors + for (unsigned int j = 0; j < dimensions.size(); ++j) { + // Done using a loop so that data is copied, not referenced + partialStarts.push_back(start[j]); + partialStrides.push_back(stride[j]); + partialDimensions.push_back(dimensions[j]); + partialDataSizes.push_back(dataspaceDimensions[j]); + } + } + } + } + else { + // If the array has been split + // This case should not come up often + // as it requires truly gigantic data sets + // See if the remaining data will fit in the next file + // If yes, skip to it + // If no, split + if (remainingSize + getFileOverhead() > getFileSizeLimit()*(1024*1024) + && usableSpace > 0) { + // Figure out the size of the largest block that will fit. + unsigned int blockSizeSubtotal = 0; + unsigned int tempTotal = 0; + unsigned int dimensionSizeTotal = 1; + unsigned int dimensionIndex = 0; + // Find the dimension that was split + while (dimensionIndex < dataspaceDimensions.size() + && blockSizeSubtotal <= usableSpace) { + // This is totally different for strings + dimensionSizeTotal *= dimensions[dimensionIndex]; + tempTotal = blockSizeSubtotal; + blockSizeSubtotal = 0; + for (unsigned int k = 0; k < dimensionSizeTotal; ++k) { + if (amountAlreadyWritten + k > array.getSize()) { + try { + XdmfError::message(XdmfError::FATAL, + "Error: Invalid Dimension in HDF5 Write.\n"); + } + catch (XdmfError e) { + throw e; + } + } + blockSizeSubtotal += array.getValue(amountAlreadyWritten + k).size(); + } + dimensionIndex++; + } + // It should end on the "blockSizeSubtotal <= usableSpace" statement + // the other half is for backup + // Move back one dimension so we're working + // on the dimension that was split, not the one after it + dimensionIndex--; + blockSizeSubtotal = tempTotal; + unsigned int j = 0; + for (; j < dimensionIndex; ++j) { + partialStarts.push_back(start[j]); + partialStrides.push_back(stride[j]); + partialDimensions.push_back(dimensions[j]); + partialDataSizes.push_back(dataspaceDimensions[j]); + } + // Continue if the block is smaller than the available size + if (blockSizeSubtotal <=usableSpace) { + // Find number of blocks that will fit + // This should be less than the current value for the dimension + unsigned int numBlocks = usableSpace / blockSizeSubtotal; + // Add dimensions to the partial vectors + if (mMode == Hyperslab) { + int newStart = (start[j] + + stride[j] * previousDimensions[j]) - + previousDataSizes[j]; + while (newStart < 0) { + newStart += stride[j]; + } + partialStarts.push_back(newStart); + // Stride should not change in this algorithm + partialStrides.push_back(stride[j]); + partialDataSizes.push_back(numBlocks); + // Determine how many values from the array\ + // will fit into the blocks being used + // with the dimensions specified + unsigned int displacement = (numBlocks - newStart) + / stride[j]; + if (((int)displacement * (int)stride[j]) + (newStart % stride[j]) + < numBlocks) { + displacement++; + } + displacement -= newStart/stride[j]; + if (newStart > (int)numBlocks) { + displacement = 0; + } + if ((dimensions[j] - previousDimensions[j]) <= displacement) { + // If there are less values than there are space for + // just write all of them. + partialDimensions.push_back(dimensions[j] - previousDimensions[j]); + } + else { + // Otherwise write what space allows for + partialDimensions.push_back(displacement); + } + } + else { + // Start and stride are only specified in hyperslab + partialStarts.push_back(start[j]); + partialStrides.push_back(stride[j]); + partialDataSizes.push_back(numBlocks); + partialDimensions.push_back(numBlocks); + } + // Place dimensions into previous dimensions for later iterations + } + else { + // If this is larger than usable space, try the next file + // If moving to next file + // just do nothing and pass out of the if statement + // but also check if specified file size is too small + if (getFileSizeLimit()*(1024*1024) + < blockSizeSubtotal) { + // This shouldn't ever trigger + // but it's good to cover ourselves + // and throw an error if the block size won't work + try { + XdmfError::message(XdmfError::FATAL, + "Error: Dimension Block size" + " / Maximum File size mismatch."); + } + catch (XdmfError e) { + throw e; + } + } + } + } + } + // Move to next file + setFileIndex(getFileIndex()+1); + } + } + else { + // If needed split the written array + // into smaller arrays based on dimension blocks + // Working with strings has a more + // resource intensive version of this algorithm + // Size needed is equal to the dataspaceDimensions if in hyperslab mode + // otherwise is equal to the size of the written array + unsigned int remainingValues = 0; + if (mMode == Hyperslab) { + remainingValues += 1; + for (unsigned int j = 0; j < dataspaceDimensions.size(); ++j) { + remainingValues *= dataspaceDimensions[j]; + } + } + else { + remainingValues += 1; + for (unsigned int j = 0; j < dimensions.size(); ++j) { + remainingValues *= dimensions[j]; + } + } + remainingValues -= amountAlreadyWritten; + // Reduce by number of values already written + if (remainingValues == 0) {//end if no remaining values + break; + } + unsigned int dataItemSize = array.getArrayType()->getElementSize() * mCompressionRatio; + // If remaining size is less than available space, just write all of what's left + if ((remainingValues * dataItemSize) + previousDataSize + fileSize + < getFileSizeLimit()*(1024*1024)) { + // If the array hasn't been split + if (amountAlreadyWritten == 0) { + // Just pass all data to the partial vectors + for (unsigned int j = 0; j < dimensions.size(); ++j) { + // Done using a loop so that data is copied, not referenced + partialStarts.push_back(start[j]); + partialStrides.push_back(stride[j]); + partialDimensions.push_back(dimensions[j]); + partialDataSizes.push_back(dataspaceDimensions[j]); + } + } + else { + // If the array has been split + int dimensionIndex = previousDimensions.size() - 1; + // Loop previous dimensions in + int j = 0; + for (j = 0; j < dimensionIndex; ++j) { + partialStarts.push_back(start[j]); + partialStrides.push_back(stride[j]); + partialDimensions.push_back(dimensions[j]); + partialDataSizes.push_back(dataspaceDimensions[j]); + } + if (mMode == Hyperslab) { + int newStart = (start[j] + stride[j] * previousDimensions[j]) + - previousDataSizes[j]; + while (newStart < 0) { + newStart += stride[j]; + } + partialStarts.push_back(newStart); + // Stride should not change in this algorithm + partialStrides.push_back(stride[j]); + // Total up number of blocks for + // the higher dimesions and subtract the amount already written + unsigned int dimensiontotal = dimensions[j]; + unsigned int dataspacetotal = dataspaceDimensions[j]; + for (unsigned int k = j + 1; k < dimensions.size(); ++k) { + dimensiontotal *= dimensions[k]; + dataspacetotal *= dataspaceDimensions[k]; + } + if (previousDimensions.size() > 0) { + partialDimensions.push_back(dimensiontotal-previousDimensions[j]); + } + else { + partialDimensions.push_back(dimensiontotal); + } + if (previousDataSizes.size() > 0) { + partialDataSizes.push_back(dataspacetotal-previousDataSizes[j]); + } + else { + partialDataSizes.push_back(dataspacetotal); + } + } + else { + // Start and stride are not used outside of hyperslab + partialStarts.push_back(start[j]); + partialStrides.push_back(stride[j]); + // Total up number of blocks for + // the higher dimesions and subtract the amount already written + // since it isn't hyperslab dimensions + // and dataspacedimensions should be the same + unsigned int dimensiontotal = dimensions[j]; + for (unsigned int k = j + 1; k < dimensions.size(); ++k) { + dimensiontotal *= dimensions[k]; + } + if (previousDimensions.size() > 0) { + partialDimensions.push_back(dimensiontotal-previousDimensions[j]); + } + else { + partialDimensions.push_back(dimensiontotal); + } + if (previousDataSizes.size() > 0) { + partialDataSizes.push_back(dimensiontotal-previousDataSizes[j]); + } + else { + partialDataSizes.push_back(dimensiontotal); + } + } + } + } + else { + // Otherwise, take remaining size + // and start removing dimensions until the dimension block is less + // then take a fraction of the dimension + // Calculate the number of values of the data type you're using will fit + unsigned int usableSpace = (getFileSizeLimit()*(1024*1024) - + fileSize) / dataItemSize; + if (getFileSizeLimit()*(1024*1024) < fileSize) { + usableSpace = 0; + } + usableSpace += hyperslabSize-previousDataSize; + // If the array hasn't been split + if (amountAlreadyWritten == 0) { + // See if it will fit in the next file + // If it will just go to the next file + // Otherwise split it. + if ((remainingValues * dataItemSize) + getFileOverhead() > + getFileSizeLimit()*(1024*1024) + && usableSpace > 0) { + if (getAllowSetSplitting()) { + // Figure out the size of the largest block that will fit. + unsigned int blockSizeSubtotal = 1; + unsigned int dimensionIndex = 0; + // Find the dimension that was split + while (dimensionIndex < dataspaceDimensions.size() + && blockSizeSubtotal <= usableSpace) { + blockSizeSubtotal *= dataspaceDimensions[dimensionIndex]; + dimensionIndex++; + } + // It should end on the "blockSizeSubtotal <= arrayStartIndex" statement + // the other half is for backup + // Move back one dimension so we're working on the dimension that was split + // not the one after it + dimensionIndex--; + blockSizeSubtotal /= dataspaceDimensions[dimensionIndex]; + // Determine how many of those blocks will fit + unsigned int numBlocks = usableSpace / blockSizeSubtotal; + // This should be less than the current value for the dimension + // Add dimensions as required. + unsigned int j = 0; + for (j = 0; j < dimensionIndex; ++j) { + partialStarts.push_back(start[j]); + partialStrides.push_back(stride[j]); + partialDimensions.push_back(dimensions[j]); + partialDataSizes.push_back(dataspaceDimensions[j]); + } + if (start[j] > numBlocks) { + partialStarts.push_back(numBlocks-1); + } + else { + partialStarts.push_back(start[j]); + } + partialStrides.push_back(stride[j]); + partialDataSizes.push_back(numBlocks); + if (dimensions[j] == dataspaceDimensions[j]) { + // This is for non-hyperslab and specific cases of hyperslab + partialDimensions.push_back(numBlocks); + } + else { + // For hyperslab in general + // Determine how many values from the array will fit + // into the blocks being used with the dimensions specified + unsigned int displacement = numBlocks / stride[j]; + if (((int)displacement * (int)stride[j]) + (start[j] % stride[j]) + < numBlocks) { + displacement++; + } + displacement -= start[j]/stride[j]; + if (start[j] > numBlocks) { + displacement = 0; + } + if (dimensions[j] <= displacement) { + // If there are less values than there are space for, just write all of them. + partialDimensions.push_back(dimensions[j]); + } + else { + // Otherwise write what space allows for + partialDimensions.push_back(displacement); + } + } + } + else { + // Just pass all data to the partial vectors + for (unsigned int j = 0; j < dimensions.size(); ++j) { + // Done using a loop so that data is copied, not referenced + partialStarts.push_back(start[j]); + partialStrides.push_back(stride[j]); + partialDimensions.push_back(dimensions[j]); + partialDataSizes.push_back(dataspaceDimensions[j]); + } + } + } + } + else { + // If the array has been split + // This case should not come up often as it requires truly gigantic data sets + // See if it will fit in the next file + // If it will just go to the next file + // Otherwise split it. + if ((remainingValues * dataItemSize) + getFileOverhead() > + getFileSizeLimit()*(1024*1024) + && usableSpace > 0) { + unsigned int blockSizeSubtotal = 1; + unsigned int dimensionIndex = 0; + // Find the dimension that was split + while (dimensionIndex < dataspaceDimensions.size() + && blockSizeSubtotal <= amountAlreadyWritten) { + blockSizeSubtotal *= dataspaceDimensions[dimensionIndex]; + dimensionIndex++; + } + // It should end on the "blockSizeSubtotal <= arrayStartIndex" statement + // the other half is for backup + // Move back one dimension so we're working on the dimension that was split + // not the one after it + dimensionIndex--; + blockSizeSubtotal /= dataspaceDimensions[dimensionIndex]; + unsigned int j = 0; + for (j = 0; j < dimensionIndex; ++j) { + partialStarts.push_back(start[j]); + partialStrides.push_back(stride[j]); + partialDimensions.push_back(dimensions[j]); + partialDataSizes.push_back(dataspaceDimensions[j]); + } + // Continue if the block is smaller than the available size + if (blockSizeSubtotal <=usableSpace) { + // Find number of blocks that will fit + // This should be less than the current value for the dimension + unsigned int numBlocks = usableSpace / blockSizeSubtotal; + // Add dimensions to the partial vectors + if (mMode == Hyperslab) { + int newStart = (start[j] + stride[j] * previousDimensions[j]) + - previousDataSizes[j]; + while (newStart < 0) { + newStart += stride[j]; + } + partialStarts.push_back(newStart); + // Stride should not change in this algorithm + partialStrides.push_back(stride[j]); + partialDataSizes.push_back(numBlocks); + // Determine how many values from the array will fit + // into the blocks being used + // with the dimensions specified + unsigned int displacement = numBlocks / stride[j]; + if (((int)displacement * (int)stride[j]) + (newStart % stride[j]) < numBlocks) { + displacement++; + } + displacement -= newStart/stride[j]; + if (newStart > (int)numBlocks) { + displacement = 0; + } + if ((dimensions[j] - previousDimensions[j]) <= displacement) { + // If there are less values than there are space for + // just write all of them. + partialDimensions.push_back(dimensions[j] - previousDimensions[j]); + } + else { + // Otherwise write what space allows for + partialDimensions.push_back(displacement); + } + } + else { + // Start and stride are only specified in hyperslab + partialStarts.push_back(start[j]); + partialStrides.push_back(stride[j]); + partialDataSizes.push_back(numBlocks); + partialDimensions.push_back(numBlocks); + } + // Place dimensions into previous dimensions + // for later iterations + } + else { + // If this is larger than usable space, try the next file + // If moving to next file + // just do nothing and pass out of the if statement + // but also check if specified file size is too small + if (getFileSizeLimit()*(1024*1024) < blockSizeSubtotal) { + // This shouldn't ever trigger, but it's good to cover ourselves + // Throw an error if the block size won't work + try { + XdmfError::message(XdmfError::FATAL, + "Error: Dimension Block size" + " / Maximum File size mismatch.\n"); + } + catch (XdmfError e) { + throw e; + } + } + } + } + } + // Move to next file + setFileIndex(getFileIndex()+1); + } + } + + if (partialDimensions.size() > 0) { + // Building the array to be written + int containedInDimensions = 1; + // Count moved + for (unsigned int j = 0 ; j < partialDimensions.size(); ++j) { + containedInDimensions *= partialDimensions[j]; + } + // Starting index + int containedInPriorDimensions = controllerIndexOffset; + int startOffset = 1; + for (unsigned int j = 0; j < previousDimensions.size(); ++j) { + startOffset *= previousDimensions[j]; + } + if (previousDimensions.size() == 0) { + startOffset = 0; + } + containedInPriorDimensions += startOffset; + int dimensionTotal = 1; + for (unsigned int j = 0; j < dimensions.size(); ++j) { + dimensionTotal *= dimensions[j]; + } + if (containedInDimensions > 0) { + shared_ptr partialArray = XdmfArray::New(); + if (array.getArrayType() == XdmfArrayType::Int8()) { + partialArray->initialize(XdmfArrayType::Int8(), 0); + char * movedData = new char[containedInDimensions]; + array.getValues(containedInPriorDimensions, + movedData, + containedInDimensions); + partialArray->insert(0, movedData, containedInDimensions); + delete movedData; + } + else if (array.getArrayType() == XdmfArrayType::Int16()) { + partialArray->initialize(XdmfArrayType::Int16(), 0); + short * movedData = new short[containedInDimensions]; + array.getValues(containedInPriorDimensions, + movedData, + containedInDimensions); + partialArray->insert(0, movedData, containedInDimensions); + delete movedData; + } + else if (array.getArrayType() == XdmfArrayType::Int32()) { + partialArray->initialize(XdmfArrayType::Int32(), 0); + int * movedData = new int[containedInDimensions]; + array.getValues(containedInPriorDimensions, + movedData, + containedInDimensions); + partialArray->insert(0, movedData, containedInDimensions); + delete movedData; + } + else if (array.getArrayType() == XdmfArrayType::Int64()) { + partialArray->initialize(XdmfArrayType::Int64(), 0); + long * movedData = new long[containedInDimensions]; + array.getValues(containedInPriorDimensions, + movedData, + containedInDimensions); + partialArray->insert(0, movedData, containedInDimensions); + delete movedData; + } + else if (array.getArrayType() == XdmfArrayType::Float32()) { + partialArray->initialize(XdmfArrayType::Float32(), 0); + float * movedData = new float[containedInDimensions]; + array.getValues(containedInPriorDimensions, + movedData, + containedInDimensions); + partialArray->insert(0, movedData, containedInDimensions); + delete movedData; + } + else if (array.getArrayType() == XdmfArrayType::Float64()) { + partialArray->initialize(XdmfArrayType::Float64(), 0); + double * movedData = new double[containedInDimensions]; + array.getValues(containedInPriorDimensions, + movedData, + containedInDimensions); + partialArray->insert(0, movedData, containedInDimensions); + delete movedData; + } + else if (array.getArrayType() == XdmfArrayType::UInt8()) { + partialArray->initialize(XdmfArrayType::UInt8(), 0); + unsigned char * movedData = new unsigned char[containedInDimensions]; + array.getValues(containedInPriorDimensions, + movedData, + containedInDimensions); + partialArray->insert(0, movedData, containedInDimensions); + delete movedData; + } + else if (array.getArrayType() == XdmfArrayType::UInt16()) { + partialArray->initialize(XdmfArrayType::UInt16(), 0); + unsigned short * movedData = new unsigned short[containedInDimensions]; + array.getValues(containedInPriorDimensions, + movedData, + containedInDimensions); + partialArray->insert(0, movedData, containedInDimensions); + delete movedData; + } + else if (array.getArrayType() == XdmfArrayType::UInt32()) { + partialArray->initialize(XdmfArrayType::UInt32(), 0); + unsigned int * movedData = new unsigned int[containedInDimensions]; + array.getValues(containedInPriorDimensions, + movedData, + containedInDimensions); + partialArray->insert(0, movedData, containedInDimensions); + delete movedData; + } + else if (array.getArrayType() == XdmfArrayType::String()) { + partialArray->initialize(XdmfArrayType::String(), 0); + for (int j = containedInPriorDimensions; + j < containedInPriorDimensions + containedInDimensions; + ++j) { + partialArray->pushBack(array.getValue(j)); + } + } + arraysWritten.push_back(partialArray); + filesWritten.push_back(testFile.str()); + startsWritten.push_back(partialStarts); + stridesWritten.push_back(partialStrides); + dimensionsWritten.push_back(partialDimensions); + dataSizesWritten.push_back(partialDataSizes); + arrayOffsetsWritten.push_back(containedInPriorDimensions); + } + if (mMode == Hyperslab) { + containedInPriorDimensions -= controllerIndexOffset; + } + if (containedInDimensions + containedInPriorDimensions == dimensionTotal) { + controllerIndexOffset += dimensionTotal; + } + // For hyperslab the space is controlled by the dataspace dimensions + // So use that since the dimensions should be equal + // to the dataspace dimensions in all other variations + // Total up written data space + unsigned int writtenDataSpace = 1; + for (unsigned int j = 0; j < partialDataSizes.size(); ++j) { + writtenDataSpace *= partialDataSizes[j]; + } + amountAlreadyWritten += writtenDataSpace; + // Generate previous dimensions + if (previousDataSizes.size() == 0) { + previousDataSizes = partialDataSizes; + previousDimensions = partialDimensions; + } + else { + // Determine if the sizes match + // If they do, add the top values together + // Otherwise, compress the higher dimensions and then add them + if (previousDimensions.size() == partialDimensions.size()) { + previousDimensions[previousDimensions.size()-1] += + partialDimensions[previousDimensions.size()-1]; + } + else if (previousDimensions.size() < partialDimensions.size()) { + unsigned int overflowDimensions = 1; + for (unsigned int j = previousDimensions.size() - 1; + j < partialDimensions.size(); + ++j) { + overflowDimensions *= partialDimensions[j]; + } + previousDimensions[previousDimensions.size()-1] += overflowDimensions; + } + else if (previousDimensions.size() > partialDimensions.size()) { + unsigned int overflowDimensions = 1; + for (unsigned int j = partialDimensions.size() - 1; + j < previousDimensions.size(); + ++j) { + overflowDimensions *= previousDimensions[j]; + } + previousDimensions.resize(partialDimensions.size()); + previousDimensions[partialDimensions.size()-1] = overflowDimensions; + previousDimensions[previousDimensions.size()-1] += + partialDimensions[previousDimensions.size()-1]; + } + if (previousDataSizes.size() == partialDataSizes.size()) { + previousDataSizes[previousDataSizes.size()-1] += + partialDataSizes[previousDataSizes.size()-1]; + } + else if (previousDataSizes.size() < partialDataSizes.size()) { + unsigned int overflowDataSizes = 1; + for (unsigned int j = previousDataSizes.size() - 1; + j < partialDataSizes.size(); + ++j) { + overflowDataSizes *= partialDataSizes[j]; + } + previousDataSizes[previousDataSizes.size()-1] += overflowDataSizes; + } + else if (previousDataSizes.size() > partialDataSizes.size()) { + unsigned int overflowDataSizes = 1; + for (unsigned int j = partialDataSizes.size() - 1; + j < previousDataSizes.size(); + ++j) { + overflowDataSizes *= previousDataSizes[j]; + } + previousDataSizes.resize(partialDataSizes.size()); + previousDataSizes[partialDataSizes.size()-1] = overflowDataSizes; + previousDataSizes[previousDataSizes.size()-1] += + partialDataSizes[previousDataSizes.size()-1]; + } + } + } + } + + if (mMode == Append) { + // If the written filename is different write add the previous controller + if (*(filesWritten.rbegin()) != heavyDataController->getFilePath()) { + // Should also be different from previous controller + if (filesWritten.size() > 1) { + if (*(filesWritten.rbegin()) != *((filesWritten.rbegin())++)) { + array.insert(heavyDataController); + } + } + else { + array.insert(heavyDataController); + } + } + } + } + else { + // Otherwise work with the full array + shared_ptr partialArray = XdmfArray::New(); + // Need to copy by duplicating the contents of the array + unsigned int j = controllerIndexOffset; + + try { + heavyDataController = + this->createController(heavyDataController->getFilePath(), + heavyDataController->getDataSetPath(), + array.getArrayType(), + start, + stride, + dimensions, + dataspaceDimensions); + } + catch (XdmfError e) { + throw e; + } + + int movedSize = 0; + if (array.getArrayType() == XdmfArrayType::Int8()){ + partialArray->initialize(XdmfArrayType::Int8(), 0); + if ((array.getSize() - controllerIndexOffset) <= + heavyDataController->getSize()) { + movedSize = array.getSize() - controllerIndexOffset; + } + else if (heavyDataController->getSize() < + (array.getSize() - controllerIndexOffset)) { + movedSize = heavyDataController->getSize(); + } + char * movedData = new char[movedSize]; + array.getValues(controllerIndexOffset, movedData, movedSize); + partialArray->insert(0, movedData, movedSize); + j+=movedSize; + delete movedData; + } + else if (array.getArrayType() == XdmfArrayType::Int16()){ + partialArray->initialize(XdmfArrayType::Int16(), 0); + if ((array.getSize() - controllerIndexOffset) <= + heavyDataController->getSize()) { + movedSize = array.getSize() - controllerIndexOffset; + } + else if (heavyDataController->getSize() < + (array.getSize() - controllerIndexOffset)) { + movedSize = heavyDataController->getSize(); + } + short * movedData = new short[movedSize]; + array.getValues(controllerIndexOffset, movedData, movedSize); + partialArray->insert(0, movedData, movedSize); + j+=movedSize; + delete movedData; + } + else if (array.getArrayType() == XdmfArrayType::Int32()){ + partialArray->initialize(XdmfArrayType::Int32(), 0); + if ((array.getSize() - controllerIndexOffset) <= + heavyDataController->getSize()) { + movedSize = array.getSize() - controllerIndexOffset; + } + else if (heavyDataController->getSize() < + (array.getSize() - controllerIndexOffset)) { + movedSize = heavyDataController->getSize(); + } + int * movedData = new int[movedSize]; + array.getValues(controllerIndexOffset, movedData, movedSize); + partialArray->insert(0, movedData, movedSize); + j+=movedSize; + delete movedData; + } + else if (array.getArrayType() == XdmfArrayType::Int64()){ + partialArray->initialize(XdmfArrayType::Int64(), 0); + if ((array.getSize() - controllerIndexOffset) <= + heavyDataController->getSize()) { + movedSize = array.getSize() - controllerIndexOffset; + } + else if (heavyDataController->getSize() < + (array.getSize() - controllerIndexOffset)) { + movedSize = heavyDataController->getSize(); + } + long * movedData = new long[movedSize]; + array.getValues(controllerIndexOffset, movedData, movedSize); + partialArray->insert(0, movedData, movedSize); + j+=movedSize; + delete movedData; + } + else if (array.getArrayType() == XdmfArrayType::Float32()){ + partialArray->initialize(XdmfArrayType::Float32(), 0); + if ((array.getSize() - controllerIndexOffset) <= + heavyDataController->getSize()) { + movedSize = array.getSize() - controllerIndexOffset; + } + else if (heavyDataController->getSize() < + (array.getSize() - controllerIndexOffset)) { + movedSize = heavyDataController->getSize(); + } + float * movedData = new float[movedSize]; + array.getValues(controllerIndexOffset, movedData, movedSize); + partialArray->insert(0, movedData, movedSize); + j+=movedSize; + delete movedData; + } + else if (array.getArrayType() == XdmfArrayType::Float64()){ + partialArray->initialize(XdmfArrayType::Float64(), 0); + if ((array.getSize() - controllerIndexOffset) <= + heavyDataController->getSize()) { + movedSize = array.getSize() - controllerIndexOffset; + } + else if (heavyDataController->getSize() < + (array.getSize() - controllerIndexOffset)) { + movedSize = heavyDataController->getSize(); + } + double * movedData = new double[movedSize]; + array.getValues(controllerIndexOffset, movedData, movedSize); + partialArray->insert(0, movedData, movedSize); + j+=movedSize; + delete movedData; + } + else if (array.getArrayType() == XdmfArrayType::UInt8()){ + partialArray->initialize(XdmfArrayType::UInt8(), 0); + if ((array.getSize() - controllerIndexOffset) <= + heavyDataController->getSize()) { + movedSize = array.getSize() - controllerIndexOffset; + } + else if (heavyDataController->getSize() < + (array.getSize() - controllerIndexOffset)) { + movedSize = heavyDataController->getSize(); + } + unsigned char * movedData = new unsigned char[movedSize]; + array.getValues(controllerIndexOffset, movedData, movedSize); + partialArray->insert(0, movedData, movedSize); + j+=movedSize; + delete movedData; + } + else if (array.getArrayType() == XdmfArrayType::UInt16()){ + partialArray->initialize(XdmfArrayType::UInt16(), 0); + if ((array.getSize() - controllerIndexOffset) <= + heavyDataController->getSize()) { + movedSize = array.getSize() - controllerIndexOffset; + } + else if (heavyDataController->getSize() < + (array.getSize() - controllerIndexOffset)) { + movedSize = heavyDataController->getSize(); + } + unsigned short * movedData = new unsigned short[movedSize]; + array.getValues(controllerIndexOffset, movedData, movedSize); + partialArray->insert(0, movedData, movedSize); + j+=movedSize; + delete movedData; + } + else if (array.getArrayType() == XdmfArrayType::UInt32()) { + partialArray->initialize(XdmfArrayType::UInt32(), 0); + if ((array.getSize() - controllerIndexOffset) <= + heavyDataController->getSize()) { + movedSize = array.getSize() - controllerIndexOffset; + } + else if (heavyDataController->getSize() < + (array.getSize() - controllerIndexOffset)) { + movedSize = heavyDataController->getSize(); + } + unsigned int * movedData = new unsigned int[movedSize]; + array.getValues(controllerIndexOffset, movedData, movedSize); + partialArray->insert(0, movedData, movedSize); + j+=movedSize; + delete movedData; + } + else if (array.getArrayType() == XdmfArrayType::String()) { + // closeDatatype is only true if strings are being used + partialArray->initialize(XdmfArrayType::String(), 0); + // Transfering via loop because the getValues function is not fully tested with strings + for (j = controllerIndexOffset; + j < controllerIndexOffset + heavyDataController->getSize() + && j < array.getSize(); + ++j){ + partialArray->pushBack(array.getValue(j)); + } + } + arrayOffsetsWritten.push_back(controllerIndexOffset); + // Set the offset to the point after the end of the current subset + controllerIndexOffset = j; + + arraysWritten.push_back(partialArray); + filesWritten.push_back(heavyDataController->getFilePath()); + // Also need to push the starts and strides loaded from the HeavyDataController + startsWritten.push_back(start); + stridesWritten.push_back(stride); + dimensionsWritten.push_back(dimensions); + dataSizesWritten.push_back(dataspaceDimensions); + } +} + +int +XdmfHeavyDataWriter::getAllowSetSplitting() +{ + return mAllowSplitDataSets; +} + +int +XdmfHeavyDataWriter::getFileIndex() +{ + return mFileIndex; +} + +unsigned int +XdmfHeavyDataWriter::getFileOverhead() +{ + return mFileOverhead; +} + std::string XdmfHeavyDataWriter::getFilePath() const { return mFilePath; } +int +XdmfHeavyDataWriter::getFileSizeLimit() +{ + return mFileSizeLimit; +} + XdmfHeavyDataWriter::Mode XdmfHeavyDataWriter::getMode() const { @@ -61,6 +1254,24 @@ XdmfHeavyDataWriter::getReleaseData() const return mReleaseData; } +void +XdmfHeavyDataWriter::setAllowSetSplitting(bool newAllow) +{ + mAllowSplitDataSets = newAllow; +} + +void +XdmfHeavyDataWriter::setFileIndex(int newSize) +{ + mFileIndex = newSize; +} + +void +XdmfHeavyDataWriter::setFileSizeLimit(int newSize) +{ + mFileSizeLimit = newSize; +} + void XdmfHeavyDataWriter::setMode(const Mode mode) { diff --git a/core/XdmfHeavyDataWriter.hpp b/core/XdmfHeavyDataWriter.hpp index d709aa89..780df14b 100644 --- a/core/XdmfHeavyDataWriter.hpp +++ b/core/XdmfHeavyDataWriter.hpp @@ -30,7 +30,10 @@ class XdmfArray; // Includes #include #include "XdmfCore.hpp" +#include "XdmfArrayType.hpp" +#include "XdmfHeavyDataController.hpp" #include "XdmfVisitor.hpp" +#include /** * @brief Traverses the Xdmf graph and writes heavy data stored in @@ -97,6 +100,91 @@ public: */ virtual void closeFile() = 0; + /** + * + */ + virtual void controllerSplitting(XdmfArray & array, + const int fapl, + int & controllerIndexOffset, + shared_ptr heavyDataController, + std::string checkFileName, + std::string checkFileExt, + std::string dataSetPath, + std::vector dimensions, + std::vector dataspaceDimensions, + std::vector start, + std::vector stride, + std::list & filesWritten, + std::list > & arraysWritten, + std::list > & startsWritten, + std::list > & stridesWritten, + std::list > & dimensionsWritten, + std::list > & dataSizesWritten, + std::list & arrayOffsetsWritten); + + virtual shared_ptr + createController(const std::string & hdf5FilePath, + const std::string & dataSetPath, + const shared_ptr type, + const std::vector & start, + const std::vector & stride, + const std::vector & dimensions, + const std::vector & dataspaceDimensions) = 0; + + /** + * Gets whether the HDF5 Writer is allowed to split data sets when writing to hdf5. + * Splitting should only occur for massive data sets. + * Setting to false assures compatibility with previous editions. + * Default setting is false. + * + * Example of use: + * + * C++ + * + * @dontinclude ExampleXdmfHDF5Writer.cpp + * @skipline newPath + * @until New + * @skipline exampleAllow + * + * Python + * + * @dontinclude XdmfExampleHDF5Writer.py + * @skipline newPath + * @until New + * @skipline exampleAllow + * + * @return whether to allow data sets to be split across hdf5 files + */ + int getAllowSetSplitting(); + + virtual int getDataSetSize(std::string fileName, std::string dataSetName, const int fapl) = 0; + + /** + * Gets the file index. Used when file splitting and incremented whent he current file is full. + * + * C++ + * + * @dontinclude ExampleXdmfHDF5Writer.cpp + * @skipline newPath + * @until New + * @skipline getFileIndex + * + * Python + * + * @dontinclude XdmfExampleHDF5Writer.py + * @skipline newPath + * @until New + * @skipline getFileIndex + * + * @return The current file index. + */ + int getFileIndex(); + + /** + * + */ + unsigned int getFileOverhead(); + /** * Get the path to the heavy data file on disk this writer is writing to. * @@ -119,6 +207,29 @@ public: */ std::string getFilePath() const; + /** + * Gets the file size limit of the HDF5 files produced by the writer in MB. Overflow is pushed to a new HDF5 file. + * + * Example of use: + * + * C++ + * + * @dontinclude ExampleXdmfHDF5Writer.cpp + * @skipline newPath + * @until New + * @skipline exampleLimit + * + * Python + * + * @dontinclude XdmfExampleHDF5Writer.py + * @skipline newPath + * @until New + * @skipline exampleLimit + * + * @return The size limit in MB + */ + int getFileSizeLimit(); + /** * Get the Mode of operation for this writer. * @@ -194,6 +305,79 @@ public: */ virtual void openFile() = 0; + /** + * Sets whether to allow the HDF5 writer to split data sets when writing to hdf5. + * Splitting should only occur for massive data sets. + * Setting to false assures compatibility with previous editions. + * Default setting is false + * + * Example of use: + * + * C++ + * + * @dontinclude ExampleXdmfHDF5Writer.cpp + * @skipline newPath + * @until New + * @skipline newAllow + * @until setAllow + * + * Python + * + * @dontinclude XdmfExampleHDF5Writer.py + * @skipline newPath + * @until New + * @skipline newAllow + * @until setAllow + * + * @param newAllow whether to allow data sets to be split across hdf5 files + */ + void setAllowSetSplitting(bool newAllow); + + /** + * Sets the file index. Used when file splitting and incremented when the current file is full. Set to 0 before using hyperslab or overwrite. + * + * C++ + * + * @dontinclude ExampleXdmfHDF5Writer.cpp + * @skipline newPath + * @until New + * @skipline newFileIndex + * @until setFileIndex + * + * Python + * + * @dontinclude XdmfExampleHDF5Writer.py + * @skipline newPath + * @until New + * @skipline newFileIndex + * @until setFileIndex + * + * @param newIndex The index that the writer will append to the file name when incorperating file splitting + */ + void setFileIndex(int newIndex); + + /** + * Sets the file size limit of the HDF5 files produced by the writer in MB. Overflow is pushed to a new HDF5 file. + * Using with arrays of string type may reduce performance. + * + * Example of use: + * + * C++ + * + * @dontinclude ExampleXdmfHDF5Writer.cpp + * @skipline newPath + * @until setFileSizeLimit + * + * Python + * + * @dontinclude XdmfExampleHDF5Writer.py + * @skipline newPath + * @until setFileSizeLimit + * + * @param newSize The size limit in MB + */ + void setFileSizeLimit(int newSize); + /** * Set the mode of operation for this writer. * @@ -265,13 +449,18 @@ public: protected: - XdmfHeavyDataWriter(); - XdmfHeavyDataWriter(const std::string & filePath); + XdmfHeavyDataWriter(const double compression = 1, const unsigned int overhead = 0); + XdmfHeavyDataWriter(const std::string & filePath, const double compression = 1, const unsigned int overhead = 0); + bool mAllowSplitDataSets; int mDataSetId; + int mFileIndex; std::string mFilePath; + unsigned int mFileSizeLimit; Mode mMode; bool mReleaseData; + double mCompressionRatio; + unsigned int mFileOverhead; private: diff --git a/core/tests/Cxx/TestXdmfArray.cpp b/core/tests/Cxx/TestXdmfArray.cpp index abafb054..b7c6149c 100644 --- a/core/tests/Cxx/TestXdmfArray.cpp +++ b/core/tests/Cxx/TestXdmfArray.cpp @@ -322,5 +322,58 @@ int main(int, char **) int num = stringArray->getValue(3); assert(num == 1); + /** + * ArrayType compatibility + */ + std::vector > typeVector; + typeVector.push_back(XdmfArrayType::Int8()); + typeVector.push_back(XdmfArrayType::Int16()); + typeVector.push_back(XdmfArrayType::Int32()); + typeVector.push_back(XdmfArrayType::Int64()); + typeVector.push_back(XdmfArrayType::UInt8()); + typeVector.push_back(XdmfArrayType::UInt16()); + typeVector.push_back(XdmfArrayType::UInt32()); + typeVector.push_back(XdmfArrayType::Float32()); + typeVector.push_back(XdmfArrayType::Float64()); + typeVector.push_back(XdmfArrayType::String()); + + for (unsigned int i = 0; i < typeVector.size(); ++i) { + for (unsigned int j = 0; j < typeVector.size(); ++j) { + shared_ptr valTypeArray1 = XdmfArray::New(); + shared_ptr valTypeArray2 = XdmfArray::New(); + shared_ptr valType1 = typeVector[i]; + shared_ptr valType2 = typeVector[j]; + valTypeArray1->initialize(valType1); + valTypeArray2->initialize(valType2); + valTypeArray1->pushBack(-1.25); + valTypeArray2->pushBack(-1.25); + shared_ptr valIntersectArray = XdmfArray::New(); + shared_ptr valIntersectType = XdmfArrayType::comparePrecision(typeVector[i], typeVector[j]); + valIntersectArray->initialize(valIntersectType); + valIntersectArray->insert(0, valTypeArray1, 0, 1, 1); + valIntersectArray->insert(1, valTypeArray2, 0, 1, 1); + std::stringstream output1; + std::stringstream output2; + if (valType1 == XdmfArrayType::Int8() && valType2 == XdmfArrayType::String()) { + output1 << valTypeArray1->getValue(0) << " " << valTypeArray2->getValuesString() << std::endl; + } + else if (valType1 == XdmfArrayType::UInt8() && valType2 == XdmfArrayType::String()) { + output1 << valTypeArray1->getValue(0) << " " << valTypeArray2->getValuesString() << std::endl; + } + else if (valType2 == XdmfArrayType::Int8() && valType1 == XdmfArrayType::String()) { + output1 << valTypeArray1->getValuesString() << " " << valTypeArray2->getValue(0) << std::endl; + } + else if (valType2 == XdmfArrayType::UInt8() && valType1 == XdmfArrayType::String()) { + output1 << valTypeArray1->getValuesString() << " " << valTypeArray2->getValue(0) << std::endl; + } + else { + output1 << valTypeArray1->getValuesString() << " " << valTypeArray2->getValuesString() << std::endl; + } + output2 << valIntersectArray->getValuesString() << std::endl; + //std::cout << output1.str() << output2.str(); + assert(output1.str() == output2.str()); + } + } + return 0; } diff --git a/core/tests/Cxx/TestXdmfHDF5WriterDSM.cpp b/core/tests/Cxx/TestXdmfHDF5WriterDSM.cpp index 60db98f6..d2ed8f8f 100644 --- a/core/tests/Cxx/TestXdmfHDF5WriterDSM.cpp +++ b/core/tests/Cxx/TestXdmfHDF5WriterDSM.cpp @@ -92,7 +92,7 @@ int main(int argc, char *argv[]) std::vector(1, 1), std::vector(1, size*3), std::vector(1, size*3), - NULL); + dsmBuffer); array->setHeavyDataController(fullController); array->release(); array->read(); diff --git a/examples/Cxx/DSMLoopTest.cpp b/examples/Cxx/DSMLoopTest.cpp index d3b0096d..61236289 100644 --- a/examples/Cxx/DSMLoopTest.cpp +++ b/examples/Cxx/DSMLoopTest.cpp @@ -120,9 +120,7 @@ int main(int argc, char *argv[]) writeStrideVector, writeCountVector, writeDataSizeVector, - exampleWriter->getServerBuffer(), - size-numServersCores, - size-1); + exampleWriter->getServerBuffer()); testArray->insert(writeController); @@ -139,10 +137,7 @@ int main(int argc, char *argv[]) readStrideVector, readCountVector, readDataSizeVector, - exampleWriter->getServerBuffer(), - size-numServersCores, - size-1); - + exampleWriter->getServerBuffer()); readArray->insert(readController); for (unsigned int i = 0; igetServerBuffer(), - size-numServersCores, - size-1); + exampleWriter->getServerBuffer()); readArray->insert(readController); @@ -189,9 +182,7 @@ int main(int argc, char *argv[]) readStrideVector, readOutputCountVector, readDataSizeVector, - exampleWriter->getServerBuffer(), - size-numServersCores, - size-1);; + exampleWriter->getServerBuffer()); writeStartVector.push_back(0); writeStrideVector.push_back(1); @@ -205,9 +196,7 @@ int main(int argc, char *argv[]) writeStrideVector, writeCountVector, writeDataSizeVector, - exampleWriter->getServerBuffer(), - size-numServersCores, - size-1); + exampleWriter->getServerBuffer()); testArray->insert(writeController); } diff --git a/examples/Cxx/ExampleXdmfArray.cpp b/examples/Cxx/ExampleXdmfArray.cpp index d5dfb855..56553845 100644 --- a/examples/Cxx/ExampleXdmfArray.cpp +++ b/examples/Cxx/ExampleXdmfArray.cpp @@ -3,46 +3,120 @@ #include #include +//#declarefunction begin + shared_ptr maximum(std::vector > values); + +//#declarefunction end + +//#declareoperation begin + shared_ptr prepend(shared_ptr val1, shared_ptr val2); +//#declareoperation end + +//#programstart begin + int main(int, char **) { + + //#programstart end + + //#initialization begin + shared_ptr exampleArray = XdmfArray::New(); - //Assuming that exampleArray is a shared pointer to an XdmfArray object + + //#initialization end + + //#setName begin std::string newName = "New Name"; exampleArray->setName(newName); + //#setName end + + //#sizedeclaration begin + int newSize = 10; + + //#sizedelcaration end + + //#reserve begin + exampleArray->reserve(newSize); + + //#reserve end + + //#initializesingletemplate begin + shared_ptr > exampleVector = exampleArray->initialize(newSize); + + //#initializesingletemplate end + + //#initializesingletype begin + exampleArray->initialize(XdmfArrayType::Int32(), newSize); + //#initializesingletype end + + //#sizevectordeclaration begin + std::vector newSizeVector; newSizeVector.push_back(4); newSizeVector.push_back(5); + + //#sizevectordelcaration end + + //#initializevectortemplate begin + shared_ptr > exampleVectorFromVector = exampleArray->initialize(newSizeVector); + + //#initializevectortemplate end + + //#initializevectortype begin + exampleArray->initialize(XdmfArrayType::Int32(), newSize); + //#initializevectortype end + + //#isInitialized begin + if (exampleArray->isInitialized()) { //do whatever is to be done if the array is initialized } + //#isInitialized end + + //#read begin + if (!exampleArray->isInitialized()) { exampleArray->read(); } + //#read end + + //#datapointersetup begin + int initArray [10] = {0,1,2,3,4,5,6,7,8,9}; - shared_ptr tempArray = XdmfArray::New(); + + //#datapointersetup end + + //#pointerinsert begin + exampleArray->insert(0, initArray, 10, 1, 1); //exampleArray now contains {0,1,2,3,4,5,6,7,8,9} exampleArray->insert(0, initArray, 5, 2, 1); //exampleArray now contains {0,1,1,3,2,5,3,7,4,9} exampleArray->insert(0, initArray, 5, 1, 2); //exampleArray now contains {0,2,4,6,8,5,3,7,4,9} + + //#pointerinsert end + + //#arrayinsert begin + + shared_ptr tempArray = XdmfArray::New(); tempArray->insert(0, exampleArray, 0, 10, 1, 1); //tempArray now contains {0,1,2,3,4,5,6,7,8,9} tempArray->insert(0, exampleArray, 0, 5, 2, 1); @@ -50,29 +124,88 @@ int main(int, char **) tempArray->insert(0, exampleArray, 0, 5, 1, 2); //tempArray now contains {0,2,4,6,8,5,3,7,4,9} - int newIndex = 0; + //#arrayinsert end + + //#pointinsertvalues begin + double newValue = 3.5; + + //#pointinsertvalues end + + //#pushBack begin + exampleArray->pushBack(newValue); - exampleArray->insert(newIndex, newValue);//the value of 3.5 is inserted at index 0 + + //#pushBack end + + //#pointinsert begin + + int newIndex = 0; + exampleArray->insert(newIndex, newValue); + //the value of 3.5 is inserted at index 0 + + //#pointinsert end + + //#setValuesInternalpointer begin exampleArray->setValuesInternal(initArray, 10, 1); + //#setValuesInternalpointer end + + //#initinternalvector begin + std::vector initVector; initVector.push_back(1); initVector.push_back(2); initVector.push_back(3); initVector.push_back(4); initVector.push_back(5); + + //#initinternalvector end + + //#setValuesInternalvector begin + exampleArray->setValuesInternal(initVector, 1); + //#setValuesInternalvector end + + //#initsharedvector begin + shared_ptr > storeVector(&initVector); + + //#initsharedvector end + + //#setValuesInternalsharedvector begin + exampleArray->setValuesInternal(storeVector); + //#setValuesInternalsharedvector end + + //#setarraybase begin + + exampleArray->insert(0, initArray, 10, 1, 1); + //exampleArray now contains {0,1,2,3,4,5,6,7,8,9} + + //#setarraybase end + + //#swapvector begin + //The vector contains {1,2,3,4,5} and the XdmfArray contains {0,1,2,3,4,5,6,7,8,9} bool swapSucceded = exampleArray->swap(initVector); //The vector contains {0,1,2,3,4,5,6,7,8,9} and the XdmfArray contains {1,2,3,4,5} + + //#swapvector end + + //#swapsharedvector begin + + //The vector contains {1,2,3,4,5} and the XdmfArray contains {0,1,2,3,4,5,6,7,8,9} bool storeSwapSucceded = exampleArray->swap(storeVector); //storeVector contains {0,1,2,3,4,5,6,7,8,9} and the XdmfArray contains {1,2,3,4,5} + + //#swapsharedvector end + + //#swaparray begin + shared_ptr swapArray = XdmfArray::New(); int initArray2 [5] = {1,2,3,4,5}; swapArray->insert(0, initArray2, 5, 1, 1); @@ -80,8 +213,16 @@ int main(int, char **) exampleArray->swap(swapArray); //Now exampleArray contains {1,2,3,4,5} and swapArray contains {0,1,2,3,4,5,6,7,8,9} + //#swaparray end + + //#clear begin + exampleArray->clear(); + //#clear end + + //#getValues begin + int storeArray [10] = {0,1,2,3,4,5,6,7,8,9}; exampleArray->insert(0, storeArray, 10, 1, 1); int readArray [10] = {10, 11, 12, 13, 14, 15, 16, 17, 18, 19}; @@ -90,6 +231,10 @@ int main(int, char **) exampleArray->getValues(0, readArray, 5, 2, 1); //readArray now contains {0, 2, 4, 6, 8, 15, 3, 17, 4, 19} + //#getValues end + + //#resizesingle begin + newSize = 20; int baseValue = 1; exampleArray->resize(newSize, baseValue); @@ -98,56 +243,156 @@ int main(int, char **) exampleArray->resize(newSize, baseValue); //exampleArray now contains {0,1,2,3,4} - exampleArray->resize(newSizeVector, baseValue); + //#resizesingle end + + //#resizevector begin + + std::vector newresizeVector; + newResizeVector.push_back(4); + newResizeVector.push_back(5); + + exampleArray->resize(newResizeVector, baseValue); //exampleArray now contains {0,1,2,3,4,5,6,7,8,9,1,1,1,1,1,1,1,1,1,1} - newSizeVector[0] = 1; - exampleArray->resize(newSizeVector, baseValue); + newResizeVector[0] = 1; + exampleArray->resize(newResizeVector, baseValue); //exampleArray now contains {0,1,2,3,4} + //#resizevector end + //#getCapacity begin unsigned int exampleCapacity = exampleArray->getCapacity(); + //#getCapacity end + + //#getDimensions begin + std::vector exampleDimensions = exampleArray->getDimensions(); + //#getDimensions end + + //#getDimensionsString begin + std::string exampleDimensionString = exampleArray->getDimensionsString(); + //#getDimensionsString end + + //#getArrayType begin + shared_ptr exampleType = exampleArray->getArrayType(); + //#getArrayType end + + //#getName begin + std::string exampleName = exampleArray->getName(); + //#getName end + + //#getSize begin + unsigned int exampleSize = exampleArray->getSize(); + //#getSize end + + //#setHeavyDataController begin + shared_ptr exampleController = exampleArray->getHeavyDataController(); + + //#getHeavyDataController end + + //#setHeavyDataController begin + shared_ptr newArray = XdmfArray::New(); newArray->setHeavyDataController(exampleController); + + //#setHeavyDataController end + + //#getHeavyDataControllerconst begin + shared_ptr exampleControllerConst = exampleArray->getHeavyDataController(); - //if exampleArray contains [0, 1, 2, 3, 4, 5, 6, 7] + //#getHeavyDataControllerconst end + + //#getValueindex begin + + //if exampleArray contains {0,1,2,3,4,5,6,7,8,9} int exampleValue = exampleArray->getValue(4); //exampleValue now has the value of what was stored at index 4, which in this case is 4 + //#getValueindex end + + //#getValuesString begin + std::string exampleValueString = exampleArray->getValuesString(); - //assuming that exampleArray is filled with ints + //#getValuesString end + + //#getValuesInternalvector begin + shared_ptr > exampleInternalVector = exampleArray->getValuesInternal(); + + //#getValuesInternalvector end + + //#getValuesInternalvoid begin + void * exampleInternalPointer = exampleArray->getValuesInternal(); + + //#getValuesInternalvoid end + + //#getValuesInternalvoidconst begin + const void * exampleInternalPointerConst = exampleArray->getValuesInternal(); - //if exampleArray contains [0, 1, 2, 3, 4, 5, 6, 7] + //#getValuesInternalvoidconst end + + //#erase begin + + //if exampleArray contains {0,1,2,3,4,5,6,7,8,9} unsigned int erasedIndex = 4; exampleArray->erase(erasedIndex); //exampleArray now contains the following - // [0, 1, 2, 3, 5, 6, 7] + // {0,1,2,3,5,6,7,8,9} + + //#erase end + + //#release begin exampleArray->release(); - std::string exampleOperations = XdmfArray::getSupportedOperations(); - std::vector exampleFunctions = XdmfArray::getSupportedFunctions(); - std::string exampleVariableChars = XdmfArray::getValidVariableChars(); - std::string exampleDigitChars = XdmfArray::getValidDigitChars(); + //#release end + + //#getSupportedOperations begin + + std::string exampleOperations = XdmfFunction::getSupportedOperations(); + + //#getSupportedOperations end + + //#getSupportedFunctions begin + + std::vector exampleFunctions = XdmfFunction::getSupportedFunctions(); + + //#getSupportedFunctions end - int examplePriority = XdmfArray::getOperationPriority('|'); + //#getValidVariableChars begin + + std::string exampleVariableChars = XdmfFunction::getValidVariableChars(); + + //#getValidVariableChars end + + //#getValidDigitChars begin + + std::string exampleDigitChars = XdmfFunction::getValidDigitChars(); + + //#getValidDigitChars end + + //#getOperationPriority begin + + int examplePriority = XdmfFunction::getOperationPriority('|'); + + //#getOperationPriority end + + //#valueinit begin shared_ptr valueArray1 = XdmfArray::New(); valueArray1->pushBack(1); @@ -166,23 +411,68 @@ int main(int, char **) shared_ptr answerArray; - answerArray = XdmfArray::sum(valueVector); - answerArray = XdmfArray::ave(valueVector); - answerArray = XdmfArray::chunk(valueArray1, valueArray2); - answerArray = XdmfArray::interlace(valueArray1, valueArray2); + //#valueinit end + + //#sum begin + + answerArray = XdmfFunction::sum(valueVector); + + //#sum end + + //#average begin + + answerArray = XdmfFunction::average(valueVector); + + //#average end + + //#chunk begin + + answerArray = XdmfFunction::chunk(valueArray1, valueArray2); + + //#chunk end + + //#interlace begin + + answerArray = XdmfFunction::interlace(valueArray1, valueArray2); + + //#interlace end - int exampleNumOperations = XdmfArray::addOperation('@', (shared_ptr(*)(shared_ptr, shared_ptr))prepend, 2); - answerArray = XdmfArray::evaluateOperation(valueArray1, valueArray2, '@'); + //#addOperation begin - int exampleNumFunctions = XdmfArray::addFunction("MAX", (shared_ptr(*)(std::vector >))maximum); - answerArray = XdmfArray::evaluateFunction(valueVector, "MAX"); + int exampleNumOperations = XdmfFunction::addOperation('@', (shared_ptr(*)(shared_ptr, shared_ptr))prepend, 2); + + //#addOperation end + + //#evaluateOperation begin + + answerArray = XdmfFunction::evaluateOperation(valueArray1, valueArray2, '@'); + + //#evaluateOperation end + + //#addFunction begin + + int exampleNumFunctions = XdmfFunction::addFunction("MAX", (shared_ptr(*)(std::vector >))maximum); + + //#addFunction end + + //#evaluateFunction begin + + answerArray = XdmfFunction::evaluateFunction(valueVector, "MAX"); + + //#evaluateFunction end + + //#evaluateExpression begin std::map > valueMap; valueMap["A"] = valueArray1; valueMap["B"] = valueArray2; std::string parsedExpression = "MAX(A,B)@(A#B)"; - answerArray = XdmfArray::evaluateExpression(parsedExpression, valueMap); + answerArray = XdmfFunction::evaluateExpression(parsedExpression, valueMap); + + //#evaluateExpression end + + //#insertmultidim begin shared_ptr writtenArray = XdmfArray::New(); std::vector dimensionVector; @@ -220,9 +510,17 @@ int main(int, char **) readArray->insert(readStarts, writtenArray, writeStarts, writeDim, readDim, readStrides, writeStrides); + //#insertmultidim end + + //#programend start + return 0; } +//#programend end + +//#definefunction begin + shared_ptr maximum(std::vector > values) { if (values[0]->getArrayType() == XdmfArrayType::String()) @@ -250,6 +548,10 @@ shared_ptr maximum(std::vector > values) } } +//#definefunction end + +//#defineoperation begin + shared_ptr prepend(shared_ptr val1, shared_ptr val2) { //joins into new array and returns it @@ -258,3 +560,5 @@ shared_ptr prepend(shared_ptr val1, shared_ptr returnArray->insert(val2->getSize(), val1, 0, val1->getSize(), 1, 1); return returnArray; } + +//#defineoperation end diff --git a/examples/Cxx/ExampleXdmfArrayType.cpp b/examples/Cxx/ExampleXdmfArrayType.cpp index 5525f843..7bfa4780 100644 --- a/examples/Cxx/ExampleXdmfArrayType.cpp +++ b/examples/Cxx/ExampleXdmfArrayType.cpp @@ -2,6 +2,8 @@ int main(int, char **) { + //#getType begin + shared_ptr exampleArray = XdmfArray::New(); if (XdmfArrayType::Int8() == exampleArray->getArrayType()) @@ -9,9 +11,25 @@ int main(int, char **) //do whatever is to be done with in the case that the array type is Int8 } + //#getType end + + //#getElementSize begin + unsigned int dataSize = XdmfArrayType::Int8()->getElementSize(); + //#getElementSize end + + //#getName begin + std::string dataName = XdmfArrayType::Int8()->getName(); + //#getName end + + //#comparePrecision begin + + shared_ptr resultType = XdmfArrayType::comparePrecision(XdmfArrayType::Int16(), XdmfArrayType::UInt8()); + + //#comparePrecision end + return 0; } diff --git a/examples/Cxx/ExampleXdmfAttribute.cpp b/examples/Cxx/ExampleXdmfAttribute.cpp index e39940af..3df6762b 100644 --- a/examples/Cxx/ExampleXdmfAttribute.cpp +++ b/examples/Cxx/ExampleXdmfAttribute.cpp @@ -4,16 +4,32 @@ int main(int, char **) { + //#initialization begin shared_ptr exampleAttribute = XdmfAttribute::New(); + //#initialization end //Assuming that exampleAttribute is a shared pointer to an XdmfAttribute object + //#setCenter begin + exampleAttribute->setCenter(XdmfAttributeCenter::Node()); + //#setCenter end + + //#setName begin + std::string newName = "New Name"; exampleAttribute->setName(newName); - exampleAttribute->setType(XdmfAttributeType::Node()); + //#setName end + + //#setType begin + + exampleAttribute->setType(XdmfAttributeType::Scalar()); + + //#setType end + + //#getCenter begin shared_ptr exampleCenter = exampleAttribute->getCenter(); @@ -22,8 +38,16 @@ int main(int, char **) //do whatever is to be done if the center is grid } + //#getCenter end + + //#getName begin + std::string exampleName = exampleAttribute->getName(); + //#getName end + + //#getType begin + shared_ptr exampleType = exampleAttribute->getType(); if (exampleType == XdmfAttributeType:Scalar()) @@ -31,5 +55,7 @@ int main(int, char **) //do whatever is to be done if the attribute is a scalar } + //#getType end + return 0; } diff --git a/examples/Cxx/ExampleXdmfCoreItemFactory.cpp b/examples/Cxx/ExampleXdmfCoreItemFactory.cpp index 178094be..562679d8 100644 --- a/examples/Cxx/ExampleXdmfCoreItemFactory.cpp +++ b/examples/Cxx/ExampleXdmfCoreItemFactory.cpp @@ -3,6 +3,8 @@ int main(int, char **) { + //#createItem begin + //using XdmfItemFactory because XdmfCoreItemFactory is abstract shared_ptr exampleFactory = XdmfItemFactory::New(); std::map newProperties; @@ -14,5 +16,7 @@ int main(int, char **) //childItems and itemProperties are not added to the item when created this way //the collections are used to determine type + //#createItem end + return 0; } diff --git a/examples/Cxx/ExampleXdmfCoreReader.cpp b/examples/Cxx/ExampleXdmfCoreReader.cpp index 58895c06..0a903b3b 100644 --- a/examples/Cxx/ExampleXdmfCoreReader.cpp +++ b/examples/Cxx/ExampleXdmfCoreReader.cpp @@ -6,24 +6,48 @@ int main(int, char **) { + //#initialization begin + //using XdmfReader since XdmfCoreReader is abstract shared_ptr exampleReader = XdmfReader::New(); + //#initialization end + + //#parse begin + std::string readLight = "your light data here"; //Assuming that an XdmfArray is the root item generated by the light data provided shared_ptr exampleArray = shared_dynamic_cast(reader->parse(readLight)); + //#parse end + + //#readpath begin + std::string readPath = "your file path here"; + //#readpath end + + //#readroot begin + //Assuming that an XdmfDomain is the root item at the file path provided shared_ptr exampleDomain = shared_dynamic_cast(reader->read(readPath)); + //#readroot end + + //#readItems begin + std::vector > exampleCollection = reader->readItems(readPath); //Used in a similar manner as read, but in this case the read file has multiple items at the returned level + //#readItems end + + //#readXPath begin + std::string readXPath = "your X path here"; std::vector > exampleItems = reader->read(readPath, readXPath); + //#readXPath end + return 0; } diff --git a/examples/Cxx/ExampleXdmfCurvilinearGrid.cpp b/examples/Cxx/ExampleXdmfCurvilinearGrid.cpp index d6153d1b..391c2b31 100644 --- a/examples/Cxx/ExampleXdmfCurvilinearGrid.cpp +++ b/examples/Cxx/ExampleXdmfCurvilinearGrid.cpp @@ -12,45 +12,83 @@ int main(int, char **) if (size == 2) { + //#initializationdim2 start + unsigned int newPointsX = 5; unsigned int newPointsY = 5; shared_ptr exampleGrid = XdmfCurvilinearGrid::New(newPointsX, newPointsY); - shared_ptr exampleDimensions = exampleGrid->getDimensions(); + + //#initializationdim2 end } else if (size = 3) { + //#initializationdim3 start + unsigned int newPointsX = 5; unsigned int newPointsY = 5; unsigned int newPointsZ = 5; shared_ptr exampleGrid = XdmfCurvilinearGrid::New(newPointsX, newPointsY, newPointsZ); + + //#initializationdim3 end + + //#setDimensions begin + + shared_ptr newPoints = XdmfArray::New(); + newPoints->pushBack(10); + newPoints->pushBack(10); + newPoints->pushBack(10); + exampleGrid->setDimensions(newPoints); + + //#setDimensions end + + //#getDimensions begin + + shared_ptr exampleDimensions = exampleGrid->getDimensions(); + + //#getDimensions end + + //#getDimensionsconst begin + shared_ptr exampleDimensions = exampleGrid->getDimensions(); - shared_ptr newPoints = XdmfArray::New(); - newPoints->pushBack(10); - newPoints->pushBack(10); - newPoints->pushBack(10); - exampleGrid->setDimensions(newPoints); + + //#getDimensionsconst end + + //#setGeometry begin + shared_ptr newData = XdmfArray::New(); newData->pushBack(5); newData->pushBack(5); newData->pushBack(5); shared_ptr newGeometry = XdmfGeometry::New(); newGeometry->setType(XdmfGeometryType::XYZ()); - newGeometry->insert(0, newData, 0, 3, 1, 1);//Start index is 0, 3 values are passed, stride for both arrays is 1 + // Start index is 0, 3 values are passed, stride for both arrays is 1 + newGeometry->insert(0, newData, 0, 3, 1, 1); exampleGrid->setGeometry(newGeometry); + + //#setGeometry end + + //#getGeometry begin + shared_ptr exampleGeometry = exampleGrid->getGeometry(); + //#getGeometry end + } else // via array { + //#initializationvector start + shared_ptr newPoints = XdmfArray::New(); newPoints->pushBack(5); newPoints->pushBack(5); newPoints->pushBack(5); shared_ptr exampleGrid = XdmfCurvilinearGrid::New(newPoints); + //#initializationvector end + } diff --git a/examples/Cxx/ExampleXdmfDSMNoThread.cpp b/examples/Cxx/ExampleXdmfDSMNoThread.cpp index 72755a0a..77238722 100644 --- a/examples/Cxx/ExampleXdmfDSMNoThread.cpp +++ b/examples/Cxx/ExampleXdmfDSMNoThread.cpp @@ -83,23 +83,16 @@ int main(int argc, char *argv[]) if (id < size - numServersCores) { + // This section is to demonstrate the functionality of the XdmfDSM classes exampleWriter->setServerMode(true); bool exampleServerMode = exampleWriter->getServerMode(); - /* - MPI_Comm exampleServerComm = exampleWriter->getServerComm(); - exampleWriter->setServerComm(exampleServerComm); - */ - MPI_Comm exampleWorkerComm = exampleWriter->getWorkerComm(); exampleWriter->setWorkerComm(exampleWorkerComm); /* - MPI_Comm exampleServerComm = exampleController->getServerComm(); - exampleController->setServerComm(exampleServerComm); - MPI_Comm exampleWorkerComm = exampleController->getWorkerComm(); exampleController->setWorkerComm(exampleWorkerComm); */ @@ -112,11 +105,9 @@ int main(int argc, char *argv[]) writeStrideVector, writeCountVector, writeDataSizeVector, - exampleWriter->getServerBuffer(), - size-numServersCores, - size-1); + exampleWriter->getServerBuffer()); - shared_ptr exampleWriter2 = XdmfHDF5WriterDSM::New(newPath, exampleWriter->getServerBuffer(), size-numServersCores, size-1); + shared_ptr exampleWriter2 = XdmfHDF5WriterDSM::New(newPath, exampleWriter->getServerBuffer()); writeController->setServerMode(true); bool exampleControllerServerMode = writeController->getServerMode(); @@ -162,10 +153,12 @@ int main(int argc, char *argv[]) exampleBuffer = exampleWriter->getServerBuffer(); exampleWriter->setBuffer(exampleBuffer); + /* exampleBuffer = exampleController->getServerBuffer(); exampleController->setBuffer(exampleBuffer); */ + exampleManager->SetDsmBuffer(exampleBuffer); exampleBuffer = exampleManager->GetDsmBuffer(); @@ -186,6 +179,15 @@ int main(int argc, char *argv[]) int exampleServerStart = exampleBuffer->GetStartServerId(); int exampleServerEnd = exampleBuffer->GetEndServerId(); + + for (int i = 0; iGetLength(); long exampleTotalBufferLength = exampleBuffer->GetTotalLength(); @@ -248,38 +250,6 @@ int main(int argc, char *argv[]) exampleBuffer->ReceiveAcknowledgment(0, recvData, XDMF_DSM_PUT_DATA_TAG, XDMF_DSM_INTER_COMM); } - MPI_Comm readComm, writeComm; - - MPI_Group readingCores, writingCores; - - MPI_Comm_group(workerComm, &workers); - int * ServerIds = (int *)calloc(((size - numServersCores) / 2), sizeof(int)); - unsigned int index = 0; - for(int i=0 ; i < (int)((size - numServersCores) / 2) ; ++i) - { - ServerIds[index++] = i; - } - - MPI_Group_excl(workers, index, ServerIds, &writingCores); - testval = MPI_Comm_create(workerComm, writingCores, &writeComm); - MPI_Group_incl(workers, index, ServerIds, &readingCores); - testval = MPI_Comm_create(workerComm, readingCores, &readComm); - cfree(ServerIds); - - - if (id < (int)((size - numServersCores) / 2)) - { - exampleBuffer->GetComm()->DupComm(readComm); - exampleBuffer->ReceiveInfo(); - } - else - { - exampleBuffer->GetComm()->DupComm(writeComm); - exampleBuffer->SendInfo(); - } - - exampleBuffer->GetComm()->DupComm(workerComm); - int broadcastComm = XDMF_DSM_INTER_COMM; exampleBuffer->BroadcastComm(&broadcastComm, 0); @@ -343,7 +313,7 @@ int main(int argc, char *argv[]) if (!connectingGroup) { exampleDSMComm->OpenPort(); - portString = exampleDSMComm->GetDsmMasterHostName(); + portString = exampleDSMComm->GetDsmPortName(); // Send the port string to the connecting group exampleDSMComm->Accept(); @@ -354,7 +324,7 @@ int main(int argc, char *argv[]) if (connectingGroup) { // Recieve string from Master group - exampleDSMComm->SetDsmMasterHostName(portString); + exampleDSMComm->SetDsmPortName(portString); exampleDSMComm->Connect(); // When done with connection @@ -364,7 +334,7 @@ int main(int argc, char *argv[]) if (connectingGroup) { // Recieve string from Master group - exampleDSMComm->SetDsmMasterHostName(portString); + exampleDSMComm->SetDsmPortName(portString); exampleManager->Connect(); // When done with connection @@ -444,15 +414,13 @@ int main(int argc, char *argv[]) readStrideVector, readCountVector, readDataSizeVector, - exampleWriter->getServerBuffer(), - size-numServersCores, - size-1); + exampleWriter->getServerBuffer()); readArray->insert(readController); if (id == 0) { - printf("\n\n\n"); + std::cout << "\n\n\n"; } std::cout << "testing read" << std::endl; @@ -521,6 +489,15 @@ int main(int argc, char *argv[]) MPI_Comm exampleInterComm = exampleDSMComm->GetInterComm(); exampleDSMComm->DupInterComm(comm); + if (id >= size - numServersCores) + { + exampleWriter->getServerBuffer()->SendInfo(); + } + else + { + exampleWriter->getServerBuffer()->ReceiveInfo(); + } + /* exampleWriter->restartDSM(); exampleController->restartDSM(); diff --git a/examples/Cxx/ExampleXdmfDomain.cpp b/examples/Cxx/ExampleXdmfDomain.cpp index b9267b42..85365ae5 100644 --- a/examples/Cxx/ExampleXdmfDomain.cpp +++ b/examples/Cxx/ExampleXdmfDomain.cpp @@ -2,6 +2,11 @@ int main(int, char **) { + //#initialization begin + shared_ptr exampleDomain = XdmfDomain::New(); + + //#initialization end + return 0; } diff --git a/examples/Cxx/ExampleXdmfError.cpp b/examples/Cxx/ExampleXdmfError.cpp index 7cc3b1ca..2b4f9f5d 100644 --- a/examples/Cxx/ExampleXdmfError.cpp +++ b/examples/Cxx/ExampleXdmfError.cpp @@ -3,15 +3,50 @@ int main(int, char **) { + //#initialization begin + XdmfError testError = XdmfError(XdmfError:DEBUG, "This is a debug error"); + //#initialization end + + //#getLevel begin + + XdmfError::Level testError.getLevel(); + + //#getLevel end + + //#setLevel begin + + testError.setLevel(XdmfError::WARNING); + + //#setLevel end + + //#what begin + + char * errorOutput = testError.what(); + + //#what end + + //#getLevelLimit begin + XdmfError::Level exampleLevel = XdmfError::getLevelLimit(); + //#getLevelLimit end + + //#setLevelLimit begin + XdmfError::setLevelLimit(XdmfError::FATAL); - XdmfError::setBuffer(std::cout.rdbuf());//the default buffer is cout + //#setLevelLimit end + + //#setBuffer begin + XdmfError::setBuffer(std::cout.rdbuf()); + //the default buffer is cout + //#setBuffer end + + //#message begin try { @@ -19,12 +54,10 @@ int main(int, char **) } catch (XdmfError exampleError) { - XdmfError::Level exampleError.getLevel(); - - exampleError.setLevel(XdmfError::WARNING); - char * errorOutput = exampleError.what(); } + //#message end + return 0; } diff --git a/examples/Cxx/ExampleXdmfGeometry.cpp b/examples/Cxx/ExampleXdmfGeometry.cpp index 972e5d13..367cdd3b 100644 --- a/examples/Cxx/ExampleXdmfGeometry.cpp +++ b/examples/Cxx/ExampleXdmfGeometry.cpp @@ -3,15 +3,31 @@ int main(int, char **) { + //#initialization begin + shared_ptr exampleGeometry = XdmfGeometry::New(); + //#initialization end + //Assuming that exampleGeometry is a shared pointer to a XdmfGeometry object + //#setType begin + exampleGeometry->setType(XdmfGeometryType::XYZ()); + //#setType end + + //#getType begin + shared_ptr exampleType = exampleGeometry->getType(); + //#getType end + + //#getNumberPoints begin + unsigned int numPoints = exampleGeometry->getNumberPoints(); + //#getNumberPoints end + return 0; } diff --git a/examples/Cxx/ExampleXdmfGeometryType.cpp b/examples/Cxx/ExampleXdmfGeometryType.cpp index 9024a1f5..fad8003f 100644 --- a/examples/Cxx/ExampleXdmfGeometryType.cpp +++ b/examples/Cxx/ExampleXdmfGeometryType.cpp @@ -2,15 +2,32 @@ int main(int, char **) { + //#initialization begin + shared_ptr exampleGeometry = XdmfGeometry::New(); + //#initialization end + + //#getType begin + if (exampleGeometry->getType() == XdmfGeometry::XYZ()) { //do whatever is to be done if the geometry is xyz } + //#getType end + + //#getDimensions begin + unsigned int exampleDimensions = XdmfGeometryType::XYZ()->getDimensions(); + + //#getDimensions end + + //#getName begin + std::string exampleName = XdmfGeometryType::XYZ()->getName(); + //#getName end + return 0; } diff --git a/examples/Cxx/ExampleXdmfGraph.cpp b/examples/Cxx/ExampleXdmfGraph.cpp index a4767c7a..ba40cbc8 100644 --- a/examples/Cxx/ExampleXdmfGraph.cpp +++ b/examples/Cxx/ExampleXdmfGraph.cpp @@ -2,6 +2,11 @@ int main(int, char **) { + //#initialization begin + shared_ptr exampleGraph = XdmfGraph::New(); + + //#initialization end + return 0; } diff --git a/examples/Cxx/ExampleXdmfGrid.cpp b/examples/Cxx/ExampleXdmfGrid.cpp index df5ef149..af1bfd52 100644 --- a/examples/Cxx/ExampleXdmfGrid.cpp +++ b/examples/Cxx/ExampleXdmfGrid.cpp @@ -2,26 +2,57 @@ int main(int, char **) { + //#initialization begin + shared_ptr exampleGrid = XdmfUnstructuredGrid::New(); //Using an unstructured grid since XdmfGrid is an abstract class - //Assumming that exampleGrid is a shared pointer to an XdmfUnstructuredGrid object + + //#initialization end + //#setName begin + std::string newName = "New Name"; exampleGrid->setName(newName); + //#setName end + + //#setTime begin + shared_ptr newTime = XdmfTime::New(20.0); exampleGrid->setTime(newTime); + //#setTime end + + //#getTime begin + shared_ptr< XdmfTime> exampleTime = exampleGrid->getTime(); + //#getTime end + + //#getTimeconst begin + shared_ptr exampleTimeConst = exampleGrid->getTime(); + //#getTimeconst end + + //#getName begin + std::string exampleName = exampleGrid->getName(); + //#getName end + + //#getGeometry begin + shared_ptr exampleGeometry = exampleGrid->getGeometry(); + //#getGeometry end + + //#getTopology begin + shared_ptr exampleTopology = exampleGrid->getTopology(); + //#getTopology end + return 0; } diff --git a/examples/Cxx/ExampleXdmfGridCollection.cpp b/examples/Cxx/ExampleXdmfGridCollection.cpp index a23970bf..ce8bcb61 100644 --- a/examples/Cxx/ExampleXdmfGridCollection.cpp +++ b/examples/Cxx/ExampleXdmfGridCollection.cpp @@ -6,10 +6,20 @@ int main(int, char **) { //Assuming that exampleCollection is a shared pointer to an XdmfGridCollection object + //#initalization begin + shared_ptr exampleCollection = XdmfGridCollection::New(); + //#initialization end + + //#setType begin + exampleCollection->setType(XdmfGridCollectionType::Temporal()); + //#setType end + + //#getType begin + shared_ptr exampleType = exampleCollection->getType(); if (exampleType == XdmfGridCollectionType::Temporal()) @@ -17,6 +27,10 @@ int main(int, char **) //do whatever is to be done if the grid collection is temporal } + //#getType end + + //#insert begin + shared_ptr exampleInformation = XdmfInformation::New(); std::string newKey = "New Key"; std::string newValue = "New Value"; @@ -24,5 +38,7 @@ int main(int, char **) exampleInformation->setValue(newValue); exampleCollection->insert(exampleInformation); + //#insert end + return 0; } diff --git a/examples/Cxx/ExampleXdmfItemFactory.cpp b/examples/Cxx/ExampleXdmfItemFactory.cpp index 4608ee57..4f7c5a57 100644 --- a/examples/Cxx/ExampleXdmfItemFactory.cpp +++ b/examples/Cxx/ExampleXdmfItemFactory.cpp @@ -2,6 +2,11 @@ int main(int, char **) { + //#initialization begin + shared_ptr exampleFactory = XdmfItemFactory::New(); + + //#initialization end + return 0; } diff --git a/examples/Cxx/ExampleXdmfMap.cpp b/examples/Cxx/ExampleXdmfMap.cpp index 41d3c25d..cd153251 100644 --- a/examples/Cxx/ExampleXdmfMap.cpp +++ b/examples/Cxx/ExampleXdmfMap.cpp @@ -4,9 +4,13 @@ int main(int, char **) { + //#initialization begin + shared_ptr exampleMap = XdmfMap::New(); - //Assumming that exampleMap is a shared pointer to a XdmfMap object + //#initialization end + + //#initializationnode begin std::vector > holdGlobalNodes; shared_ptr nodeAttribute = XdmfAttribute::New(); @@ -36,6 +40,10 @@ int main(int, char **) //and map 3 would have an entry of (1, 2, 5) //The entries are formatted (remoteTaskID, remoteLocalNodeID, localNodeID) + //#initializationnode end + + //#setMap begin + std::map > > taskMap; std::map > nodeMap; std::set remoteIDset; @@ -84,6 +92,10 @@ int main(int, char **) //(2, 9, 9) //Are now in the XdmfMap + //#setMap end + + + //#inserttuple begin unsigned int newRemoteTaskID = 4; unsigned int newLocalNodeID = 7; @@ -91,11 +103,18 @@ int main(int, char **) exampleMap->insert(newRemoteTaskID, newLocalNodeID, newRemoteLocalNodeID); //This inserts an entry of (4, 7, 3) into the map + //#inserttuple end + + + //#setName begin std::string newName = "New Name"; exampleMap->setName(newName); - //getMap + //#setName end + + //#getMap begin + //Assuming that exampleMap is a shared pointer to an XdmfMap object filled with the following tuples //(1, 1, 9) //(1, 2, 8) @@ -122,7 +141,18 @@ int main(int, char **) int remoteNodeValue = (*setWalker); //remoteNodeValue now equals 9 - + //#getMap end + + + //#getRemoteNodeIds begin + + //Assuming that exampleMap is a shared pointer to an XdmfMap object filled with the following tuples + //(1, 1, 9) + //(1, 2, 8) + //(2, 3, 7) + //(2, 4, 6) + //(3, 5, 5) + //(3, 6, 4) std::map > nodeIDMap = exampleMap->getRemoteNodeIds(1); //nodeIDMap now contains the following tuples because it retrieved the tuples associated with taskID 1 //(1, 9) @@ -137,14 +167,25 @@ int main(int, char **) int remoteNodeValue = (*setWalker); //remoteNodeValue now equals 9 + //#getRemoteNodeIds end + + //#getName begin std::string exampleName = exampleMap->getName(); + //#getName end + + //#isInitialized begin + if (!exampleMap->isInitialized()) { exampleMap->read(); } + //#isInitialized end + + //#setHeavyDataControllers begin + std::string hdf5FilePath = "The HDF5 file path goes here"; std::string hdf5SetPath = "The HDF5 set path goes here"; int startIndex = 0; //start at the beginning @@ -175,7 +216,13 @@ int main(int, char **) shared_ptr exampleMap = XdmfMap::New(); exampleMap->setHeavyDataControllers(newRemoteTaskController, newLocalNodeController, newRemoteLocalNodeController); + //#setHeavyDataControllers end + + //#release begin + exampleMap->release(); + //#release end + return 0; } diff --git a/examples/Cxx/ExampleXdmfReader.cpp b/examples/Cxx/ExampleXdmfReader.cpp index f31fb5c2..4e1f43aa 100644 --- a/examples/Cxx/ExampleXdmfReader.cpp +++ b/examples/Cxx/ExampleXdmfReader.cpp @@ -2,6 +2,11 @@ int main(int, char **) { + //#initialization begin + shared_ptr exampleReader = XdmfReader::New(); + + //#initialization end + return 0; } diff --git a/examples/Cxx/ExampleXdmfRectilinearGrid.cpp b/examples/Cxx/ExampleXdmfRectilinearGrid.cpp index 533b81c4..e5f04c4d 100644 --- a/examples/Cxx/ExampleXdmfRectilinearGrid.cpp +++ b/examples/Cxx/ExampleXdmfRectilinearGrid.cpp @@ -7,6 +7,8 @@ int main(int, char **) //Assuming that exampleGrid is a shared pointer to an XdmfRectilinearGrid + //#initvalues begin + shared_ptr pointsXArray = XdmfArray::New(); pointsXArray->pushBack(5); pointsXArray->pushBack(6); @@ -29,37 +31,91 @@ int main(int, char **) pointsZArray->pushBack(7); pointsZArray->pushBack(2); + //#initvalues end + if (size==2) { + //#initialization2 begin + shared_ptr exampleGrid = XdmfRectilinearGrid::New(pointsXArray, pointsYArray); + + //#initialization2 end + + //#getCoodinatessingle begin + shared_ptr readPointsX = exampleGrid->getCoordinates(0); shared_ptr readPointsY = exampleGrid->getCoordinates(1); + + //#getCoordinatessingle end + + //#getCoordinatessingleconst begin + shared_ptr readPointsXConst = exampleGrid->getCoordinates(0); shared_ptr readPointsYConst = exampleGrid->getCoordinates(1); + //#getCoordinatessingleconst end + } else if (size==3) { + //#initialization3 begin + shared_ptr exampleGrid = XdmfRectilinearGrid::New(pointsXArray, pointsYArray, pointsZArray); + + //#initialization3 end + + //#setCoordinatessingle begin + exampleGrid->setCoordinates(0, pointsXArray); + //#setCoordinatessingle end + } else //mutable size { + //#initializationvector begin + std::vector > pointsCollector; pointsCollector.push_back(pointsXArray); pointsCollector.push_back(pointsYArray); pointsCollector.push_back(pointsZArray); shared_ptr exampleGrid = XdmfRectilinearGrid::New(pointsCollector); + + //#initializationvector end + + //#setCoordinatesvector begin + exampleGrid->setCoordinates(pointsCollector); + + //#setCoordinatesvector end + + //#getDimensions begin + shared_ptr exampleDimensions = exampleGrid->getDimensions(); + + //#getDimensions end + + //#getDimensionsconst begin + shared_ptr exampleDimensionsConst = exampleGrid->getDimensions(); + + //#getDimensionsconst end + + //#getCoordinatesvector begin + std::vector > exampleCoordinates = exampleGrid->getCoordinates(); + + //#getCoordinatesvector end + + //#getCoordinatesvectorconst begin + const std::vector > exampleCoordinatesConst = exampleGrid->getCoordinates(); + //#getCoordinatesvectorconst end + } return 0; } diff --git a/examples/Cxx/ExampleXdmfRegularGrid.cpp b/examples/Cxx/ExampleXdmfRegularGrid.cpp index 227db734..69431b01 100644 --- a/examples/Cxx/ExampleXdmfRegularGrid.cpp +++ b/examples/Cxx/ExampleXdmfRegularGrid.cpp @@ -7,6 +7,8 @@ int main(int, char **) //Assuming exampleGrid is a shared pointer to an XdmfRegularGrid object + //#initvalue begin + double newBrickX = 20.0; unsigned int newPointsX = 5; double newOriginX = 0; @@ -17,29 +19,71 @@ int main(int, char **) unsigned int newPointsZ = 5; double newOriginZ = 0; + //#initvalue end + if (size==2) { + //#initialization2 begin + shared_ptr exampleGrid = XdmfRegularGrid::New( newBrickX, newBrickY, newPointsX, newPointsY, newOriginX, newOriginY); + + //#initialization2 end + + //#getBrickSize begin + shared_ptr exampleBrick = exampleGrid->getBrickSize(); + + //#getBrickSize end + + //#getBrickSizeconst begin + shared_ptr exampleBrickConst = exampleGrid->getBrickSize(); + + //#getBrickSizeconst end + + //#getDimensions begin + shared_ptr exampleDimensions = exampleGrid->getDimensions(); + + //#getDimensions end + + //#getDimensionsconst begin + shared_ptr exampleDimensionsConst = exampleGrid->getDimensions(); + + //#getDimensionsconst end + + //#getOrigin begin + shared_ptr exampleOrigin = exampleGrid->getOrigin(); + + //#getOrigin end + + //#getOriginconst begin + shared_ptr exampleOriginConst = exampleGrid->getOrigin(); + //#getOriginconst end + } else if (size==3) { + //#initialization3 begin + shared_ptr exampleGrid = XdmfRegularGrid::New( newBrickX, newBrickY, newBrickZ, newPointsX, newPointsY, newPointsZ, newOriginX, newOriginY, newOriginZ); + //#initialization3 end + } else //mutable size { + //#initializationvector begin + shared_ptr newBrickSize = XdmfArray::New(); newBrickSize->pushBack(20.0); newBrickSize->pushBack(21.0); @@ -54,10 +98,26 @@ int main(int, char **) newGridOrigin->pushBack(2.0); shared_ptr exampleGrid = XdmfRegularGrid::New(newBrickSize, newNumPoints, newGridOrigin); + //#initializationvector end + + //#setBrickSize begin + exampleGrid->setBrickSize(newBrickSize); + + //#setBrickSize end + + //#setDimensions begin + exampleGrid->setDimensions(newNumPoints); + + //#setDimensions end + + //#setOrigin begin + exampleGrid->setOrigin(newGridOrigin); + //#setOrigin end + } return 0; diff --git a/examples/Cxx/ExampleXdmfSet.cpp b/examples/Cxx/ExampleXdmfSet.cpp index 095ea245..24fdb7b7 100644 --- a/examples/Cxx/ExampleXdmfSet.cpp +++ b/examples/Cxx/ExampleXdmfSet.cpp @@ -3,17 +3,33 @@ int main(int, char **) { + //#initialize begin + shared_ptr exampleSet = XdmfSet::New(); - //Assuming that exampleSet is a shared pointer to an XdmfSet object + //#initialize end + + //#setName begin std::string newName = "New Name"; exampleSet->setName(newName); + //#setName end + + //#setType begin + exampleSet->setType(XdmfSetType::Node()); + //#setType end + + //#getName begin + std::string exampleName = exampleSet->getName(); + //#getName end + + //#getType begin + shared_ptr exampleType = exampleSet->getType(); if (exampleType == XdmfSetType::Node()) @@ -21,5 +37,7 @@ int main(int, char **) //Do whatever is to be done if the set is a node } + //#getType end + return 0; } diff --git a/examples/Cxx/ExampleXdmfTime.cpp b/examples/Cxx/ExampleXdmfTime.cpp index efafaefc..f8179e42 100644 --- a/examples/Cxx/ExampleXdmfTime.cpp +++ b/examples/Cxx/ExampleXdmfTime.cpp @@ -2,7 +2,7 @@ int main(int, char **) { - //Assumming that exampleTime is a shared pointer to an XdmfTime object + //#initialization begin shared_ptr exampleTime = XdmfTime::New(); //The Default case sets the time to 0.0 @@ -11,9 +11,19 @@ int main(int, char **) double newTime = 5.0; shared_ptr exampleTime2 = XdmfTime::New(newTime); - double readTime = exampleTime->getTime(); + //#initialization end + + //#getValue begin + + double readTime = exampleTime->getValue(); + + //#getValue end + + //#setValue begin exampleTime->setValue(newTime); + //#setValue end + return 0; } diff --git a/examples/Cxx/ExampleXdmfTopology.cpp b/examples/Cxx/ExampleXdmfTopology.cpp index 5c91503f..12619fef 100644 --- a/examples/Cxx/ExampleXdmfTopology.cpp +++ b/examples/Cxx/ExampleXdmfTopology.cpp @@ -3,15 +3,29 @@ int main(int, char **) { + //#initialization begin + shared_ptr exampleTopology = XdmfTopology::New(); - //Assuming that exampleTopology is a shared pointer to an XdmfTopology object + //#initialization end + + //#setType begin exampleTopology->setType(XdmfTopologyType::Pyramid()); + //#setType end + + //#getType begin + shared_ptr exampleType = exampleTopology->getType(); + //#getType end + + //#getNumberElements begin + unsigned int numElements = exampleTopology->getNumberElements(); + //#getNumberElements end + return 0; } diff --git a/examples/Cxx/ExampleXdmfTopologyType.cpp b/examples/Cxx/ExampleXdmfTopologyType.cpp index 06f6000b..58eddd93 100644 --- a/examples/Cxx/ExampleXdmfTopologyType.cpp +++ b/examples/Cxx/ExampleXdmfTopologyType.cpp @@ -3,10 +3,16 @@ int main(int, char **) { + //#initialization begin + unsigned int exampleID = XdmfTopologyType::Triangle()->getID(); shared_ptr createdTopology = XdmfTopology::New(); createdTopology->setType(XdmfTopologyType::New(exampleID)); + //#initialization end + + //#getCellType begin + XdmfTopologyType::CellType exampleType = XdmfTopologyType::Linear; //Assuming that exampleTopology is a shared pointer to a filled XdmfTopology object if (exampleType == exampleTopology->getCellType()) @@ -14,20 +20,52 @@ int main(int, char **) //Do whatever is to be done if the cell type is linear } + //#getCellType end + + //#getEdgesPerElement begin + unsigned int numEdges = XdmfTopologyType::Triangle()->getEdgesPerElement(); + //#getEdgesPerElement end + + //#getFacesPerElement begin + unsigned int numFaces = XdmfTopologyType::Triangle()->getFacesPerElement(); + //#getFacesPerElement end + + //#getID begin + unsigned int holdID = XdmfTopologyType::Triangle()->getID(); + //#getID end + + //#getName begin + std::string exampleName = XdmfTopologyType::Triangle()->getName(); + //#getName end + + //#getFaceType begin + + shared_ptr exampleface = XdmfTopologyType::Tetrahedron()->getFaceType(); + + //#getFaceType end + + //#getNodesPerElement begin + unsigned int numNodes = XdmfTopologyType::Triangle()->getNodesPerElement(); + //#getNodesPerElement end + + //#getType begin + if (createdTopology->getType() == XdmfTopologyType::Triangle()) { //Do whatever is to be done if the type is Triangle } + //#getType end + return 0; } diff --git a/examples/Cxx/ExampleXdmfUnstructuredGrid.cpp b/examples/Cxx/ExampleXdmfUnstructuredGrid.cpp index aaa4e386..f3886905 100644 --- a/examples/Cxx/ExampleXdmfUnstructuredGrid.cpp +++ b/examples/Cxx/ExampleXdmfUnstructuredGrid.cpp @@ -5,10 +5,14 @@ int main(int, char **) { - //Assuming that exampleGrid is a shared pointer to an XdmfUnstructuredGrid object + //#initialization begin shared_ptr exampleGrid = XdmfUnstructuredGrid::New(); + //#initialization end + + //#initializationregular begin + double newBrickX = 0.0; double newBrickY = 0.0; unsigned int newPointsX = 5; @@ -18,6 +22,10 @@ int main(int, char **) shared_ptr baseGrid = XdmfRegularGrid::New(newBrickX, newBrickY, newPointsX, newPointsY, newOriginX, newOriginY); shared_ptr regGeneratedGrid = XdmfUnstructuredGrid::New(baseGrid); + //#initializationregular end + + //#setGeometry begin + shared_ptr newGeometry = XdmfGeometry::New(); newGeometry->setType(XdmfGeometryType::XYZ()); newGeometry->pushBack(1); @@ -31,6 +39,10 @@ int main(int, char **) newGeometry->pushBack(9); exampleGrid->setGeometry(newGeometry); + //#setGeometry end + + //#setTopology begin + shared_ptr newTopology = XdmfTopology::New(); newTopology->setType(XdmfTopologyType::Triangle()); newTopology->pushBack(1); @@ -44,8 +56,19 @@ int main(int, char **) newTopology->pushBack(9); exampleGrid->setTopology(newTopology); + //#setTopology end + + //#getGeometry begin + shared_ptr exampleGeometry = exampleGrid->getGeometry(); + + //#getGeometry end + + //#getTopology begin + shared_ptr exampleTopology = exampleGrid->getTopology(); + //#getTopology end + return 0; } diff --git a/examples/Cxx/XdmfAcceptTest.cpp b/examples/Cxx/XdmfAcceptTest.cpp new file mode 100644 index 00000000..9d53745b --- /dev/null +++ b/examples/Cxx/XdmfAcceptTest.cpp @@ -0,0 +1,44 @@ +#include +#include +#include +#include +#include +#include +#include + + +int main(int argc, char *argv[]) +{ + int size, id, dsmSize; + dsmSize = 64; + MPI_Status status; + MPI_Comm comm = MPI_COMM_WORLD; + + MPI_Init(&argc, &argv); + + MPI_Comm_rank(comm, &id); + MPI_Comm_size(comm, &size); + + + std::string newPath = "dsm"; + int numServersCores = 3; + + + shared_ptr exampleWriter = XdmfHDF5WriterDSM::New(newPath, comm, dsmSize/numServersCores, size-numServersCores, size-1); + + if (id < size-numServersCores) + { + exampleWriter->getServerBuffer()->GetComm()->OpenPort(); + exampleWriter->getServerBuffer()->SendAccept(2); + + MPI_Barrier(exampleWriter->getServerBuffer()->GetComm()->GetIntraComm()); + } + + MPI_Barrier(exampleWriter->getServerBuffer()->GetComm()->GetInterComm()); + + exampleWriter->getServerBuffer()->GetComm()->ClosePort(); + + MPI_Finalize(); + + return 0; +} diff --git a/examples/Cxx/XdmfConnectTest.cpp b/examples/Cxx/XdmfConnectTest.cpp new file mode 100644 index 00000000..02012c9d --- /dev/null +++ b/examples/Cxx/XdmfConnectTest.cpp @@ -0,0 +1,179 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +int main(int argc, char *argv[]) +{ + int size, id, dsmSize; + dsmSize = 64; + MPI_Status status; + MPI_Comm comm = MPI_COMM_WORLD; + + MPI_Init(&argc, &argv); + + MPI_Comm_rank(comm, &id); + MPI_Comm_size(comm, &size); + + + std::string newPath = "dsm"; + std::string newSetPath = "Data"; + + // Initializing objects + + //since the start and end ids are larger than the size, there are no buffers alloted + //thus, no blockage occurs + XdmfDSMCommMPI * testComm = new XdmfDSMCommMPI(); + testComm->DupComm(comm); + testComm->Init(); + XdmfDSMBuffer * testBuffer = new XdmfDSMBuffer(); + testBuffer->SetIsServer(false); + testBuffer->SetComm(testComm); + testBuffer->SetIsConnected(true); + + shared_ptr exampleWriter = XdmfHDF5WriterDSM::New(newPath, testBuffer); + + exampleWriter->getServerBuffer()->GetComm()->ReadDsmPortName(); + + exampleWriter->getServerManager()->Connect(); + + MPI_Barrier(exampleWriter->getServerBuffer()->GetComm()->GetIntraComm()); + + shared_ptr writeArray = XdmfArray::New(); + + for (int i = 1; i <= 5; ++i) + { + writeArray->pushBack(i*(id+1)); + } + + std::vector writeStartVector; + std::vector writeStrideVector; + std::vector writeCountVector; + std::vector writeDataSizeVector; + + writeStartVector.push_back(id*5); + writeStrideVector.push_back(1); + writeCountVector.push_back(5); + writeDataSizeVector.push_back(5*size); + + shared_ptr writeController = XdmfHDF5ControllerDSM::New( + newPath, + newSetPath, + XdmfArrayType::Int32(), + writeStartVector, + writeStrideVector, + writeCountVector, + writeDataSizeVector, + exampleWriter->getServerBuffer()); + + std::vector readStartVector; + std::vector readStrideVector; + std::vector readCountVector; + std::vector readDataSizeVector; + + readStartVector.push_back(5*id); + readStrideVector.push_back(1); + readCountVector.push_back(5); + readDataSizeVector.push_back(5*size); + + shared_ptr readController = XdmfHDF5ControllerDSM::New( + newPath, + newSetPath, + XdmfArrayType::Int32(), + readStartVector, + readStrideVector, + readCountVector, + readDataSizeVector, + exampleWriter->getServerBuffer()); + + exampleWriter->setMode(XdmfHeavyDataWriter::Hyperslab); + + // Done initializing + + for (int i = 0; i < size; ++i) + { + MPI_Barrier(exampleWriter->getServerBuffer()->GetComm()->GetIntraComm()); + if (i == id) + { + std::stringstream outputstream; + outputstream << "Array on core " << exampleWriter->getServerBuffer()->GetComm()->GetInterId() << " contains:" << std::endl; + for (unsigned int j = 0; j < writeArray->getSize(); ++j) + { + outputstream << "[" << j << "]" << writeArray->getValue(j) << std::endl; + } + std::cout << outputstream.str(); + } + } + + for (unsigned int numloops = 0; numloops < 4; ++numloops) + { + if (writeArray->getNumberHeavyDataControllers() > 0) + { + writeArray->removeHeavyDataController(0); + } + writeArray->insert(writeController); + + + if (id == size - 1) + { + std::cout << std::endl << std::endl; + } + + writeArray->accept(exampleWriter); + + if (id == size - 1) + { + int sentData = 1; + exampleWriter->getServerBuffer()->SendAcknowledgment(exampleWriter->getServerBuffer()->GetComm()->GetInterId() + 1, sentData, XDMF_DSM_EXCHANGE_TAG, XDMF_DSM_INTER_COMM); + exampleWriter->getServerBuffer()->ReceiveAcknowledgment(exampleWriter->getServerBuffer()->GetComm()->GetInterId() + 1, sentData, XDMF_DSM_EXCHANGE_TAG, XDMF_DSM_INTER_COMM); + } + + MPI_Barrier(exampleWriter->getServerBuffer()->GetComm()->GetIntraComm()); + + writeArray->removeHeavyDataController(0); + writeArray->insert(readController); + writeArray->release(); + writeArray->read(); + + for (int i = 0; i < size; ++i) + { + MPI_Barrier(exampleWriter->getServerBuffer()->GetComm()->GetIntraComm()); + if (i == id) + { + std::stringstream outputstream; + outputstream << "Array on core " << exampleWriter->getServerBuffer()->GetComm()->GetInterId() << " contains:" << std::endl; + for (unsigned int j = 0; j < writeArray->getSize(); ++j) + { + int tempVal = writeArray->getValue(j); + tempVal = tempVal * 2; + writeArray->insert(j, tempVal); + outputstream << "[" << j << "]" << writeArray->getValue(j) << std::endl; + } + std::cout << outputstream.str(); + } + } + } + + if (id == size - 1) + { + int sentData = 1; + exampleWriter->getServerBuffer()->SendAcknowledgment(exampleWriter->getServerBuffer()->GetComm()->GetInterId() + 1, sentData, XDMF_DSM_EXCHANGE_TAG, XDMF_DSM_INTER_COMM); + } + + MPI_Barrier(exampleWriter->getServerBuffer()->GetComm()->GetIntraComm()); + + // Do work stuff here + + MPI_Barrier(exampleWriter->getServerBuffer()->GetComm()->GetInterComm()); + + MPI_Finalize(); + + return 0; +} diff --git a/examples/Cxx/XdmfConnectTest2.cpp b/examples/Cxx/XdmfConnectTest2.cpp new file mode 100644 index 00000000..932e6ea9 --- /dev/null +++ b/examples/Cxx/XdmfConnectTest2.cpp @@ -0,0 +1,173 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +int main(int argc, char *argv[]) +{ + int size, id, dsmSize; + dsmSize = 64; + MPI_Status status; + MPI_Comm comm = MPI_COMM_WORLD; + + MPI_Init(&argc, &argv); + + MPI_Comm_rank(comm, &id); + MPI_Comm_size(comm, &size); + + + std::string newPath = "dsm"; + std::string newSetPath = "Data"; + + // Initializing objects + + //since the start and end ids are larger than the size there are no buffers alloted + //thus, not blockage occurs + XdmfDSMCommMPI * testComm = new XdmfDSMCommMPI(); + testComm->DupComm(comm); + testComm->Init(); + XdmfDSMBuffer * testBuffer = new XdmfDSMBuffer(); + testBuffer->SetIsServer(false); + testBuffer->SetComm(testComm); + testBuffer->SetIsConnected(true); + + std::vector readStartVector; + std::vector readStrideVector; + std::vector readCountVector; + std::vector readDataSizeVector; + + readStartVector.push_back(5*id); + readStrideVector.push_back(1); + readCountVector.push_back(5); + readDataSizeVector.push_back(5*size); + + shared_ptr readArray = XdmfArray::New(); + + readArray->initialize(0); + readArray->reserve(5); + + shared_ptr readController = XdmfHDF5ControllerDSM::New( + newPath, + newSetPath, + XdmfArrayType::Int32(), + readStartVector, + readStrideVector, + readCountVector, + readDataSizeVector, + testBuffer); + + readController->getServerBuffer()->GetComm()->ReadDsmPortName(); + + readController->getServerManager()->Connect(); + + shared_ptr exampleWriter = XdmfHDF5WriterDSM::New(newPath, testBuffer); + + std::vector writeStartVector; + std::vector writeStrideVector; + std::vector writeCountVector; + std::vector writeDataSizeVector; + + writeStartVector.push_back(id*5); + writeStrideVector.push_back(1); + writeCountVector.push_back(5); + writeDataSizeVector.push_back(5*size); + + shared_ptr writeController = XdmfHDF5ControllerDSM::New( + newPath, + newSetPath, + XdmfArrayType::Int32(), + writeStartVector, + writeStrideVector, + writeCountVector, + writeDataSizeVector, + exampleWriter->getServerBuffer()); + + exampleWriter->setMode(XdmfHeavyDataWriter::Hyperslab); + + // Done initialization + + MPI_Barrier(readController->getServerBuffer()->GetComm()->GetIntraComm()); + + for (unsigned int numloops = 0; numloops < 4; ++numloops) + { + if (id == 0) + { + int receiveData = 0; + readController->getServerBuffer()->ReceiveAcknowledgment(readController->getServerBuffer()->GetComm()->GetInterId() - 1, receiveData, XDMF_DSM_EXCHANGE_TAG, XDMF_DSM_INTER_COMM); + } + + MPI_Barrier(readController->getServerBuffer()->GetComm()->GetIntraComm()); + + if (readArray->getNumberHeavyDataControllers() > 0) + { + readArray->removeHeavyDataController(0); + } + readArray->insert(readController); + readArray->read(); + + for (int i = 0; i < size; ++i) + { + MPI_Barrier(readController->getServerBuffer()->GetComm()->GetIntraComm()); + if (i == id) + { + std::stringstream outputstream; + outputstream << "Array on core " << exampleWriter->getServerBuffer()->GetComm()->GetInterId() << " contains:" << std::endl; + for (unsigned int j = 0; j < readArray->getSize(); ++j) + { + int tempVal = readArray->getValue(j); + tempVal = tempVal * 3; + readArray->insert(j, tempVal); + outputstream << "[" << j << "]" << readArray->getValue(j) << std::endl; + } + std::cout << outputstream.str(); + } + } + + MPI_Barrier(readController->getServerBuffer()->GetComm()->GetIntraComm()); + if (id == 0) + { + std::cout << std::endl << std::endl; + } + + readArray->removeHeavyDataController(0); + readArray->insert(writeController); + + readArray->accept(exampleWriter); + + if (id == 0) + { + int receiveData = 0; + readController->getServerBuffer()->SendAcknowledgment(readController->getServerBuffer()->GetComm()->GetInterId() - 1, receiveData, XDMF_DSM_EXCHANGE_TAG, XDMF_DSM_INTER_COMM); + } + } + + //this last acknowledgment is to end the loop. + + if (id == 0) + { + int receiveData = 0; + readController->getServerBuffer()->ReceiveAcknowledgment(readController->getServerBuffer()->GetComm()->GetInterId() - 1, receiveData, XDMF_DSM_EXCHANGE_TAG, XDMF_DSM_INTER_COMM); + } + + MPI_Barrier(readController->getServerBuffer()->GetComm()->GetIntraComm()); + + // Do work stuff here + + if (id == 0) + { + readController->stopDSM(); + } + + MPI_Barrier(readController->getServerBuffer()->GetComm()->GetInterComm()); + + MPI_Finalize(); + + return 0; +} diff --git a/examples/Python/XdmfExampleArray.py b/examples/Python/XdmfExampleArray.py index 9d898692..c43d664e 100644 --- a/examples/Python/XdmfExampleArray.py +++ b/examples/Python/XdmfExampleArray.py @@ -1,8 +1,11 @@ from Xdmf import * from numpy import * +#//definefunction begin + def maximum(values): - values = ArrayVector(values)#need to cast to the right data type + # Need to cast to the right data type + values = ArrayVector(values) if values[0].getArrayType() == XdmfArrayType.String(): returnArray = XdmfArray.New() returnArray.pushBackAsString(values[0].getValueAsString(0)) @@ -17,38 +20,103 @@ def maximum(values): returnArray.pushBackAsFloat64(maxVal) return returnArray +#//definefunction end + +#//defineoperation begin + def prepend(val1, val2): - val1 = XdmfArray.XdmfArrayPtr(val1)#need to cast to the right data type - val2 = XdmfArray.XdmfArrayPtr(val2)#had to write a custom casting method to integrate it properly + # Need to cast to the right data type + # Had to write a custom casting method to integrate it properly + val1 = XdmfArray.XdmfArrayPtr(val1) + val2 = XdmfArray.XdmfArrayPtr(val2) returnArray = XdmfArray.New() returnArray.insert(0, val2, 0, val2.getSize()) returnArray.insert(val2.getSize(), val1, 0, val1.getSize()) return returnArray +#//defineoperation end + +#//programstart begin + if __name__ == "__main__": + + #//programstart end + + #//initialization begin + exampleArray = XdmfArray.New() - #Assuming that exampleArray is a shared pointer to an XdmfArray object + #//initialization end + + #//setName begin newName = "New Name" exampleArray.setName(newName) + #//setName end + + #//reserve begin + newSize = 10 exampleArray.reserve(newSize) + + #//reserve end + + #//initializesingle begin + + newSize = 10 exampleArray.initialize(XdmfArrayType.Int32(), newSize) + + #//initializesingle end + + #//initializevector begin + newSizeVector = UInt32Vector() newSizeVector.push_back(5) newSizeVector.push_back(5) newSizeVector.push_back(5) exampleArray.initialize(XdmfArrayType.Int32(), newSizeVector) + #//initializevector end + + #//getArrayType begin + exampleType = exampleArray.getArrayType() + + #//getArrayType end + + #//getCapacity begin + exampleCapacity = exampleArray.getCapacity() + + #//getCapacity end + + #//getDimensions begin + exampleDimensions = exampleArray.getDimensions() + + #//getDimensions end + + #//getDimensionsString begin + exampleDimensionString = exampleArray.getDimensionsString() + + #//getDimensionsString end + + #//getName begin + exampleName = exampleArray.getName() + + #//getName end + + #//getSize begin + exampleSize = exampleArray.getSize() + #//getSize end + + #//insertarray begin + initArray = [0,1,2,3,4,5,6,7,8,9] storeArray = XdmfArray.New() exampleArray.insertAsInt32(0, initArray) @@ -58,6 +126,12 @@ if __name__ == "__main__": #storeArray now contains {0,1,1,3,2,5,3,7,4,9} storeArray.insert(0, exampleArray, 0, 5, 1, 2) #storeArray now contains {0,2,4,6,8,5,3,7,4,9} + + #//insertarray end + + #//insertlist begin + + initArray = [0,1,2,3,4,5,6,7,8,9] exampleArray.insertAsInt32(0, initArray) #exampleArray now contains {0,1,2,3,4,5,6,7,8,9} exampleArray.insertAsInt32(0, initArray[0:5:2]) @@ -65,14 +139,29 @@ if __name__ == "__main__": exampleArray.insertAsInt32(0, initArray[::-1]) #exampleArray now contains {9,8,7,6,5,4,3,2,1,0} - outputArray = exampleArray.getNumpyArray() - #Python uses a different function for each data type #This example uses insertAsInt32 to insert ints #insertAsFloat64 can also be used to insert doubles #This function takes a start index and a list #Sublists are inserted using Python's sublist notation + #//insertlist end + + #//getNumpyArray begin + + outputArray = exampleArray.getNumpyArray() + + #//getNumpyArray end + + #//arraydefaultvalues begin + + initArray = [0,1,2,3,4,5,6,7,8,9] + exampleArray.insertAsInt32(0, initArray) + + #//arraydefaultvalues end + + #//resizesingle begin + newSize = 20 baseValue = 1 exampleArray.resizeAsInt32(newSize, baseValue) @@ -84,6 +173,10 @@ if __name__ == "__main__": #All other supported data types have similarly named function calls #For example to insert a double resizeAsFloat64 is called + #//resizesingle end + + #//resizevector begin + newSizeArray = UInt32Vector() newSizeArray.push_back(4) newSizeArray.push_back(5) @@ -97,6 +190,10 @@ if __name__ == "__main__": #All other supported data types have similarly named function calls #For example to insert a double resizeAsFloat64 is called + #//resizevector end + + #//getValueindex begin + #If exampleArray contains [0, 1, 2, 3, 4, 5, 6, 7] exampleValue = exampleArray.getValueAsInt32(4) #exampleValue now equals 4 @@ -104,19 +201,35 @@ if __name__ == "__main__": #getValueAsInt32 returns an int value while getValueAsFloat64 returns a double value #Variations of this function exist for all supported data types + #//getValueindex end + + #//getValuesparse begin + exampleValueString = exampleArray.getValuesString() valueArray = [float(piece) for piece in exampleArray.getValuesString().split()] #This is one method of getting the contained values of the array + #//getValuesparse end + + #//isInitialized begin + if not(exampleArray.isInitialized()): exampleArray.read() + #//isInitialized end + + #//getValuesInternal begin + exampleValues = exampleArray.getValuesInternal() #alternatively getBuffer gives a buffer object exampleValues = exampleArray.getBuffer() #due to the way python handles void pointers, this function is only useful for getting a pointer to pass #if the retrieval of the internal values of the array is required, another function should be used + #//getValuesInternal end + + #//swap begin + swapArray = XdmfArray.New() initArray2 = [1,2,3,4,5] swapArray.insertAsInt32(0, initArray2) @@ -124,12 +237,20 @@ if __name__ == "__main__": exampleArray.swap(swapArray) #Now exampleArray contains {1,2,3,4,5} and swapArray contains {0,1,2,3,4,5,6,7,8,9} + #//swap end + + #//pushBack begin + newValue = 5 exampleArray.pushBackAsInt32(newValue) #For Python pushBack has multiple functions to cover different data types #This case used an int so the function was pushBackAsInt32 #Another example would be to use pushBackAsFloat64 for double values + #//pushBack end + + #//pointinsert begin + newIndex = 0 newValue = 3.5 exampleArray.insertAsFloat64(newIndex, newValue) @@ -137,34 +258,75 @@ if __name__ == "__main__": #versions for all other data types exist #for example insertAsInt32 inserts as an int + #//pointinsert end + + #//erase begin + #If exampleArray contains [0, 1, 2, 3, 4, 5, 6, 7] erasedIndex = 4 exampleArray.erase(erasedIndex) #exampleArray now contains the following #[0, 1, 2, 3, 5, 6, 7] - exampleArray.clear() + #//erase end + + #//clear begin + exampleArray.clear() + #//clear end + #//getHeavyDataController begin exampleController = exampleArray.getHeavyDataController() + #//getHeavyDataController end + + #//setHeavyDataController begin + newArray = XdmfArray.New() newArray.setHeavyDataController(exampleController) - exampleArray.release() + #//setHeavyDataController end + #//release begin + exampleArray.release() + #//release end + + #//getSupportedOperations begin exampleOperations = XdmfArray.getSupportedOperations() + + #//getSupportedOperations end + + #//getSupportedFunctions begin + exampleFunctions = XdmfArray.getSupportedFunctions() + + #//getSupportedFunctions end + + #//getValidVariableChars begin + exampleVariableChars = XdmfArray.getValidVariableChars() + + #//getValidVariableChars end + + #//getValidDigitChars begin + exampleDigitChars = XdmfArray.getValidDigitChars() + #//getValidDigitChars end + + #//getOperationPriority begin + examplePriority = XdmfArray.getOperationPriority('|') + #//getOperationPriority end + + #//valueinit begin + valueArray1 = XdmfArray.New() valueArray1.pushBackAsInt32(1) valueArray1.pushBackAsInt32(2) @@ -180,17 +342,58 @@ if __name__ == "__main__": valueVector.push_back(valueArray1) valueVector.push_back(valueArray2) + #//valueinit end + + #//sum begin + answerArray = XdmfArray.sum(valueVector) - answerArray = XdmfArray.ave(valueVector) + + #//sum end + + #//average begin + + answerArray = XdmfArray.average(valueVector) + + #//average end + + #//chunk begin + answerArray = XdmfArray.chunk(valueArray1, valueArray2) + + #//chunk end + + #//interlace begin + answerArray = XdmfArray.interlace(valueArray1, valueArray2) + #//interlace end + + #//addOperation begin + exampleNumOperations = XdmfArray.addOperation('@', prepend, 2) + + #//addOperation end + + #//evaluateOperation begin + answerArray = XdmfArray.evaluateOperation(valueArray1, valueArray2, '@') + #//evaluateOperation end + + #//addFunction begin + exampleNumFunctions = XdmfArray.addFunction("MAX", maximum) + + #//addFunction end + + #//evaluateFunction begin + answerArray = XdmfArray.evaluateFunction(valueVector, "MAX") + #//evaluateFunction end + + #//evaluateExpression begin + valueMap = ArrayMap() valueMap["A"] = valueArray1 valueMap["B"] = valueArray2 @@ -198,6 +401,9 @@ if __name__ == "__main__": parsedExpression = "MAX(A,B)@(A#B)" answerArray = XdmfArray.evaluateExpression(parsedExpression, valueMap) + #//evaluateExpression end + + #//insertmultidim begin writtenArray = XdmfArray.New() dimensionVector = UInt32Vector() @@ -232,3 +438,5 @@ if __name__ == "__main__": readDim.push_back(2) readArray.insert(readStarts, writtenArray, writeStarts, writeDim, readDim, readStrides, writeStrides) + + #//insertmultidim end diff --git a/examples/Python/XdmfExampleArrayType.py b/examples/Python/XdmfExampleArrayType.py index 4b907840..f692a17b 100644 --- a/examples/Python/XdmfExampleArrayType.py +++ b/examples/Python/XdmfExampleArrayType.py @@ -1,13 +1,31 @@ from Xdmf import * if __name__ == "__main__": + #//getElementSize begin + dataSize = XdmfArrayType.Int8().getElementSize() + #//getElementSize end + + #//getName begin + dataName = XdmfArrayType.Int8().getName() + #//getName end + + #//getType begin + exampleArray = XdmfArray.New() exampleType = exampleArray.getType() if exampleType == XdmfArrayType.Int8(): #do whatever is to be done if the type is Int8 + + #//getType end + + #//comparePrecision begin + + resultType = XdmfArrayType.comparePrecision(XdmfArrayType.Int16(), XdmfArrayType.UInt8()) + + #//comparePrecision end diff --git a/examples/Python/XdmfExampleAttribute.py b/examples/Python/XdmfExampleAttribute.py index 9fb5b080..b64609f8 100644 --- a/examples/Python/XdmfExampleAttribute.py +++ b/examples/Python/XdmfExampleAttribute.py @@ -1,22 +1,52 @@ from Xdmf import * if __name__ == "__main__": + + #//initialization begin exampleAttribute = XdmfAttribute.New() + #//initialization end #Assuming that exampleAttribute is a shared pointer to an XdmfAttribute object + #//setCenter begin + exampleAttribute.setCenter(XdmfAttributeCenter.Node()) + + #//setCenter end + + #//setName begin + newName = "New Name" exampleAttribute.setName(newName) + + #//setNAme end + + #//setType begin + exampleAttribute.setType(XdmfAttributeType.Scalar()) + #//setType end + + #//getCenter begin + exampleCenter = exampleAttribute.getCenter() if exampleCenter == XdmfAttributeCenter.Grid(): #do whatever is to be done if the center is a grid + #//getCenter end + + #//getName begin + exampleName = exampleAttribute.getName() + + #//getName end + + #//getType begin + exampleType = exampleAttribute.getType() if exampleType == XdmfAttributeType.Scalar(): #do whatever is to be done if the Type is a Scalar + + #//getType end diff --git a/examples/Python/XdmfExampleCoreItemFactory.py b/examples/Python/XdmfExampleCoreItemFactory.py index 9685bcf5..f7cc1266 100644 --- a/examples/Python/XdmfExampleCoreItemFactory.py +++ b/examples/Python/XdmfExampleCoreItemFactory.py @@ -1,6 +1,8 @@ from Xdmf import * if __name__ == "__main__": + #//createItem begin + #using XdmfItemFactory because XdmfCoreItemFactory is abstract exampleFactory = XdmfItemFactory.New() newProperties = StringMap() @@ -9,3 +11,5 @@ if __name__ == "__main__": #Same usage as the individual constructors #childItems and itemProperties are not added to the item when created this way #the collections are used to determine type + + #//createItem end diff --git a/examples/Python/XdmfExampleCoreReader.py b/examples/Python/XdmfExampleCoreReader.py index 50eb51c3..d4c582dc 100644 --- a/examples/Python/XdmfExampleCoreReader.py +++ b/examples/Python/XdmfExampleCoreReader.py @@ -1,16 +1,41 @@ from Xdmf import * if __name__ == "__main__": + #//initialization begin + #using XdmfReader since XdmfCoreReader is abstract exampleReader = XdmfReader.New() + #//initialization end + + #//parse begin readLight = "1 1 1 1 1 1 3 5 7 4 2" exampleItem = exampleReader.parse(readLight) + #//parse end + + #//readpath begin + readPath = "your file path here"; + + #//readpath end + + #//readroot begin + exampleItem = exampleReader.read(readPath) + + #//readroot end + + #//readItems begin + exampleCollection = exampleReader.readItems(readPath) + #//readItems end + + #//readXPath begin + readXPath = "your X path here" exampleItems = exampleReader.read(readPath, readXPath) + + #//readXPath end diff --git a/examples/Python/XdmfExampleCurvilinearGrid.py b/examples/Python/XdmfExampleCurvilinearGrid.py index 90b0e6bf..feb3293d 100644 --- a/examples/Python/XdmfExampleCurvilinearGrid.py +++ b/examples/Python/XdmfExampleCurvilinearGrid.py @@ -3,33 +3,68 @@ from Xdmf import * if __name__ == "__main__": #Assuming that exampleGrid is a shared pointer to an XdmfCurvilinearGrid object + #//initialization begin + newPointsX = 5 newPointsY = 5 newPointsZ = 5 + + #//initialization end + + #//constructor2 begin + exampleGrid = XdmfCurvilinearGrid.New(newPointsX, newPointsY) + + #//constructor2 end + + #//constructor3 begin + exampleGrid = XdmfCurvilinearGrid.New(newPointsX, newPointsY, newPointsZ) + + #//constructor3 end + + #//constructorvector begin + newPoints = XdmfArray.New() newPoints.pushBackAsInt32(5) newPoints.pushBackAsInt32(5) newPoints.pushBackAsInt32(5) exampleGrid = XdmfCurvilinearGrid.New(newPoints) - #setGeometry + #//constructorvector end + + #//setGeometry begin + newPoints = XdmfArray.New() newPoints.pushBackAsInt32(5) newPoints.pushBackAsInt32(5) newPoints.pushBackAsInt32(5) newGeometry = XdmfGeometry.New() newGeometry.setType(XdmfGeometryType.XYZ()) - newGeometry.insert(0, newPoints, 0, 3, 1, 1)#Start index is 0, 3 values are passed, stride for both arrays is 1 + # Start index is 0, 3 values are passed, stride for both arrays is 1 + newGeometry.insert(0, newPoints, 0, 3, 1, 1) exampleGrid.setGeometry(newGeometry) - #setDimensions + #//setGeometry end + + #//setDimensions begin + newPoints = XdmfArray.New() newPoints.pushBackAsInt32(5) newPoints.pushBackAsInt32(5) newPoints.pushBackAsInt32(5) exampleGrid.setDimensions(newPoints) + #//setDimensions end + + #//getGeometry begin + exampleGeometry = exampleGrid.getGeometry() + + #//getGeometry end + + #//getDimensions begin + exampleDimensions = exampleGrid.getDimensions() + + #//getDimensions end diff --git a/examples/Python/XdmfExampleDSMNoThread.py b/examples/Python/XdmfExampleDSMNoThread.py index 31f0c7bd..a07fbe44 100644 --- a/examples/Python/XdmfExampleDSMNoThread.py +++ b/examples/Python/XdmfExampleDSMNoThread.py @@ -66,22 +66,15 @@ if __name__ == "__main__": if (id < size - numServersCores): - # This section is to demonstrate the functionality of the XdmfDSM classes exampleWriter.setServerMode(True) exampleServerMode = exampleWriter.getServerMode() - exampleServerComm = exampleWriter.getServerComm() - exampleWriter.setServerComm(exampleServerComm) - exampleWorkerComm = exampleWriter.getWorkerComm() exampleWriter.setWorkerComm(exampleWorkerComm) ''' - exampleServerComm = exampleController.getServerComm() - exampleController.setServerComm(exampleServerComm) - exampleWorkerComm = exampleController.getWorkerComm() exampleController.setWorkerComm(exampleWorkerComm) ''' @@ -94,11 +87,9 @@ if __name__ == "__main__": writeStrideVector, writeCountVector, writeDataSizeVector, - exampleWriter.getServerBuffer(), - size-numServersCores, - size-1); + exampleWriter.getServerBuffer()); - exampleWriter2 = XdmfHDF5WriterDSM.New(newPath, exampleWriter.getServerBuffer(), size-numServersCores, size-1); + exampleWriter2 = XdmfHDF5WriterDSM.New(newPath, exampleWriter.getServerBuffer()); writeController.setServerMode(True) exampleControllerServerMode = writeController.getServerMode() @@ -202,13 +193,6 @@ if __name__ == "__main__": writeComm = workerComm.Create(writingCores) - if (id < (int)((size - numServersCores) / 2)): - exampleBuffer.GetComm().DupComm(writeComm) - exampleBuffer.ReceiveInfo() - else: - exampleBuffer.GetComm().DupComm(readComm) - exampleBuffer.SendInfo() - exampleBuffer.GetComm().DupComm(workerComm) if (id == 0): @@ -237,10 +221,10 @@ if __name__ == "__main__": exampleIntraComm = exampleDSMComm.GetIntraComm() exampleDSMComm.DupComm(exampleIntraComm.Dup()) - print type(exampleDSMComm.GetDsmMasterHostName()) + print type(exampleDSMComm.GetDsmPortName()) testName = "test" - exampleDSMComm.SetDsmMasterHostName(testName) - print exampleDSMComm.GetDsmMasterHostName() + exampleDSMComm.SetDsmPortName(testName) + print exampleDSMComm.GetDsmPortName() ''' @@ -254,7 +238,7 @@ if __name__ == "__main__": if (!connectingGroup): exampleDSMComm.OpenPort() - portString = exampleDSMComm.GetDsmMasterHostName() + portString = exampleDSMComm.GetDsmPortName() // Send the port string to the connecting group exampleDSMComm.Accept() // When done with connection @@ -262,14 +246,14 @@ if __name__ == "__main__": if (connectingGroup): // Recieve string from Master group - exampleDSMComm.SetDsmMasterHostName(portString) + exampleDSMComm.SetDsmPortName(portString) exampleDSMComm.Connect() // When done with connection exampleDSMComm.Disconnect() if (connectingGroup): // Recieve string from Master group - exampleDSMComm.SetDsmMasterHostName(portString); + exampleDSMComm.SetDsmPortName(portString); exampleManager.Connect(); // When done with connection exampleManager.Disconnect(); @@ -277,7 +261,6 @@ if __name__ == "__main__": ''' # This is the end of the Demonstration - exampleWriter.setMode(XdmfHeavyDataWriter.Hyperslab) @@ -333,9 +316,7 @@ if __name__ == "__main__": readStrideVector, readCountVector, readDataSizeVector, - exampleWriter.getServerBuffer(), - size-numServersCores, - size-1) + exampleWriter.getServerBuffer()) readArray.insert(readController) @@ -377,7 +358,6 @@ if __name__ == "__main__": # End of Work Section - if (id == 0): exampleWriter.stopDSM() ''' @@ -391,6 +371,11 @@ if __name__ == "__main__": exampleInterComm = exampleDSMComm.GetInterComm() exampleDSMComm.DupInterComm(exampleInterComm.Dup()) + if (id >= size - numServersCores): + exampleWriter.getServerBuffer().SendInfo() + else: + exampleWriter.getServerBuffer().ReceiveInfo() + ''' exampleWriter.restartDSM() exampleController.restartDSM() diff --git a/examples/Python/XdmfExampleDomain.py b/examples/Python/XdmfExampleDomain.py index 2f2f8607..59a819cc 100644 --- a/examples/Python/XdmfExampleDomain.py +++ b/examples/Python/XdmfExampleDomain.py @@ -1,4 +1,9 @@ from Xdmf import * if __name__ == "__main__": + + #//initialization begin + exampleDomain = XdmfDomain.New() + + #//initialization end diff --git a/examples/Python/XdmfExampleError.py b/examples/Python/XdmfExampleError.py index 99fd38d5..d18b9248 100644 --- a/examples/Python/XdmfExampleError.py +++ b/examples/Python/XdmfExampleError.py @@ -1,18 +1,60 @@ from Xdmf import * if __name__ == "__main__": - exampleLevel = XdmfError.getLevelLimit()#these are considered integers in Python + #//getLevelLimit begin + + exampleLevel = XdmfError.getLevelLimit() + #these are considered integers in Python + + #//getLevelLimit end + + #//setLevelLimit begin XdmfError.setLevelLimit(XdmfError.FATAL) + #//setLevelLimit end + + #//message begin + try: XdmfError::message(XdmfError::FATAL, "this is an example error") except RuntimeError as exampleError: print exampleError + #//message end + + #//what begin + try: raise RuntimeError(XdmfError(XdmfError.FATAL, "testError")) except RuntimeError as exampleError: errorString = e.args[0].what() + + #//what end + + #//getLevel begin + + try: + raise RuntimeError(XdmfError(XdmfError.FATAL, "testError")) + except RuntimeError as exampleError: errorLevel = e.args[0].getLevel() + + #//getLevel end + + #//setLevel begin + + try: + raise RuntimeError(XdmfError(XdmfError.FATAL, "testError")) + except RuntimeError as exampleError: e.args[0].setLevel(XdmfError.FATAL) + + #//setLevel end + + #//initialization begin + + try: + raise RuntimeError(XdmfError(XdmfError.FATAL, "testError")) + except RuntimeError as exampleError: + print exampleError + + #//initialization end diff --git a/examples/Python/XdmfExampleGeometry.py b/examples/Python/XdmfExampleGeometry.py index a62ee8b1..73e9de09 100644 --- a/examples/Python/XdmfExampleGeometry.py +++ b/examples/Python/XdmfExampleGeometry.py @@ -1,12 +1,29 @@ from Xdmf import * if __name__ == "__main__": + + #//initialization begin + exampleGeometry = XdmfGeometry.New() + #//initialization end + #Assuming that exampleGeometry is a shared pointer to a XdmfGeometry object + #//setType begin + exampleGeometry.setType(XdmfGeometryType.XYZ()) + #//setType end + + #//getType begin + exampleType = exampleGeometry.getType() + #//getType end + + #//getNumberPoints begin + numPoints = exampleGeometry.getNumberPoints() + + #//getNumberPoints end diff --git a/examples/Python/XdmfExampleGeometryType.py b/examples/Python/XdmfExampleGeometryType.py index ddc50e51..b7a7efc4 100644 --- a/examples/Python/XdmfExampleGeometryType.py +++ b/examples/Python/XdmfExampleGeometryType.py @@ -1,12 +1,26 @@ from Xdmf import * if __name__ == "__main__": + + #//getDimensions begin + exampleDimensions = XdmfGeometryType.XYZ().getDimensions() + + #//getDimensions end + + #//getName begin + exampleName = XdmfGeometryType.XYZ().getName() + #//getName end + + #//getType begin + exampleGeometry = XdmfGeometry.New() exampleType = exampleGeometry.getType() if exampleType == XdmfGeometryType.XYZ(): #do whatever is to be done if the geometry is XYZ + + #//getType end diff --git a/examples/Python/XdmfExampleGraph.py b/examples/Python/XdmfExampleGraph.py index f58dbb0c..08f3a06d 100644 --- a/examples/Python/XdmfExampleGraph.py +++ b/examples/Python/XdmfExampleGraph.py @@ -1,4 +1,9 @@ from Xdmf import * if __name__ == "__main__": + + #//initialization begin + exampleGraph = XdmfGraph.New() + + #//initialization end diff --git a/examples/Python/XdmfExampleGrid.py b/examples/Python/XdmfExampleGrid.py index 59e7ad09..0097cd89 100644 --- a/examples/Python/XdmfExampleGrid.py +++ b/examples/Python/XdmfExampleGrid.py @@ -1,21 +1,48 @@ from Xdmf import * if __name__ == "__main__": + #//initialization begin + exampleGrid = XdmfUnstructuredGrid.New() #Using an unstructured grid since XdmfGrid is an abstract class - #Assumming that exampleGrid is a shared pointer to an XdmfUnstructuredGrid object + + #//initialization end + + #//setName begin newName = "New Name" exampleGrid.setName(newName) + #//setName end + + #//setTime begin + newTime = XdmfTime.New(20.0) exampleGrid.setTime(newTime) + #//setTIme end + + #//getTime begin + exampleTime = exampleGrid.getTime() + #//getTime end + + #//getName begin + exampleName = exampleGrid.getName() + #//getName end + + #//getGeometry begin + exampleGeometry = exampleGrid.getGeometry() + #//getGeometry end + + #//getTopology begin + exampleTopology = exampleGrid.getTopology() + + #//getTopology end diff --git a/examples/Python/XdmfExampleGridCollection.py b/examples/Python/XdmfExampleGridCollection.py index 45f318bb..129a77c3 100644 --- a/examples/Python/XdmfExampleGridCollection.py +++ b/examples/Python/XdmfExampleGridCollection.py @@ -3,18 +3,34 @@ from Xdmf import * if __name__ == "__main__": #Assuming that exampleCollection is a shared pointer to an XdmfGridCollection object + #//initialization begin + exampleCollection = XdmfGridCollection.New() + #//initialization end + + #//setType begin + exampleCollection.setType(XdmfGridCollectionType.Temporal()) + #//setType end + + #//getType begin + exampleType = exampleCollection.getType() if exampleType == XdmfGridCollectionType.Temporal(): #do whatever is to be done if the grid collection is temporal + #//getType end + + #//insert begin + exampleInformation = XdmfInformation.New() newKey = "New Key" newValue = "New Value" exampleInformation.setKey(newKey) exampleInformation.setValue(newValue) exampleCollection.insert(exampleInformation) + + #//insert end diff --git a/examples/Python/XdmfExampleItemFactory.py b/examples/Python/XdmfExampleItemFactory.py index 7906191b..eec90e07 100644 --- a/examples/Python/XdmfExampleItemFactory.py +++ b/examples/Python/XdmfExampleItemFactory.py @@ -1,4 +1,9 @@ from Xdmf import * if __name__ == "__main__": + + #//initialization begin + exampleFactory = XdmfItemFactory.New() + + #//initialization end diff --git a/examples/Python/XdmfExampleMap.py b/examples/Python/XdmfExampleMap.py index 13abd28b..56f243c5 100644 --- a/examples/Python/XdmfExampleMap.py +++ b/examples/Python/XdmfExampleMap.py @@ -1,9 +1,14 @@ from Xdmf import * if __name__ == "__main__": + + #//initialization begin + exampleMap = XdmfMap.New() - #Assumming that exampleMap is a shared pointer to a XdmfMap object + #//initialization end + + #//initializationnode begin #create attributes for each task id #the index of the node id in the attribute is the local node id @@ -27,12 +32,6 @@ if __name__ == "__main__": testVector.push_back(map1Attribute) testVector.push_back(map2Attribute) - newRemoteTaskID = 4 - newLocalNodeID = 7 - newRemoteLocalNodeID = 3 - exampleMap.insert(newRemoteTaskID, newLocalNodeID, newRemoteLocalNodeID) - #This inserts an entry of (4, 7, 3) into the map - exampleMapVector = XdmfMap.New(testVector) #returns a vector of maps that holds the equivalencies for the nodes provided #for example if Attribute 1 had globalNodeID 3 at localNodeID 2 @@ -41,6 +40,20 @@ if __name__ == "__main__": #and map 3 would have an entry of (1, 2, 5) #The entries are formatted (remoteTaskID, remoteLocalNodeID, localNodeID) + #//initializationnode end + + #//inserttuple begin + + newRemoteTaskID = 4 + newLocalNodeID = 7 + newRemoteLocalNodeID = 3 + exampleMap.insert(newRemoteTaskID, newLocalNodeID, newRemoteLocalNodeID) + #This inserts an entry of (4, 7, 3) into the map + + #//inserttuple end + + #//setMap begin + newTaskMap = XdmfMapMap() newNodeIdMap = XdmfMapNodeIdMap() newNodeIdMap[2] = (3, 6, 8) @@ -82,12 +95,23 @@ if __name__ == "__main__": #(2, 9, 9) #Is now stored in exampleMap + #//setMap end + + #//setName begin + newName = "New Name" exampleMap.setName(newName) + #//setName end + + #//getName begin + exampleName = exampleMap.getName() - #getMap + #//getName end + + #//getMap begin + #Assuming that exampleMap is a shared pointer to an XdmfMap object filled with the following tuples #(1, 1, 9) #(1, 2, 8) @@ -120,6 +144,9 @@ if __name__ == "__main__": print val #prints out all the remote node values associated with taskID 1 and localNode 1 + #//getMap end + + #//getRemoteNodeIds begin nodeIDMap = exampleMap.getRemoteNodeIds(1) #nodeIDMap now contains the following tuples because it retrieved the tuples associated with taskID 1 @@ -137,11 +164,23 @@ if __name__ == "__main__": print val #prints out all the remote node values associated with taskID 1 and localNode 1 + #//getRemoteNodeIds end + + #//isInitialized begin + if not(exampleMap.isInitialized()): exampleMap.read() + #//isInitialized end + + #//release begin + exampleMap.release() + #//release end + + #//setHeavyDataControllers begin + hdf5FilePath = "The HDF5 file path goes here" hdf5SetPath = "The HDF5 set path goes here" startIndex = 0#start at the beginning @@ -162,3 +201,5 @@ if __name__ == "__main__": startIndex, readStride, readNumber) exampleMap = XdmfMap.New() exampleMap.setHeavyDataControllers(newRemoteTaskController, newLocalNodeController, newRemoteLocalNodeController) + + #//setHeavyDataControllers end diff --git a/examples/Python/XdmfExampleReader.py b/examples/Python/XdmfExampleReader.py index 919a47c7..fec7aa14 100644 --- a/examples/Python/XdmfExampleReader.py +++ b/examples/Python/XdmfExampleReader.py @@ -1,4 +1,9 @@ from Xdmf import * if __name__ == "__main__": + + #//initialization begin + exampleReader = XdmfReader.New() + + #//initialization end diff --git a/examples/Python/XdmfExampleRectilinearGrid.py b/examples/Python/XdmfExampleRectilinearGrid.py index 8c7e80c3..77f5feca 100644 --- a/examples/Python/XdmfExampleRectilinearGrid.py +++ b/examples/Python/XdmfExampleRectilinearGrid.py @@ -3,6 +3,8 @@ from Xdmf import * if __name__ == "__main__": #Assuming that exampleGrid is a shared pointer to an XdmfRectilinearGrid + #//initvalues + pointsXArray = XdmfArray.New() pointsXArray.pushBackAsInt32(5) pointsXArray.pushBackAsInt32(6) @@ -17,7 +19,6 @@ if __name__ == "__main__": pointsYArray.pushBackAsInt32(8) pointsYArray.pushBackAsInt32(7) pointsYArray.pushBackAsInt32(10) - exampleGrid = XdmfRectilinearGrid.New(pointsXArray, pointsYArray) pointsZArray = XdmfArray.New() pointsZArray.pushBackAsInt32(3) pointsZArray.pushBackAsInt32(9) @@ -25,21 +26,58 @@ if __name__ == "__main__": pointsZArray.pushBackAsInt32(5) pointsZArray.pushBackAsInt32(7) pointsZArray.pushBackAsInt32(2) + + #//initvalues + + #//initialization2 + + exampleGrid = XdmfRectilinearGrid.New(pointsXArray, pointsYArray) + + #//initialization2 + + #//initialization3 + exampleGrid = XdmfRectilinearGrid.New(pointsXArray, pointsYArray, pointsZArray) + #//initialization3 + + #//setCoordinatessingle + exampleGrid.setCoordinates(0, pointsXArray) + #//setCoordinatessingle + + #//initializevector + pointsCollector = ArrayVector() pointsCollector.push_back(pointsXArray) pointsCollector.push_back(pointsYArray) pointsCollector.push_back(pointsZArray) exampleGrid = XdmfRectilinearGrid.New(pointsCollector) + #//initializevector + + #//getCoordinatessingle + readPointsX = exampleGrid.getCoordinates(0) readPointsY = exampleGrid.getCoordinates(1) + #//getCoordinatessingle + + #//getCoordinatesvector + exampleCoordinates = exampleGrid.getCoordinates() + #//getCoordinatesvector + + #//getDimensions + exampleDimensions = exampleGrid.getDimensions() + #//getDimensions + + #//setCoordinatesvector + exampleGrid.setCoordinates(pointsCollector) + + #//setCoordinatesvector diff --git a/examples/Python/XdmfExampleRegularGrid.py b/examples/Python/XdmfExampleRegularGrid.py index cee65dd1..e469a6d6 100644 --- a/examples/Python/XdmfExampleRegularGrid.py +++ b/examples/Python/XdmfExampleRegularGrid.py @@ -3,6 +3,8 @@ from Xdmf import * if __name__ == "__main__": #Assuming exampleGrid is a shared pointer to an XdmfRegularGrid object + #//initvalues begin + newBrickX = 20.0 newPointsX = 5 newOriginX = 0.0 @@ -13,17 +15,41 @@ if __name__ == "__main__": newPointsZ = 5 newOriginZ = 0.0 + #//initvalues end + + #//initialization2 begin + exampleGrid = XdmfRegularGrid.New( newBrickX, newBrickY, newPointsX, newPointsY, newOriginX, newOriginY) + #//initialization2 end + + #//initialization3 begin + exampleGrid = XdmfRegularGrid.New( newBrickX, newBrickY, newBrickZ, newPointsX, newPointsY, newPointsZ, newOriginX, newOriginY, newOriginZ) + #//initialization3 end + + #//getBrickSize begin exampleBrick = exampleGrid.getBrickSize() + + #//getBrickSize end + + #//getDimensions begin + exampleDimensions = exampleGrid.getDimensions() + + #//getDimensions end + + #//getOrigin begin + exampleOrigin = exampleGrid.getOrigin() + #//getOrigin end + + #//initializationvector begin newBrickSize = XdmfArray.New() newBrickSize.pushBackAsFloat64(20.0) @@ -40,6 +66,22 @@ if __name__ == "__main__": exampleGrid = XdmfRegularGrid.New(newBrickSize, newNumPoints, newGridOrigin) + #//initializationvector end + + #//setBrickSize begin + exampleGrid.setBrickSize(newBrickSize) + + #//setBrickSize end + + #//setDimensions begin + exampleGrid.setDimensions(newNumPoints) + + #//setDimensions end + + #//setOrigin begin + exampleGrid.setOrigin(newGridOrigin) + + #//setOrigin end diff --git a/examples/Python/XdmfExampleSet.py b/examples/Python/XdmfExampleSet.py index 789adc58..516e0e06 100644 --- a/examples/Python/XdmfExampleSet.py +++ b/examples/Python/XdmfExampleSet.py @@ -1,18 +1,36 @@ from Xdmf import * if __name__ == "__main__": - #Assuming that exampleSet is a shared pointer to an XdmfSet object + #//initialization begin exampleSet = XdmfSet.New() + #//initialization end + + #//setName begin + std::string newName = "New Name"; exampleSet->setName(newName); + #//setName end + + #//setType begin + exampleSet->setType(XdmfSetType::Node()); + #//setType end + + #//getName begin + exampleName = exampleSet.getName() + #//getName end + + #//getType begin + exampleType = exampleSet.getType() if exampleType == XdmfSetType.Node(): #do whatever is to be done if the set is a node + + #//getType end diff --git a/examples/Python/XdmfExampleTime.py b/examples/Python/XdmfExampleTime.py index 2ac84f1b..23941c42 100644 --- a/examples/Python/XdmfExampleTime.py +++ b/examples/Python/XdmfExampleTime.py @@ -1,7 +1,7 @@ from Xdmf import * if __name__ == "__main__": - #Assumming that exampleTime is a shared pointer to an XdmfTime object + #//initialization begin exampleTime = XdmfTime.New() #The Default case sets the time to 0.0 @@ -10,6 +10,16 @@ if __name__ == "__main__": newTime = 5.0 exampleTime2 = XdmfTime.New(newTime) + #//initialization end + + #//setValue begin + exampleTime.setValue(newTime) - readTime = exampleTime.getTime() + #//setValue end + + #//getValue begin + + readTime = exampleTime.getValue() + + #//getValue end diff --git a/examples/Python/XdmfExampleTopology.py b/examples/Python/XdmfExampleTopology.py index 1aa6624a..91928c78 100644 --- a/examples/Python/XdmfExampleTopology.py +++ b/examples/Python/XdmfExampleTopology.py @@ -1,12 +1,26 @@ from Xdmf import * if __name__ == "__main__": + #//initialization begin + exampleTopology = XdmfTopology.New() - #Assuming that exampleTopology is a shared pointer to an XdmfTopology object + #//initialization end + + #//setType begin exampleTopology.setType(XdmfTopologyType.Pyramid()) + #//setType end + + #//getType begin + exampleType = exampleTopology.getType() + #//getType end + + #//getNumberElements begin + numElements = exampleTopology.getNumberElements() + + #//getNumberElements end diff --git a/examples/Python/XdmfExampleTopologyType.py b/examples/Python/XdmfExampleTopologyType.py index 3ec461d0..25bc24b7 100644 --- a/examples/Python/XdmfExampleTopologyType.py +++ b/examples/Python/XdmfExampleTopologyType.py @@ -1,27 +1,59 @@ from Xdmf import * if __name__ == "__main__": + #//initialization begin + exampleID = XdmfTopologyType.Triangle().getID() createdTopology = XdmfTopology.New() createdTopology.setType(XdmfTopologyType.New(exampleID)) + #//initialization end + + #//getCellType begin + exampleType = XdmfTopologyType.Linear if exampleType == exampleTopology.getCellType: ''' Do whatever is to be done if the cell type is linear ''' + #//getCellType end + + #//getEdgesPerElement begin + numEdges = XdmfTopologyType.Triangle().getEdgesPerElement() + #//getEdgesPerElement end + + #//getFacesPerElement begin + numFaces = XdmfTopologyType.Triangle().getFacesPerElement() + #//getFacesPerElement end + + #//getId begin + holdID = XdmfTopologyType::Triangle().getID() + #//getId end + + #//getName begin + exampleName = XdmfTopologyType.Triangle().getName() + #//getName end + + #//getNodesPerElement begin + numNodes = XdmfTopologyType.Triangle().getNodesPerElement() + #//getNodesPerElement end + + #//getType begin + testType = createdTopology.getType() if testType == XdmfTopologyType.Triangle: #do whatever is to be done if the type is a triangle + + #//getType end diff --git a/examples/Python/XdmfExampleUnstructuredGrid.py b/examples/Python/XdmfExampleUnstructuredGrid.py index 2d51e16a..7365fb9d 100644 --- a/examples/Python/XdmfExampleUnstructuredGrid.py +++ b/examples/Python/XdmfExampleUnstructuredGrid.py @@ -1,10 +1,14 @@ from Xdmf import * if __name__ == "__main__": - #Assuming that exampleGrid is a shared pointer to an XdmfUnstructuredGrid object + #//initialization begin exampleGrid = XdmfUnstructuredGrid.New() + #//initialization end + + #//initializationregular begin + newBrickX = 0.0 newBrickY = 0.0 newPointsX = 5 @@ -14,6 +18,10 @@ if __name__ == "__main__": baseGrid = XdmfRegularGrid.New(newBrickX, newBrickY, newPointsX, newPointsY, newOriginX, newOriginY) regGeneratedGrid = XdmfUnstructuredGrid.New(baseGrid) + #//initializationregular end + + #//setGeometry begin + newGeometry = XdmfGeometry.New() newGeometry.setType(XdmfGeometryType.XYZ()) newGeometry.pushBackAsInt32(1) @@ -27,6 +35,10 @@ if __name__ == "__main__": newGeometry.pushBackAsInt32(9) exampleGrid.setGeometry(newGeometry) + #//setGeometry end + + #//setTopology begin + newTopology = XdmfTopology.New() newTopology.setType(XdmfTopologyType.Triangle()) newTopology.pushBackAsInt32(1) @@ -40,5 +52,16 @@ if __name__ == "__main__": newTopology.pushBackAsInt32(9) exampleGrid.setTopology(newTopology) + #//setTopology end + + #//getGeometry begin + exampleGeometry = exampleGrid.getGeometry() + + #//getGeometry end + + #//getTopology begin + exampleTopology = exampleGrid.getTopology() + + #//getTopology end diff --git a/tests/Cxx/HugeReadArray.cpp b/tests/Cxx/HugeReadArray.cpp index e976fc7a..c08d1f3c 100644 --- a/tests/Cxx/HugeReadArray.cpp +++ b/tests/Cxx/HugeReadArray.cpp @@ -9,6 +9,6 @@ int main(int, char **) shared_ptr testReader = XdmfReader::New(); shared_ptr readArray = shared_dynamic_cast(testReader->read("arraydata.xmf")); readArray->read(); - std::cout << "Array ocntains " << readArray->getValuesString() << std::endl; + std::cout << "Array contains " << readArray->getValuesString() << std::endl; return 0; } diff --git a/tests/Cxx/HugeWriteArray.cpp b/tests/Cxx/HugeWriteArray.cpp index b77b6eec..55fc05d6 100644 --- a/tests/Cxx/HugeWriteArray.cpp +++ b/tests/Cxx/HugeWriteArray.cpp @@ -32,33 +32,33 @@ int main(int, char **) dimensions.push_back(1000); dataspaces.push_back(3000); dataspaces.push_back(3000); - shared_ptr arrayController = XdmfHDF5Controller::New("arraydata.h5", "Data", XdmfArrayType::Int32(), starts, strides, dimensions, dataspaces); + shared_ptr arrayController = XdmfHDF5Controller::New("arraydata.h5", "TestingData", XdmfArrayType::Int32(), starts, strides, dimensions, dataspaces); writtenArray->insert(arrayController); starts[0] = 1; - arrayController = XdmfHDF5Controller::New("arraydata.h5", "Data", XdmfArrayType::Int32(), starts, strides, dimensions, dataspaces); + arrayController = XdmfHDF5Controller::New("arraydata.h5", "TestingData", XdmfArrayType::Int32(), starts, strides, dimensions, dataspaces); writtenArray->insert(arrayController); starts[0] = 2; - arrayController = XdmfHDF5Controller::New("arraydata.h5", "Data", XdmfArrayType::Int32(), starts, strides, dimensions, dataspaces); + arrayController = XdmfHDF5Controller::New("arraydata.h5", "TestingData", XdmfArrayType::Int32(), starts, strides, dimensions, dataspaces); writtenArray->insert(arrayController); starts[1] = 1; starts[0] = 0; - arrayController = XdmfHDF5Controller::New("arraydata.h5", "Data", XdmfArrayType::Int32(), starts, strides, dimensions, dataspaces); + arrayController = XdmfHDF5Controller::New("arraydata.h5", "TestingData", XdmfArrayType::Int32(), starts, strides, dimensions, dataspaces); writtenArray->insert(arrayController); starts[0] = 1; - arrayController = XdmfHDF5Controller::New("arraydata.h5", "Data", XdmfArrayType::Int32(), starts, strides, dimensions, dataspaces); + arrayController = XdmfHDF5Controller::New("arraydata.h5", "TestingData", XdmfArrayType::Int32(), starts, strides, dimensions, dataspaces); writtenArray->insert(arrayController); starts[0] = 2; - arrayController = XdmfHDF5Controller::New("arraydata.h5", "Data", XdmfArrayType::Int32(), starts, strides, dimensions, dataspaces); + arrayController = XdmfHDF5Controller::New("arraydata.h5", "TestingData", XdmfArrayType::Int32(), starts, strides, dimensions, dataspaces); writtenArray->insert(arrayController); starts[1] = 2; starts[0] = 0; - arrayController = XdmfHDF5Controller::New("arraydata.h5", "Data", XdmfArrayType::Int32(), starts, strides, dimensions, dataspaces); + arrayController = XdmfHDF5Controller::New("arraydata.h5", "TestingData", XdmfArrayType::Int32(), starts, strides, dimensions, dataspaces); writtenArray->insert(arrayController); starts[0] = 1; - arrayController = XdmfHDF5Controller::New("arraydata.h5", "Data", XdmfArrayType::Int32(), starts, strides, dimensions, dataspaces); + arrayController = XdmfHDF5Controller::New("arraydata.h5", "TestingData", XdmfArrayType::Int32(), starts, strides, dimensions, dataspaces); writtenArray->insert(arrayController); starts[0] = 2; - arrayController = XdmfHDF5Controller::New("arraydata.h5", "Data", XdmfArrayType::Int32(), starts, strides, dimensions, dataspaces); + arrayController = XdmfHDF5Controller::New("arraydata.h5", "TestingData", XdmfArrayType::Int32(), starts, strides, dimensions, dataspaces); writtenArray->insert(arrayController); shared_ptr arrayHeavyWriter = XdmfHDF5Writer::New("arraydata.h5"); diff --git a/tests/Cxx/XdmfPostFixCalc.cpp b/tests/Cxx/XdmfPostFixCalc.cpp index 82836191..3f29094e 100644 --- a/tests/Cxx/XdmfPostFixCalc.cpp +++ b/tests/Cxx/XdmfPostFixCalc.cpp @@ -6,6 +6,7 @@ #include #include #include +#include #include "boost/assign.hpp" double parse(std::string expression, std::map variables); @@ -35,13 +36,13 @@ std::map (*)(std::vector', invChunk, 2); - XdmfArray::addOperation('<', invChunk, 2); - XdmfArray::addOperation('@', invChunk, 2); + XdmfFunction::addFunction("MAX", maximum); + XdmfFunction::addOperation('&', invChunk, 2); + XdmfFunction::addOperation('!', invChunk, 2); + XdmfFunction::addOperation('^', invChunk, 2); + XdmfFunction::addOperation('>', invChunk, 2); + XdmfFunction::addOperation('<', invChunk, 2); + XdmfFunction::addOperation('@', invChunk, 2); functions["AVE"] = ave; //sometimes typecasts are required, sometimes they cause errors @@ -117,24 +118,24 @@ int main(int, char **) assert(answerArray->getSize() == 1); std::cout << "interlace" << std::endl; - answerArray = XdmfArray::evaluateOperation(testArray1, testArray5, '#'); + answerArray = XdmfFunction::evaluateOperation(testArray1, testArray5, '#'); std::cout << "answer array = " << answerArray->getValuesString() << std::endl; assert(answerArray->getValuesString().compare("1 5 1 5 1 5 1 5 1 5 1 5 1 5 1 5 1 5 1 5 5 5 5") == 0); std::cout << "chunk" << std::endl; - answerArray = XdmfArray::evaluateOperation(testArray1, testArray5, '|'); + answerArray = XdmfFunction::evaluateOperation(testArray1, testArray5, '|'); std::cout << "answer array = " << answerArray->getValuesString() << std::endl; assert(answerArray->getValuesString().compare("1 1 1 1 1 1 1 1 1 1 5 5 5 5 5 5 5 5 5 5 5 5 5") == 0); std::cout << "inverse chunk" << std::endl; - answerArray = XdmfArray::evaluateOperation(testArray1, testArray5, '@'); + answerArray = XdmfFunction::evaluateOperation(testArray1, testArray5, '@'); std::cout << "answer array = " << answerArray->getValuesString() << std::endl; assert(answerArray->getValuesString().compare("5 5 5 5 5 5 5 5 5 5 5 5 5 1 1 1 1 1 1 1 1 1 1") == 0); - answerArray = XdmfArray::evaluateExpression(arrayExpression, arrayVariable); + answerArray = XdmfFunction::evaluateExpression(arrayExpression, arrayVariable); std::cout << "after parsing" << std::endl; diff --git a/tests/Python/ReadArray.py b/tests/Python/ReadArray.py index e19e1a62..afd0b72c 100644 --- a/tests/Python/ReadArray.py +++ b/tests/Python/ReadArray.py @@ -27,24 +27,24 @@ def prepend(val1, val2): if __name__ == "__main__": #functions are passed as callable pyobjects - XdmfArray.addFunction("MAX", maximum) - functionVector = XdmfArray.getSupportedFunctions() + XdmfFunction.addFunction("MAX", maximum) + functionVector = XdmfFunction.getSupportedFunctions() for i in range (0, functionVector.size()): print functionVector[i] - XdmfArray.addOperation("@", prepend, 2) - print XdmfArray.getSupportedOperations() + XdmfFunction.addOperation("@", prepend, 2) + print XdmfFunction.getSupportedOperations() testVector = ArrayVector() testArray = XdmfArray.New() testArray.pushBackAsInt32(10) testArray.pushBackAsInt32(9) testVector.push_back(testArray) print "before evaluating function" - resultArray = XdmfArray.evaluateFunction(testVector, "MAX") + resultArray = XdmfFunction.evaluateFunction(testVector, "MAX") print type(resultArray) print "after function is evaulated" print resultArray.getValuesString() print "before evaluating function" - resultArray = XdmfArray.evaluateFunction(testVector, "AVE") + resultArray = XdmfFunction.evaluateFunction(testVector, "AVE") print type(resultArray) print "after function is evaulated" print resultArray.getValuesString() @@ -52,11 +52,11 @@ if __name__ == "__main__": testArray2.pushBackAsInt32(1) testArray2.pushBackAsInt32(2) print "before evaluating Operation" - resultArray = XdmfArray.evaluateOperation(testArray, testArray2, "|") + resultArray = XdmfFunction.evaluateOperation(testArray, testArray2, "|") print type(resultArray) print "after evaluationg Operation" print resultArray.getValuesString() - resultArray = XdmfArray.evaluateOperation(testArray, testArray2, "@") + resultArray = XdmfFunction.evaluateOperation(testArray, testArray2, "@") print type(resultArray) print "after evaluationg Operation" print resultArray.getValuesString() @@ -70,10 +70,7 @@ if __name__ == "__main__": testArray3.pushBackAsInt32(5) testArray3.pushBackAsInt32(5) testMap["C"] = testArray3 - resultArray = XdmfArray.evaluateExpression("A|B#C", testMap) + resultArray = XdmfFunction.evaluateExpression("A|B#C", testMap) print type(resultArray) print resultArray.getValuesString() print "after evaluating expression" - - #honestly, I don't think it's possible to make the dynamic library work in Python without completely reworking half of Xdmf - #(possible exaggeration, but either way, it would take a lot of work.) diff --git a/utils/CMakeLists.txt b/utils/CMakeLists.txt index 161de12c..291e6a0a 100644 --- a/utils/CMakeLists.txt +++ b/utils/CMakeLists.txt @@ -7,7 +7,8 @@ option(XDMF_BUILD_FORTRAN OFF) set(XdmfUtilsSources XdmfDiff - XdmfTopologyConverter) + XdmfTopologyConverter + XdmfUtils) set(XdmfUtilsLinkLibraries Xdmf) if(XDMF_BUILD_FORTRAN) diff --git a/utils/XdmfTopologyConverter.cpp b/utils/XdmfTopologyConverter.cpp index 7543ceaf..a30ccf1a 100644 --- a/utils/XdmfTopologyConverter.cpp +++ b/utils/XdmfTopologyConverter.cpp @@ -1256,3 +1256,418 @@ XdmfTopologyConverter::convert(const shared_ptr gridToConv return shared_ptr(); } + +shared_ptr +XdmfTopologyConverter::getExternalFaces(const shared_ptr convertedTopology) { + + if (convertedTopology->getSize() < convertedTopology->getType()->getNodesPerElement()) { + try { + XdmfError::message(XdmfError::FATAL, "Error: Not enough nodes for GetExternalSurface"); + } + catch (XdmfError e) { + throw e; + } + } + + long largestId = convertedTopology->getValue(0); + for (unsigned int i = 1; i < convertedTopology->getSize(); ++i) { + if (largestId < convertedTopology->getValue(i)) { + largestId = convertedTopology->getValue(i); + } + } + + std::vector > > hash(largestId); + + if(convertedTopology->getType() == XdmfTopologyType::Tetrahedron()) { + + // This loop can be generalized in a later version + for(int arrayOffset=0; arrayOffsetgetSize(); arrayOffset += convertedTopology->getType()->getNodesPerElement()) { + std::vector faceNodes; + for (unsigned int i = 0; i < convertedTopology->getType()->getNodesPerElement(); ++i) { + faceNodes.push_back(convertedTopology->getValue(arrayOffset + i)); + } + + std::vector< std::vector > faceVectors; + // 0, 1, 3 face + std::vector face1Vector; + face1Vector.push_back(faceNodes[0]); + face1Vector.push_back(faceNodes[1]); + face1Vector.push_back(faceNodes[3]); + faceVectors.push_back(face1Vector); + // 0, 2, 1 face + std::vector face2Vector; + face2Vector.push_back(faceNodes[0]); + face2Vector.push_back(faceNodes[2]); + face2Vector.push_back(faceNodes[1]); + faceVectors.push_back(face2Vector); + // 0, 3, 2 face + std::vector face3Vector; + face3Vector.push_back(faceNodes[0]); + face3Vector.push_back(faceNodes[3]); + face3Vector.push_back(faceNodes[2]); + faceVectors.push_back(face3Vector); + // 1, 2, 3 face + std::vector face4Vector; + face4Vector.push_back(faceNodes[1]); + face4Vector.push_back(faceNodes[2]); + face4Vector.push_back(faceNodes[3]); + faceVectors.push_back(face4Vector); + + for (unsigned int i = 0; i < faceVectors.size(); ++i) { + insertInHash(faceVectors[i], hash, 3); + } + } + + // create new topology + shared_ptr toReturn = XdmfTopology::New(); + toReturn->setType(XdmfTopologyType::Triangle()); + std::vector newCells; + int index = 0; + for(std::vector > >::const_iterator hashIter = hash.begin(); + hashIter != hash.end(); + ++hashIter, ++index) + { + const std::vector > & currHash = *hashIter; + for(std::vector >::const_iterator currHashIter = currHash.begin(); + currHashIter != currHash.end(); + ++currHashIter) + { + const std::vector & currFaceIds = *currHashIter; + newCells.push_back(index); + newCells.push_back(currFaceIds[0]); + newCells.push_back(currFaceIds[1]); + } + } + toReturn->initialize(XdmfArrayType::Int64()); + toReturn->insert(0, &newCells[0], newCells.size()); + return toReturn; + } + else if(convertedTopology->getType() == XdmfTopologyType::Hexahedron()) { + for(long arrayOffset=0; arrayOffsetgetSize(); arrayOffset += convertedTopology->getType()->getNodesPerElement()) + { + std::vector faceNodes; + for (unsigned int i = 0; i < convertedTopology->getType()->getNodesPerElement(); ++i) { + faceNodes.push_back(convertedTopology->getValue(arrayOffset + i)); + } + + std::vector< std::vector > faceVectors; + // 0, 1, 5, 4 face + std::vector face1Vector; + face1Vector.push_back(faceNodes[0]); + face1Vector.push_back(faceNodes[1]); + face1Vector.push_back(faceNodes[5]); + face1Vector.push_back(faceNodes[4]); + faceVectors.push_back(face1Vector); + // 0, 3, 2, 1 face + std::vector face2Vector; + face2Vector.push_back(faceNodes[0]); + face2Vector.push_back(faceNodes[3]); + face2Vector.push_back(faceNodes[2]); + face2Vector.push_back(faceNodes[1]); + faceVectors.push_back(face2Vector); + // 0, 4, 7, 3 face + std::vector face3Vector; + face3Vector.push_back(faceNodes[0]); + face3Vector.push_back(faceNodes[4]); + face3Vector.push_back(faceNodes[7]); + face3Vector.push_back(faceNodes[3]); + faceVectors.push_back(face3Vector); + // 1, 2, 6, 5 face + std::vector face4Vector; + face4Vector.push_back(faceNodes[1]); + face4Vector.push_back(faceNodes[2]); + face4Vector.push_back(faceNodes[6]); + face4Vector.push_back(faceNodes[5]); + faceVectors.push_back(face4Vector); + // 2, 3, 7, 6 face + std::vector face5Vector; + face5Vector.push_back(faceNodes[2]); + face5Vector.push_back(faceNodes[3]); + face5Vector.push_back(faceNodes[7]); + face5Vector.push_back(faceNodes[6]); + faceVectors.push_back(face5Vector); + // 4, 5, 6, 7 face + std::vector face6Vector; + face6Vector.push_back(faceNodes[4]); + face6Vector.push_back(faceNodes[5]); + face6Vector.push_back(faceNodes[6]); + face6Vector.push_back(faceNodes[7]); + faceVectors.push_back(face6Vector); + + for (unsigned int i = 0; i < faceVectors.size(); ++i) { + insertInHash(faceVectors[i], hash, 4); + } + } + + // create new topology + shared_ptr toReturn = XdmfTopology::New(); + toReturn->setType(XdmfTopologyType::Quadrilateral()); + std::vector newCells; + int index = 0; + for(std::vector > >::const_iterator hashIter = hash.begin(); + hashIter != hash.end(); + ++hashIter, ++index) + { + const std::vector > & currHash = *hashIter; + for(std::vector >::const_iterator currHashIter = currHash.begin(); + currHashIter != currHash.end(); + ++currHashIter) + { + const std::vector & currFaceIds = *currHashIter; + newCells.push_back(index); + newCells.push_back(currFaceIds[0]); + newCells.push_back(currFaceIds[1]); + newCells.push_back(currFaceIds[2]); + } + } + toReturn->initialize(XdmfArrayType::Int64()); + toReturn->insert(0, &newCells[0], newCells.size()); + return toReturn; + } + else if(convertedTopology->getType() == XdmfTopologyType::Tetrahedron_10()) { + for(long arrayOffset=0; arrayOffsetgetSize(); arrayOffset += convertedTopology->getType()->getNodesPerElement()) + { + std::vector faceNodes; + for (unsigned int i = 0; i < convertedTopology->getType()->getNodesPerElement(); ++i) { + faceNodes.push_back(convertedTopology->getValue(arrayOffset + i)); + } + + std::vector< std::vector > faceVectors; + // 0, 1, 3, 4, 8, 7 face + std::vector face1Vector; + face1Vector.push_back(faceNodes[0]); + face1Vector.push_back(faceNodes[1]); + face1Vector.push_back(faceNodes[3]); + face1Vector.push_back(faceNodes[4]); + face1Vector.push_back(faceNodes[8]); + face1Vector.push_back(faceNodes[7]); + faceVectors.push_back(face1Vector); + // 0, 2, 1, 6, 5, 4 face + std::vector face2Vector; + face2Vector.push_back(faceNodes[0]); + face2Vector.push_back(faceNodes[2]); + face2Vector.push_back(faceNodes[1]); + face2Vector.push_back(faceNodes[6]); + face2Vector.push_back(faceNodes[5]); + face2Vector.push_back(faceNodes[4]); + faceVectors.push_back(face2Vector); + // 0, 3, 2, 7, 9, 6 face + std::vector face3Vector; + face3Vector.push_back(faceNodes[0]); + face3Vector.push_back(faceNodes[3]); + face3Vector.push_back(faceNodes[2]); + face3Vector.push_back(faceNodes[7]); + face3Vector.push_back(faceNodes[9]); + face3Vector.push_back(faceNodes[6]); + faceVectors.push_back(face3Vector); + // 1, 2, 3, 5, 9, 8 face + std::vector face4Vector; + face4Vector.push_back(faceNodes[1]); + face4Vector.push_back(faceNodes[2]); + face4Vector.push_back(faceNodes[3]); + face4Vector.push_back(faceNodes[5]); + face4Vector.push_back(faceNodes[9]); + face4Vector.push_back(faceNodes[8]); + faceVectors.push_back(face4Vector); + + for (unsigned int i = 0; i < faceVectors.size(); ++i) { + insertInHash(faceVectors[i], hash, 3); + } + } + + // create new topology + shared_ptr toReturn = XdmfTopology::New(); + toReturn->setType(XdmfTopologyType::Triangle_6()); + std::vector newCells; + int index = 0; + for(std::vector > >::const_iterator hashIter = hash.begin(); + hashIter != hash.end(); + ++hashIter, ++index) + { + const std::vector > & currHash = *hashIter; + for(std::vector >::const_iterator currHashIter = currHash.begin(); + currHashIter != currHash.end(); + ++currHashIter) + { + const std::vector & currFaceIds = *currHashIter; + newCells.push_back(index); + newCells.push_back(currFaceIds[0]); + newCells.push_back(currFaceIds[1]); + newCells.push_back(currFaceIds[2]); + newCells.push_back(currFaceIds[3]); + newCells.push_back(currFaceIds[4]); + } + } + toReturn->initialize(XdmfArrayType::Int64()); + toReturn->insert(0, &newCells[0], newCells.size()); + return toReturn; + } + else if(convertedTopology->getType() == XdmfTopologyType::Hexahedron_20()) { + for(long arrayOffset=0; arrayOffsetgetSize(); arrayOffset += convertedTopology->getType()->getNodesPerElement()) + { + std::vector faceNodes; + for (unsigned int i = 0; i < convertedTopology->getType()->getNodesPerElement(); ++i) { + faceNodes.push_back(convertedTopology->getValue(arrayOffset + i)); + } + + std::vector< std::vector > faceVectors; + // 0, 1, 5, 4, 8, 17, 12, 16 face + std::vector face1Vector; + face1Vector.push_back(faceNodes[0]); + face1Vector.push_back(faceNodes[1]); + face1Vector.push_back(faceNodes[5]); + face1Vector.push_back(faceNodes[4]); + face1Vector.push_back(faceNodes[8]); + face1Vector.push_back(faceNodes[17]); + face1Vector.push_back(faceNodes[12]); + face1Vector.push_back(faceNodes[16]); + faceVectors.push_back(face1Vector); + // 0, 3, 2, 1, 11, 10, 9, 8 face + std::vector face2Vector; + face2Vector.push_back(faceNodes[0]); + face2Vector.push_back(faceNodes[3]); + face2Vector.push_back(faceNodes[2]); + face2Vector.push_back(faceNodes[1]); + face2Vector.push_back(faceNodes[11]); + face2Vector.push_back(faceNodes[10]); + face2Vector.push_back(faceNodes[9]); + face2Vector.push_back(faceNodes[8]); + faceVectors.push_back(face2Vector); + // 0, 4, 7, 3, 16, 15, 19, 11 face + std::vector face3Vector; + face3Vector.push_back(faceNodes[0]); + face3Vector.push_back(faceNodes[4]); + face3Vector.push_back(faceNodes[7]); + face3Vector.push_back(faceNodes[3]); + face3Vector.push_back(faceNodes[16]); + face3Vector.push_back(faceNodes[15]); + face3Vector.push_back(faceNodes[19]); + face3Vector.push_back(faceNodes[11]); + faceVectors.push_back(face3Vector); + // 1, 2, 6, 5, 9, 18, 13, 17 face + std::vector face4Vector; + face4Vector.push_back(faceNodes[1]); + face4Vector.push_back(faceNodes[2]); + face4Vector.push_back(faceNodes[6]); + face4Vector.push_back(faceNodes[5]); + face4Vector.push_back(faceNodes[9]); + face4Vector.push_back(faceNodes[18]); + face4Vector.push_back(faceNodes[13]); + face4Vector.push_back(faceNodes[17]); + faceVectors.push_back(face4Vector); + // 2, 3, 7, 6, 10, 19, 14, 18 face + std::vector face5Vector; + face5Vector.push_back(faceNodes[2]); + face5Vector.push_back(faceNodes[3]); + face5Vector.push_back(faceNodes[7]); + face5Vector.push_back(faceNodes[6]); + face5Vector.push_back(faceNodes[10]); + face5Vector.push_back(faceNodes[19]); + face5Vector.push_back(faceNodes[14]); + face5Vector.push_back(faceNodes[18]); + faceVectors.push_back(face5Vector); + // 4, 5, 6, 7, 12, 13, 14, 15 face + std::vector face6Vector; + face6Vector.push_back(faceNodes[4]); + face6Vector.push_back(faceNodes[5]); + face6Vector.push_back(faceNodes[6]); + face6Vector.push_back(faceNodes[7]); + face6Vector.push_back(faceNodes[12]); + face6Vector.push_back(faceNodes[13]); + face6Vector.push_back(faceNodes[14]); + face6Vector.push_back(faceNodes[15]); + faceVectors.push_back(face6Vector); + + for (unsigned int i = 0; i < faceVectors.size(); ++i) { + insertInHash(faceVectors[i], hash, 4); + } + } + + // create new topology + shared_ptr toReturn = XdmfTopology::New(); + toReturn->setType(XdmfTopologyType::Quadrilateral_8()); + std::vector newCells; + int index = 0; + for(std::vector > >::const_iterator hashIter = hash.begin(); + hashIter != hash.end(); + ++hashIter, ++index) + { + const std::vector > & currHash = *hashIter; + for(std::vector >::const_iterator currHashIter = currHash.begin(); + currHashIter != currHash.end(); + ++currHashIter) + { + const std::vector & currFaceIds = *currHashIter; + newCells.push_back(index); + newCells.push_back(currFaceIds[0]); + newCells.push_back(currFaceIds[1]); + newCells.push_back(currFaceIds[2]); + newCells.push_back(currFaceIds[3]); + newCells.push_back(currFaceIds[4]); + newCells.push_back(currFaceIds[5]); + newCells.push_back(currFaceIds[6]); + } + } + toReturn->initialize(XdmfArrayType::Int64()); + toReturn->insert(0, &newCells[0], newCells.size()); + return toReturn; + } + + XdmfError::message(XdmfError::FATAL, "Unsupported TopologyType when computing external surface"); + return shared_ptr(); +} + +void +XdmfTopologyConverter::insertInHash(std::vector nodes, + std::vector > > & hash, + unsigned int numCornerNodes) +{ + unsigned int minIndex = 0; + for (unsigned int i = 0; i < numCornerNodes; ++i) { + if (nodes[i] < nodes[minIndex]) { + minIndex = i; + } + } + if (minIndex !=0) { + // If the min value is not the first value, rotate as appropriate + std::vector sortedVector (nodes.begin()+minIndex, + nodes.begin()+numCornerNodes); + sortedVector.insert(sortedVector.end(), + nodes.begin(), + nodes.begin()+minIndex); + if (nodes.size() > numCornerNodes) { + sortedVector.insert(sortedVector.end(), + nodes.begin()+numCornerNodes+minIndex, + nodes.begin()+numCornerNodes+numCornerNodes); + sortedVector.insert(sortedVector.end(), + nodes.begin()+numCornerNodes, + nodes.begin()+numCornerNodes+minIndex); + } + nodes = sortedVector; + } + + // The nodes are now sorted so that the smallest corner is first + // Look for existing cell in the hash; + std::vector > & currHash = hash[nodes[0]]; + for(std::vector >::iterator iter = + currHash.begin(); iter != currHash.end(); + ++iter) { + std::vector & currFace = *iter; + // size - 1 because the first value is used elsewhere + if(currFace.size() == nodes.size()-1) { + if ((nodes[1] == currFace[0] && + nodes[numCornerNodes-1] == currFace[numCornerNodes-2]) || + (nodes[1] == currFace[numCornerNodes-2] && + nodes[numCornerNodes-1] == currFace[0])) { + currHash.erase(iter); + return; + } + } + } + + std::vector newFace; + for (unsigned int i = 1; i < nodes.size(); ++i) { + newFace.push_back(nodes[i]); + } + currHash.push_back(newFace); +} diff --git a/utils/XdmfTopologyConverter.hpp b/utils/XdmfTopologyConverter.hpp index efc8dc47..2749f144 100644 --- a/utils/XdmfTopologyConverter.hpp +++ b/utils/XdmfTopologyConverter.hpp @@ -111,12 +111,25 @@ public: const shared_ptr topologyType, const shared_ptr heavyDataWriter = shared_ptr()) const; + /** + * Gets all faces within the given topology. Removing duplicates. + * + * @param convertedTopology The topology to be deconstructed + * @return A topology containing the faces from the deconstructed topology + */ + shared_ptr + getExternalFaces(const shared_ptr convertedTopology); + protected: XdmfTopologyConverter(); private: + void insertInHash(std::vector nodes, + std::vector > > & hash, + unsigned int numCornerNodes); + XdmfTopologyConverter(const XdmfTopologyConverter &); // Not implemented. void operator=(const XdmfTopologyConverter &); // Not implemented. diff --git a/utils/XdmfUtils.i b/utils/XdmfUtils.i index 2df4ae48..687ffa7d 100644 --- a/utils/XdmfUtils.i +++ b/utils/XdmfUtils.i @@ -40,6 +40,7 @@ swig -v -c++ -python -o XdmfUtilsPython.cpp XdmfUtils.i #include #include #include + #include #include #include #include @@ -96,6 +97,7 @@ swig -v -c++ -python -o XdmfUtilsPython.cpp XdmfUtils.i #include #include #include + #include #include #include #include diff --git a/utils/tests/Cxx/CMakeLists.txt b/utils/tests/Cxx/CMakeLists.txt index e0a15bcb..5778c30b 100644 --- a/utils/tests/Cxx/CMakeLists.txt +++ b/utils/tests/Cxx/CMakeLists.txt @@ -18,7 +18,6 @@ include(AddTestsCxx) # Read UseCxxTest.cmake for more information # --------------------------------------- ADD_TEST_CXX(TestXdmfTopologyConverter) - if(XDMF_BUILD_EXODUS_IO) ADD_TEST_CXX(TestXdmfExodusIO) endif(XDMF_BUILD_EXODUS_IO) diff --git a/utils/tests/Cxx/TestXdmfTopologyConverter.cpp b/utils/tests/Cxx/TestXdmfTopologyConverter.cpp index 5f698bb7..4448e9f0 100644 --- a/utils/tests/Cxx/TestXdmfTopologyConverter.cpp +++ b/utils/tests/Cxx/TestXdmfTopologyConverter.cpp @@ -1,4 +1,5 @@ #include +#include #include "XdmfArray.hpp" #include "XdmfArrayType.hpp" #include "XdmfGeometry.hpp" @@ -67,5 +68,96 @@ int main(int, char **) assert(newHexGrid->getTopology()->getType() == XdmfTopologyType::Hexahedron()); assert(newHexGrid->getTopology()->getNumberElements() == 27); + + + shared_ptr faceTopology; + + /** + * Tetrahedron to Triangle + */ + shared_ptr tetTopology = XdmfTopology::New(); + tetTopology->setType(XdmfTopologyType::Tetrahedron()); + long tetValues[8] = {0, 1, 2, 3, 0, 1, 2, 4};// temporary + tetTopology->insert(0, tetValues, 8); + std::cout << "tetrahedrons prior to splitting into faces " << std::endl + << tetTopology->getValuesString() << std::endl; + faceTopology = converter->getExternalFaces(tetTopology); + std::cout << "after splitting into faces" << std::endl + << faceTopology->getValuesString() << std::endl; + assert(faceTopology->getValuesString().compare("0 1 3 " + "0 3 2 " + "0 1 4 " + "0 4 2 " + "1 2 3 " + "1 2 4") == 0); + + /** + * Tetrahedron_10 to Triangle_6 + */ + shared_ptr tet10Topology = XdmfTopology::New(); + tet10Topology->setType(XdmfTopologyType::Tetrahedron_10()); + long tet10Values[20] = {0, 1, 2, 3, 5, 6, 7, 8, 9, 10, + 0, 1, 2, 4, 9, 10, 11, 12, 13, 14};// temporary + tet10Topology->insert(0, tet10Values, 20); + std::cout << "tetrahedron_10s prior to splitting into faces " << std::endl + << tet10Topology->getValuesString() << std::endl; + faceTopology = converter->getExternalFaces(tet10Topology); + std::cout << "after splitting into faces" << std::endl + << faceTopology->getValuesString() << std::endl; + assert(faceTopology->getValuesString().compare("0 1 3 5 9 8 " + "0 3 2 8 10 7 " + "0 1 4 9 13 12 " + "0 4 2 12 14 11 " + "1 2 3 6 10 9 " + "1 2 4 10 14 13") == 0); + + /** + * Hexahedron to Quadrilateral + */ + shared_ptr hexTopology = XdmfTopology::New(); + hexTopology->setType(XdmfTopologyType::Hexahedron()); + long hexValues[16] = {0, 1, 2, 3, 4, 5, 6, 7, + 0, 1, 2, 3, 8, 9, 10, 11};// temporary + hexTopology->insert(0, hexValues, 16); + std::cout << "Hexahedrons prior to splitting into faces " << std::endl + << hexTopology->getValuesString() << std::endl; + faceTopology = converter->getExternalFaces(hexTopology); + std::cout << "after splitting into faces" << std::endl + << faceTopology->getValuesString() << std::endl; + assert(faceTopology->getValuesString().compare("0 1 5 4 " + "0 4 7 3 " + "0 1 9 8 " + "0 8 11 3 " + "1 2 6 5 " + "1 2 10 9 " + "2 3 7 6 " + "2 3 11 10 " + "4 5 6 7 " + "8 9 10 11") == 0); + + /** + * Hexahedron_20 to Quadrilateral_8 + */ + shared_ptr hex20Topology = XdmfTopology::New(); + hex20Topology->setType(XdmfTopologyType::Hexahedron_20()); + long hex20Values[40] = {0, 1, 2, 3, 4, 5, 6, 7, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, + 0, 1, 2, 3, 8, 9, 10, 11, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35};// temporary + hex20Topology->insert(0, hex20Values, 40); + std::cout << "Hexahedron_20s prior to splitting into faces " << std::endl + << hex20Topology->getValuesString() << std::endl; + faceTopology = converter->getExternalFaces(hex20Topology); + std::cout << "after splitting into faces" << std::endl + << faceTopology->getValuesString() << std::endl; + assert(faceTopology->getValuesString().compare("0 1 5 4 12 21 16 20 " + "0 4 7 3 20 19 23 15 " + "0 1 9 8 24 33 28 32 " + "0 8 11 3 32 31 35 27 " + "1 2 6 5 13 22 17 21 " + "1 2 10 9 25 34 29 33 " + "2 3 7 6 14 23 18 22 " + "2 3 11 10 26 35 30 34 " + "4 5 6 7 16 17 18 19 " + "8 9 10 11 28 29 30 31") == 0); + return 0; } -- GitLab