diff --git a/AMDiS/src/Debug.cc b/AMDiS/src/Debug.cc index dd6ebc7f77e54507f9e211c1e4b0dc6a6a2c3c74..5007cb06411440a6a13cce17ac937687eaeaa240 100644 --- a/AMDiS/src/Debug.cc +++ b/AMDiS/src/Debug.cc @@ -842,7 +842,7 @@ namespace AMDiS { std::cout << "(" << elCoords[i][0] << ", " << elCoords[i][1]<< ", " << elCoords[i][2] << ") "; std::cout << "another is: "; std::cout << "(" << coords[el->getIndex()][i][0] << ", " << coords[el->getIndex()][i][1] - << ". " << coords[el->getIndex()][i][2] << ")\n"; + << ", " << coords[el->getIndex()][i][2] << ")\n"; break; default: ERROR_EXIT("What is this?\n"); diff --git a/AMDiS/src/io/Arh2Reader.cc b/AMDiS/src/io/Arh2Reader.cc index 26ee51130a3692899472a78e53fed9b7c62d2b12..ff1980f37c82850ed7ec3e1da8a730180e96739a 100644 --- a/AMDiS/src/io/Arh2Reader.cc +++ b/AMDiS/src/io/Arh2Reader.cc @@ -145,7 +145,7 @@ namespace AMDiS { namespace io { uint32_t nValueVectors = 0; - detail::firstRead(file); + detail::firstRead(file, "sarh", MAJOR, MINOR); long pos = file.tellg(); file.seekg(pos + 16); file.read(reinterpret_cast<char*>(&nValueVectors), 4); @@ -176,7 +176,7 @@ namespace AMDiS { namespace io { ("Cannot open file %s\n", filename.c_str()); uint32_t headerLen = 0; - detail::firstRead(file); + detail::firstRead(file, "sarh", MAJOR, MINOR); file.read(reinterpret_cast<char*>(&headerLen), 4); file.close(); @@ -212,7 +212,7 @@ namespace AMDiS { namespace io { file.read(reinterpret_cast<char*>(&minor), 1); file.close(); - return (typeId == "arh2" && major == MAJOR && minor <= MINOR) ? true : false; + return (typeId == "sarh" && major == MAJOR && minor <= MINOR) ? true : false; } void readMeta(string filename, diff --git a/AMDiS/src/io/Arh2Reader.h b/AMDiS/src/io/Arh2Reader.h index a5c33cfddae91944c20f12c8e34416257c22a9e9..7e2c50e69d88f3f9eaafaf0a5a71382cac7b3659 100644 --- a/AMDiS/src/io/Arh2Reader.h +++ b/AMDiS/src/io/Arh2Reader.h @@ -23,8 +23,8 @@ namespace AMDiS { namespace io { **/ namespace Arh2Reader { - const uint8_t MAJOR = 2; - const uint8_t MINOR = 1; + const uint8_t MAJOR = 3; + const uint8_t MINOR = 0; /** * \brief Read MeshStructure, refine the mesh and read dof values to sysVec by order. diff --git a/AMDiS/src/io/Arh2Writer.h b/AMDiS/src/io/Arh2Writer.h index 1aca4c4403c6595fb4251a4c70adcf254e85f342..0608f124c3e05ccd2e28bd655ab51bff7ae48e27 100644 --- a/AMDiS/src/io/Arh2Writer.h +++ b/AMDiS/src/io/Arh2Writer.h @@ -14,9 +14,7 @@ namespace AMDiS { namespace io { * ARH-files. **/ namespace Arh2Writer - { - const uint8_t MAJOR = 2; - const uint8_t MINOR = 1; + { /** * \brief write the meshstructure and the dof values of DOFVectors in sysVec @@ -45,57 +43,69 @@ namespace AMDiS { namespace io { */ inline void writeFile(SystemVector *sysVec, std::string filename, - bool writeParallel = true) + bool writeParallel = true, + Cpsformat cps = NONE, + std::string dataformat = "SF64") { std::vector<DOFVector<double>*> vecs; for (int i = 0; i < sysVec->getSize(); i++) vecs.push_back(sysVec->getDOFVector(i)); - detail::write(filename, NULL, vecs, writeParallel); + detail::write(filename, NULL, vecs, writeParallel, cps, dataformat); } inline void writeFile(SystemVector &sysVec, std::string filename, - bool writeParallel = true) + bool writeParallel = true, + Cpsformat cps = NONE, + std::string dataformat = "SF64") { - writeFile(&sysVec, filename, writeParallel); + writeFile(&sysVec, filename, writeParallel, cps, dataformat); } /// write the meshstructure and the dof values of DOFVectors in vec0 /// the behavior is equal to writeFile(SystemVector* sysVec, string filename). inline void writeFile(DOFVector<double>* vec0, std::string filename, - bool writeParallel = true) + bool writeParallel = true, + Cpsformat cps = NONE, + std::string dataformat = "SF64") { std::vector<DOFVector<double>*> vecs; vecs.push_back(vec0); - detail::write(filename, NULL, vecs, writeParallel); + detail::write(filename, NULL, vecs, writeParallel, cps, dataformat); } /// write the meshstructure and the dof values of DOFVectors in vec0 /// the behavior is equal to writeFile(SystemVector* sysVec, string filename). inline void writeFile(DOFVector<double>& vec0, std::string filename, - bool writeParallel = true) + bool writeParallel = true, + Cpsformat cps = NONE, + std::string dataformat = "SF64") { - writeFile(&vec0, filename, writeParallel); + writeFile(&vec0, filename, writeParallel, cps, dataformat); } /// write the meshstructure and the dof values of DOFVectors in vecs /// the behavior is equal to writeFile(SystemVector* sysVec, string filename). inline void writeFile(std::vector<DOFVector<double>*> vecs, std::string filename, - bool writeParallel = true) + bool writeParallel = true, + Cpsformat cps = NONE, + std::string dataformat = "SF64") { - detail::write(filename, NULL, vecs, writeParallel); + detail::write(filename, NULL, vecs, writeParallel, cps, dataformat); } /// write the meshstructure of the mesh to arh file. inline void writeFile(Mesh *mesh, std::string filename, - bool writeParallel = true) + bool writeParallel = true, + Cpsformat cps = NONE, + std::string dataformat = "SF64") { std::vector<DOFVector<double>*> vecs; - detail::write(filename, mesh, vecs, writeParallel); + detail::write(filename, mesh, vecs, writeParallel, cps, dataformat); } #ifdef HAVE_PARALLEL_DOMAIN_AMDIS diff --git a/AMDiS/src/io/detail/Arh2Reader.cc b/AMDiS/src/io/detail/Arh2Reader.cc index 7e12a074db5f68ce439fbdb9c88c8e2084320e2b..1950ad146f5f56bcb227aeb20a5efb888282f01e 100644 --- a/AMDiS/src/io/detail/Arh2Reader.cc +++ b/AMDiS/src/io/detail/Arh2Reader.cc @@ -6,12 +6,14 @@ #include "SystemVector.h" #include "Debug.h" #include "../Arh2Reader.h" +#include "Arh2Writer.h" #include <boost/filesystem.hpp> #include <boost/iostreams/filtering_streambuf.hpp> #include <boost/iostreams/copy.hpp> #ifdef HAVE_COMPRESSION #include <boost/iostreams/filter/zlib.hpp> +#include <boost/iostreams/filter/bzip2.hpp> #endif namespace AMDiS { namespace io { @@ -23,27 +25,27 @@ namespace AMDiS { namespace io { namespace detail { - uint8_t firstRead(ifstream& file) + void firstRead(ifstream& file, string id, uint8_t major, uint8_t minor) { FUNCNAME("Arh2Reader::detail::firstRead"); + uint8_t major_ = 0; + uint8_t minor_ = 0; string typeId(4, ' '); - uint8_t major = 0, minor = 0; file.read(const_cast<char*>(typeId.data()), 4); - TEST_EXIT(typeId == "arh2") + TEST_EXIT(typeId == id) ("Cannot read Arh2 format: this file is not \"arh2\" format.\n"); - file.read(reinterpret_cast<char*>(&major), 1); - TEST_EXIT(major == AMDiS::io::Arh2Reader::MAJOR) + file.read(reinterpret_cast<char*>(&major_), 1); + TEST_EXIT(major == major_) ("Cannot read Arh2 format: Arh2Reader major version is %i, the file major version is %i. \n", - AMDiS::io::Arh2Reader::MAJOR, major); + major, major_); - file.read(reinterpret_cast<char*>(&minor), 1); - TEST_EXIT(minor <= AMDiS::io::Arh2Reader::MINOR) + file.read(reinterpret_cast<char*>(&minor_), 1); + TEST_EXIT(minor <= minor_) ("Cannot read Arh2 format: Arh2Reader minor version is %i is smaller than the file minor version %i.\n", - AMDiS::io::Arh2Reader::MINOR, minor); - return minor; + minor, minor_); } void setDofValues(int macroElIndex, Mesh *mesh, @@ -192,6 +194,8 @@ namespace AMDiS { namespace io { bool byName) { FUNCNAME("Arh2Reader::detail::read()"); + + using namespace ::AMDiS::io::Arh2Writer; // Get set of all macro elements in mesh. std::set<int> macroInMesh; @@ -217,20 +221,17 @@ namespace AMDiS { namespace io { file.open(filename.c_str(), ios::in | ios::binary); TEST_EXIT(file.is_open()) ("Cannot open file %s\n", filename.c_str()); - - file.seekg (0, file.end); - int fileSize = file.tellg(); - file.seekg (0, file.beg); - string cps = "null"; + Cpsformat cps = NONE; uint32_t headerLen = 0; uint32_t nMacroElements = 0; uint32_t nValueVectors = 0; uint32_t nFeSpaces = 0; uint32_t dim = 0, dow = 0; + int cpsflag = 0; // Read fixed header - uint8_t minor = firstRead(file); + firstRead(file, "sarh", MAJOR, MINOR); file.read(reinterpret_cast<char*>(&headerLen), 4); file.read(reinterpret_cast<char*>(&dow), 4); @@ -238,15 +239,16 @@ namespace AMDiS { namespace io { file.read(reinterpret_cast<char*>(&nFeSpaces), 4); file.read(reinterpret_cast<char*>(&nValueVectors), 4); file.read(reinterpret_cast<char*>(&nMacroElements), 4); - - if(minor >= 1) - file.read(const_cast<char*>(cps.data()), 4); + file.read(reinterpret_cast<char*>(&cpsflag), 4); + cps = static_cast<Cpsformat>(cpsflag); #ifdef HAVE_COMPRESSION - TEST_EXIT(cps == "null" || cps == "zlib") - ("Cannot read Arh2 file. Currently only support zlib compression.\n"); + TEST_EXIT(cps == ZLIB || + cps == BZIP2 || + cps == NONE) + ("Cannot read Arh2 file. Currently only support zlib and bzip2 compression.\n"); #else - TEST_EXIT(cps == "null") + TEST_EXIT(cps == NONE) ("HAVE_COMPRESSION OFF. Cannot read compressed Arh2 file.\n"); #endif @@ -258,25 +260,39 @@ namespace AMDiS { namespace io { ("File %s has %d vector(s), which is less than the number of DOFVectors %i in vecs!\n", filename.c_str(), nValueVectors, vecs.size()); - vector<int> vecsNameLen(0); - vector<string> vecsName(0); - vector<int> vecsFeSpaceNum(0); + vector<int> vecsNameLen; + vector<string> vecsName; + + vector<int> filesNameLen; + vector<string> filesName; + + vector<int> vecsFeSpaceNum; + vector<string> dataformat; vector<int> macroElIndex(nMacroElements); - vector<int> macroElSize(nMacroElements); + vector<pair<int,int> > macroElSize(nMacroElements); // pos, uncompressed size + int fileSize = 0; - vector<vector<int> > feSpaceDOFs(0); + vector<vector<int> > feSpaceDOFs; + vector<string> AFEDfileName(nFeSpaces); vector<int> perDOFs(4, 0); vector<vector<int> > sortedFeSpaces(nFeSpaces); // Read macro table - for(unsigned int i = 0; i < nMacroElements; i++) + for(size_t i = 0; i < nMacroElements; i++) { file.read(reinterpret_cast<char*>(¯oElIndex[i]), 4); - file.read(reinterpret_cast<char*>(¯oElSize[i]), 4); + file.read(reinterpret_cast<char*>(¯oElSize[i].first), 4); + file.read(reinterpret_cast<char*>(¯oElSize[i].second), 4); } + file.seekg(4, ios_base::cur); + file.read(reinterpret_cast<char*>(&fileSize), 4); + file.seekg(4, ios_base::cur); // Read feSpace table - for(unsigned int i = 0; i < nFeSpaces; i++) + for(size_t i = 0; i < nFeSpaces; i++) { + uint32_t tmpInt = 0; + file.read(reinterpret_cast<char*>(&tmpInt), 4); + file.read(const_cast<char*>(AFEDfileName[i].data()), tmpInt); for(int j = 0; j < 4; j++) { file.read(reinterpret_cast<char*>(&perDOFs[j]), 4); @@ -284,7 +300,7 @@ namespace AMDiS { namespace io { feSpaceDOFs.push_back(perDOFs); } // Read value table - for(unsigned int i = 0; i < nValueVectors; i++) + for(size_t i = 0; i < nValueVectors; i++) { string tmpString(""); uint32_t tmpInt = 0; @@ -296,6 +312,9 @@ namespace AMDiS { namespace io { file.read(reinterpret_cast<char*>(&tmpInt), 4); sortedFeSpaces[tmpInt].push_back(i); vecsFeSpaceNum.push_back(tmpInt); + tmpString.resize(4, ' '); + file.read(const_cast<char*>(tmpString.data()), 4); + dataformat.push_back(tmpString); } // Adjust and check vecs if(byName) @@ -311,27 +330,28 @@ namespace AMDiS { namespace io { if(!tmpVecs[k]) break; - unsigned int i; + size_t i; TEST_EXIT(tmpVecs[k]->getFeSpace()->getAdmin()) ("Vecs number %i has no DOFAdmin. Should not happen.\n", k); DimVec<int>* nDOF = tmpVecs[k]->getFeSpace()->getBasisFcts()->getNumberOfDofs(); - for(i = 0; i < nValueVectors; i++) - { - if(tmpVecs[k]->getName() != vecsName[i]) - { + for(i = 0; i < nValueVectors; i++) { + + if(tmpVecs[k]->getName() != vecsName[i]) continue; - } - int j; - for(j = 0; j < nDOF->getSize(); j++) - { - if((*nDOF)[j] != feSpaceDOFs[vecsFeSpaceNum[i]][j]) - { - break; + + bool matchdof = true; + if ((*nDOF)[0] != feSpaceDOFs[vecsFeSpaceNum[i]][3]) + matchdof = false; + else { + for(size_t j = 1; j < nDOF->getSize(); j++) { + if((*nDOF)[j] != feSpaceDOFs[vecsFeSpaceNum[i]][j-1]){ + matchdof = false; + break; + } } } - if(j == nDOF->getSize()) - { + if(matchdof) { vecs[i] = tmpVecs[k]; break; } @@ -343,43 +363,51 @@ namespace AMDiS { namespace io { } else { - for(size_t i = 0; i < vecs.size(); i++) - { - if(vecs[i]) - { + for(size_t i = 0; i < vecs.size(); i++) { + if(vecs[i]) { + TEST_EXIT(vecs[i]->getFeSpace()->getAdmin()) ("Vecs number %i has no DOFAdmin. Should not happen.\n", i); DimVec<int>* nDOF = vecs[i]->getFeSpace()->getBasisFcts()->getNumberOfDofs(); - for(int j = 0; j < nDOF->getSize(); j++) - { - TEST_EXIT((*nDOF)[j] == feSpaceDOFs[vecsFeSpaceNum[i]][j]) + + TEST_EXIT((*nDOF)[0] == feSpaceDOFs[vecsFeSpaceNum[i]][3]) + ("The fespace of vec number %i is not equal to the correspond fespace.\n", i+1); + for(size_t j = 1; j < nDOF->getSize(); j++) + TEST_EXIT((*nDOF)[j] == feSpaceDOFs[vecsFeSpaceNum[i]][j-1]) ("The fespace of vec number %i is not equal to the correspond fespace.\n", i+1); - } } } } // Read data: meshstructure and dof values - for (unsigned int i = 0; i < nMacroElements; i++) { + for (size_t i = 0; i < nMacroElements; i++) { stringstream dataStream(ios::out | ios::in | ios::binary); - int size = 0; - if(minor >= 1) - size = macroElSize[i]; - else - size = (i != nMacroElements - 1) ? macroElSize[i + 1] - macroElSize[i] : fileSize - macroElSize[i]; + int size = (i == nMacroElements - 1) ? fileSize - macroElSize[i].first + : (macroElSize[i+1].first - macroElSize[i].first); + char* buffer = new char[size]; file.read(buffer, size); dataStream.write(buffer, size); delete[] buffer; #ifdef HAVE_COMPRESSION - if(cps == "zlib") { - stringstream tmp(ios::out | ios::in); - boost::iostreams::filtering_streambuf<boost::iostreams::input> in; - in.push(boost::iostreams::zlib_decompressor()); - in.push(dataStream); - boost::iostreams::copy(in, tmp); - dataStream.str(tmp.str()); + stringstream tmp(ios::out | ios::in); + boost::iostreams::filtering_streambuf<boost::iostreams::input> in; + switch(cps) + { + case ZLIB: + in.push(boost::iostreams::zlib_decompressor()); + break; + case BZIP2: + in.push(boost::iostreams::bzip2_decompressor()); + break; + case NONE: + break; + default: + MSG("NOT correct compression flag.\n"); } + in.push(dataStream); + boost::iostreams::copy(in, tmp); + dataStream.str(tmp.str()); #endif uint32_t nStructureCodes = 0; uint32_t codeSize = 0; @@ -406,7 +434,7 @@ namespace AMDiS { namespace io { for(size_t k = 0; k < sortedFeSpaces[j].size(); k++) { values[valuePos + k].resize(nValuesPerVector); - dataStream.read(reinterpret_cast<char*>(&(values[valuePos + k][0])), 8 * nValuesPerVector); + readValues(dataStream, dataformat[valuePos + k], values[valuePos + k]); } valuePos += sortedFeSpaces[j].size(); } @@ -419,9 +447,64 @@ namespace AMDiS { namespace io { } } } - file.close(); delete refManager; } + + void readValues(stringstream& file, + string dataformat, + vector<double>& values) + { + using namespace ::AMDiS::io::Arh2Writer; + + std::map<string,Valformat>::const_iterator it = dataformatMap.find(dataformat); + TEST_EXIT(it != dataformatMap.end())("Wrong data format.\n"); + + switch(it->second) { + case SI08: + readValues<int8_t>(file, values); + break; + case SI16: + readValues<int16_t>(file, values); + break; + case SI32: + readValues<int32_t>(file, values); + break; + case SI64: + readValues<int64_t>(file, values); + break; + case UI08: + readValues<uint8_t>(file, values); + break; + case UI16: + readValues<uint16_t>(file, values); + break; + case UI32: + readValues<uint32_t>(file, values); + break; + case UI64: + readValues<uint64_t>(file, values); + break; + case SF32: + readValues<float>(file, values); + break; + case SF64: + readValues<double>(file, values); + break; + default: + ERROR_EXIT("Wrong data format.\n"); + } + } + + template<typename T> + void readValues(stringstream& file, vector<double>& values) + { + int size = values.size(); + T data[size]; + file.read(reinterpret_cast<char*>(&data[0]), sizeof(T) * size); + + for (size_t i = 0; i < size; i++) + values[i] = static_cast<double>(data[i]); + } void readFile(string filename, Mesh *mesh, vector<DOFVector<double>*> vecs, @@ -475,46 +558,55 @@ namespace AMDiS { namespace io { ERROR_EXIT("Reading parallel ARH files in sequential computations requires to specify the number of nodes on which the ARH file was created!\n"); #endif } else { + string parhfn = name + ".parh", filenameType = ""; + int nProcs_ = 0, nMacros_ = 0, nMacros = 0; + vector<int> partition; - // check if there are no more or less files as nProcs - int n = 0; - for (; n < nProcs + 1; n++) { - string fn = name + "-p" + boost::lexical_cast<string>(n) + "-.arh"; - if(!boost::filesystem::exists(fn)) break; + bool parh = boost::filesystem::exists(parhfn); + if (parh) + readParallelFile(parhfn, filenameType, partition, nProcs_, nMacros_); + else { + for (; nProcs_ < nProcs + 1; nProcs_++) { + string fn = name + "-p" + boost::lexical_cast<string>(nProcs_) + "-.arh"; + if(!boost::filesystem::exists(fn)) break; + } } - TEST_EXIT(n == nProcs) - ("Number of arh files doesn't match number of processors \n"); + TEST_EXIT(nProcs_ == nProcs) + ("Number of arh files doesn't match number of processors: %d vs %d\n", nProcs_, nProcs); - // - // Some test should be checked. This is because of the variation of the - // number of macro elements per processor: - // - // There should be at least 10 macro Elements per processor, therefore: - // nMacroElements * 2^gr >= nProcs * 10 - // => gr = log_2(nProcs * 10 / nMacroElements) - - int allMacros = mesh->getNumberOfMacros(); - int allMacrosFromProcFiles = 0; - + if (!parh) { +#ifdef HAVE_PARALLEL_DOMAIN_AMDIS + if(MPI::COMM_WORLD.Get_rank() == 0) +#endif + for(int i = 0; i < nProcs; i++) + nMacros_ += readNumOfMacrosFromSgArh(filename, i); + } + + nMacros = mesh->getNumberOfMacros(); #ifdef HAVE_PARALLEL_DOMAIN_AMDIS - int sendValue = static_cast<int>(mesh->getNumberOfMacros()); - MPI::COMM_WORLD.Allreduce(&sendValue, &allMacros, 1, MPI_INT, MPI_SUM); - - if(MPI::COMM_WORLD.Get_rank() == 0) { + Parallel::mpi::globalAdd(nMacros); + if(MPI::COMM_WORLD.Get_rank() == 0) #endif - for(int i = 0; i < nProcs; i++) { - allMacrosFromProcFiles += readNumOfMacrosFromSgArh(filename, i); + TEST_EXIT(nMacros == nMacros_) + ("Number of macro elements in parallel ARH files doesn't match to the current runtime. %d vs %d\n", + nMacros, nMacros_); + + if (!parh) { + for (int i = 0; i < nProcs; i++) { + string procFilename = name + "-p" + lexical_cast<string>(i) + "-.arh"; + read(procFilename, mesh, vecs, byName); } + } else { + std::set<int> needFiles; + deque<MacroElement*>::iterator it = mesh->firstMacroElement(); + for (;it != mesh->endOfMacroElements(); it++) + needFiles.insert(partition[(*it)->getIndex()]); - TEST_EXIT(allMacros == allMacrosFromProcFiles) - ("Number of macro elements in parallel ARH files doesn't match to the current runtime.\n"); -#ifdef HAVE_PARALLEL_DOMAIN_AMDIS - } -#endif - for (int i = 0; i < nProcs; i++) { - string procFilename = name + "-p" + lexical_cast<string>(i) + "-.arh"; - read(procFilename, mesh, vecs, byName); - MSG("ARH file read from: %s\n", procFilename.c_str()); + std::set<int>::iterator it2 = needFiles.begin(); + for (;it2 != needFiles.end(); it2++) { + string procFilename = name + "-p" + lexical_cast<string>(*it2) + "-.arh"; + read(procFilename, mesh, vecs, byName); + } } } } else { @@ -526,23 +618,22 @@ namespace AMDiS { namespace io { void readMetaFromSgArh(std::string filename, int nProc, std::vector< std::set<std::pair<int, int> > >& data) { + using namespace ::AMDiS::io::Arh2Writer; + ifstream file; file.open(filename.c_str(), ios::in | ios::binary); TEST_EXIT(file.is_open()) ("Cannot open file %s\n", filename.c_str()); - - file.seekg (0, file.end); - int fileSize = file.tellg(); - file.seekg (0, file.beg); uint32_t dow = 0, dim = 0; uint32_t headerLen = 0; uint32_t nMacroElements = 0; uint32_t nValueVectors = 0; uint32_t nFeSpaces = 0; - string cps = "null"; + int cpsflag = 0, fileSize = 0; + Cpsformat cps = NONE; - uint8_t minor = firstRead(file); + firstRead(file, "sarh", MAJOR, MINOR); file.read(reinterpret_cast<char*>(&headerLen), 4); file.read(reinterpret_cast<char*>(&dow), 4); @@ -550,30 +641,42 @@ namespace AMDiS { namespace io { file.read(reinterpret_cast<char*>(&nFeSpaces), 4); file.read(reinterpret_cast<char*>(&nValueVectors), 4); file.read(reinterpret_cast<char*>(&nMacroElements), 4); - - if(minor > 0) - file.read(const_cast<char*>(cps.data()), 4); + file.read(reinterpret_cast<char*>(&cpsflag), 4); + cps = static_cast<Cpsformat>(cpsflag); #ifdef HAVE_COMPRESSION - TEST_EXIT(cps == "null" || cps == "zlib") - ("Cannot read Arh2 file. Currently only support zlib compression.\n"); + TEST_EXIT(cps == ZLIB || + cps == BZIP2 || + cps == NONE) + ("Cannot read Arh2 file. Currently only support zlib and bzip2 compression.\n"); #else - TEST_EXIT(cps == "null") + TEST_EXIT(cps == NONE) ("HAVE_COMPRESSION OFF. Cannot read compressed Arh2 file.\n"); #endif vector<int> macroElIndex(nMacroElements); - vector<int> macroElSize(nMacroElements); + vector<pair<int, int> > macroElSize(nMacroElements); vector<vector<int> > sortedFeSpaces(nFeSpaces); + vector<string> dataformat; // Read macro table for(uint32_t i = 0; i < nMacroElements; i++) { file.read(reinterpret_cast<char*>(¯oElIndex[i]), 4); - file.read(reinterpret_cast<char*>(¯oElSize[i]), 4); + file.read(reinterpret_cast<char*>(¯oElSize[i].first), 4); + file.read(reinterpret_cast<char*>(¯oElSize[i].second), 4); } + file.seekg(4, ios_base::cur); + file.read(reinterpret_cast<char*>(&fileSize), 4); + file.seekg(4, ios_base::cur); // Read feSpace table - file.seekg(nFeSpaces * 4 * 4, ios_base::cur); + for(size_t i = 0; i < nFeSpaces; i++) + { + uint32_t tmpInt = 0; + file.read(reinterpret_cast<char*>(&tmpInt), 4); + file.seekg(tmpInt, ios_base::cur); + file.seekg(16, ios_base::cur); + } // Read value table for(uint32_t i = 0; i < nValueVectors; i++) { @@ -584,16 +687,15 @@ namespace AMDiS { namespace io { file.read(const_cast<char*>(tmpString.data()), tmpInt); // file.read(reinterpret_cast<char*>(&tmpInt), 4); sortedFeSpaces[tmpInt].push_back(i); + tmpString.resize(4, ' '); + file.read(const_cast<char*>(tmpString.data()), 4); + dataformat.push_back(tmpString); } for (uint32_t i = 0; i < nMacroElements; i++) { stringstream dataStream(ios::out | ios::in | ios::binary); - int size = 0; - - if(minor > 0) - size = macroElSize[i]; - else - size = (i != nMacroElements - 1) ? macroElSize[i + 1] - macroElSize[i] : fileSize - macroElSize[i]; + int size = (i == nMacroElements - 1) ? fileSize - macroElSize[i].first + : (macroElSize[i+1].first - macroElSize[i].first); char* buffer = new char[size]; file.read(buffer, size); @@ -601,14 +703,24 @@ namespace AMDiS { namespace io { delete[] buffer; #ifdef HAVE_COMPRESSION - if(cps == "zlib") { - stringstream tmp(ios::out | ios::in); - boost::iostreams::filtering_streambuf<boost::iostreams::input> in; - in.push(boost::iostreams::zlib_decompressor()); - in.push(dataStream); - boost::iostreams::copy(in, tmp); - dataStream.str(tmp.str()); + stringstream tmp(ios::out | ios::in); + boost::iostreams::filtering_streambuf<boost::iostreams::input> in; + switch(cps) + { + case ZLIB: + in.push(boost::iostreams::zlib_decompressor()); + break; + case BZIP2: + in.push(boost::iostreams::bzip2_decompressor()); + break; + case NONE: + break; + default: + MSG("NOT correct compression flag.\n"); } + in.push(dataStream); + boost::iostreams::copy(in, tmp); + dataStream.str(tmp.str()); #endif uint32_t nStructureCodes = 0; uint32_t codeSize = 0; @@ -623,10 +735,33 @@ namespace AMDiS { namespace io { if (nValueVectors > 0) { + int valuePos = 0; for(uint32_t j = 0; j < nFeSpaces; j++) { uint32_t nValuesPerVector = 0; dataStream.read(reinterpret_cast<char*>(&nValuesPerVector), 4); - dataStream.seekg(sortedFeSpaces[j].size() * 8 * nValuesPerVector, ios_base::cur); + + for(size_t k = 0; k < sortedFeSpaces[j].size(); k++) { + + std::map<string,Valformat>::const_iterator it = dataformatMap.find(dataformat[valuePos + k]); + TEST_EXIT(it != dataformatMap.end())("Wrong data format.\n"); + + int unitsize = 0; + switch(it->second) { + case SI08: + case UI08: unitsize = 1;break; + case SI16: + case UI16: unitsize = 2;break; + case SI32: + case UI32: + case SF32: unitsize = 4;break; + case SI64: + case UI64: + case SF64: unitsize = 8;break; + default:ERROR_EXIT("Wrong data format.\n"); + } + dataStream.seekg(unitsize * nValuesPerVector, ios_base::cur); + } + valuePos += sortedFeSpaces[j].size(); } } } @@ -653,14 +788,41 @@ namespace AMDiS { namespace io { ("Cannot open file %s\n", filename.c_str()); int nMacroElements = 0; - detail::firstRead(file); + firstRead(file, "sarh", MAJOR, MINOR); file.seekg(20, ios_base::cur); file.read(reinterpret_cast<char*>(&nMacroElements), 4); file.close(); return nMacroElements; } - + + void readParallelFile(string filename, string& filenameType, vector<int>& partition, int& nFiles, int& nMacros) + { + ifstream file; + file.open(filename.c_str(), ios::in | ios::binary); + TEST_EXIT(file.is_open()) + ("Cannot open file %s\n", filename.c_str()); + + firstRead(file, "parh", 1, 0); + + uint32_t macroFile_nl = 0; + string macroFilename; + + filenameType.resize(4, ' '); + + file.read(reinterpret_cast<char*>(&nFiles), 4); + file.read(const_cast<char*>(filenameType.data()), 4); + file.read(reinterpret_cast<char*>(&nMacros), 4); + file.read(reinterpret_cast<char*>(¯oFile_nl), 4); + macroFilename.resize(macroFile_nl, ' '); + file.read(const_cast<char*>(macroFilename.data()), macroFile_nl); + + uint32_t rank = 0; + for (size_t i = 0; i < nMacros; i++) { + file.read(reinterpret_cast<char*>(&rank), 4); + partition.push_back(rank); + } + } } // end namespace detail } // end namespace Arh2Reader diff --git a/AMDiS/src/io/detail/Arh2Reader.h b/AMDiS/src/io/detail/Arh2Reader.h index d4d82d061abcd454f10ceec820d7cfff1c270b0f..fa1589cfc00a1b984f4569202584414b4a60c9b0 100644 --- a/AMDiS/src/io/detail/Arh2Reader.h +++ b/AMDiS/src/io/detail/Arh2Reader.h @@ -23,7 +23,7 @@ namespace AMDiS { namespace io { * 3. the minor version of Arh2Reader is bigger than the one in the file. * return value: minor version */ - uint8_t firstRead(std::ifstream& file); + void firstRead(std::ifstream& file, std::string, uint8_t, uint8_t); void setDofValues(int macroElIndex, Mesh *mesh, std::vector<std::vector<double> >& values, @@ -60,6 +60,11 @@ namespace AMDiS { namespace io { std::vector<DOFVector<double>*> vecs, bool byName = false); + void readValues(std::stringstream&, std::string dataformat, std::vector<double>&); + + template<typename T> + void readValues(std::stringstream&, std::vector<double>&); + void readFile(std::string filename, Mesh *mesh, std::vector<DOFVector<double>*> vecs, @@ -73,6 +78,13 @@ namespace AMDiS { namespace io { int readNumOfMacrosFromSgArh(std::string filename, int nProc = -1); + + + void readParallelFile(std::string filename, + std::string& filenameType, + std::vector<int>& partition, + int& nFiles, + int& nMacros); }//end namespace detail } // end namespace Arh2Reader diff --git a/AMDiS/src/io/detail/Arh2Writer.cc b/AMDiS/src/io/detail/Arh2Writer.cc index 6e95ce8e4248cf2cdbeccf4ab7ce397d7813807c..7a9993cc95fb2cdf03f6b5a7ec20d7f3b7f22922 100644 --- a/AMDiS/src/io/detail/Arh2Writer.cc +++ b/AMDiS/src/io/detail/Arh2Writer.cc @@ -7,12 +7,13 @@ #include "MeshStructure.h" #include "Traverse.h" #include "DOFVector.h" -#include "../Arh2Writer.h" +#include "../Arh2Reader.h" #include <boost/iostreams/filtering_streambuf.hpp> #include <boost/iostreams/copy.hpp> #ifdef HAVE_COMPRESSION #include <boost/iostreams/filter/zlib.hpp> +#include <boost/iostreams/filter/bzip2.hpp> #endif namespace AMDiS { namespace io { @@ -27,7 +28,10 @@ namespace AMDiS { namespace io { DOFVector<double>* vec0, DOFVector<double>* vec1, DOFVector<double>* vec2, - bool writeParallel) + bool writeParallel, + Cpsformat cps, + string dataformat, + string filenameType) { vector<DOFVector<double>*> vecs(0); if (vec0 != NULL) @@ -37,16 +41,63 @@ namespace AMDiS { namespace io { if (vec2 != NULL) vecs.push_back(vec2); - write(filename, NULL, vecs, writeParallel); + write(filename, NULL, vecs, writeParallel, cps, dataformat, filenameType); } - - void write(std::string filename, + +#ifdef HAVE_PARALLEL_DOMAIN_AMDIS + void writeParallelFile(string filename, Mesh* mesh, string filenameType) + { + TEST_EXIT(filenameType == "cont")("Unsupported filename type.\n"); + + ofstream file; + file.open(filename.c_str(), ios::out | ios::binary | ios::trunc); + + string typeId = "parh", macroFilename = ""; + Parameters::get(mesh->getName() + "->macro file name", macroFilename); + uint8_t major = 1; + uint8_t minor = 1; + uint32_t nFiles = MPI::COMM_WORLD.Get_size(); + uint32_t macroFile_nl = macroFilename.length(); + map<int, int> partitionMap = + Parallel::MeshDistributor::globalMeshDistributor->getPartitionMap(); + uint32_t nMacros =partitionMap.size(); + + file.write(typeId.c_str(), 4); + file.write(reinterpret_cast<char*>(&major), 1); + file.write(reinterpret_cast<char*>(&minor), 1); + file.write(reinterpret_cast<char*>(&nFiles), 4); + file.write(filenameType.c_str(), 4); + file.write(reinterpret_cast<char*>(&nMacros), 4); + file.write(reinterpret_cast<char*>(¯oFile_nl), 4); + file.write(macroFilename.c_str(), macroFile_nl); + + map<int, int>::const_iterator it = partitionMap.begin(); + uint32_t rank = 0; + for (;it != partitionMap.end(); it++) { + rank = it->second; + file.write(reinterpret_cast<char*>(&rank), 4); + } + } +#endif + + void write(string filename, Mesh* mesh, - std::vector<DOFVector<double>*> vecs, - bool writeParallel) + vector<DOFVector<double>*> vecs, + bool writeParallel, + Cpsformat cps, + string dataformat, + string filenameType) { FUNCNAME("Arh2Writer::detail::write()"); + if (!mesh && vecs.empty()) { + WARNING("There is nothing to be writen.\n"); + return; + } + + map<string,Valformat>::const_iterator it = dataformatMap.find(dataformat); + TEST_EXIT(it != dataformatMap.end())("Wrong data format.\n"); + std::set<string> nameSet; pair<std::set<string>::iterator,bool> ret; @@ -56,6 +107,28 @@ namespace AMDiS { namespace io { ret = nameSet.insert(vecs[i]->getName()); TEST_EXIT(ret.second)("DOFVectors in vecs cannot have idential name. Please check.\n"); } + +#ifdef HAVE_PARALLEL_DOMAIN_AMDIS + if (writeParallel) { + using boost::lexical_cast; + + int sPos = filename.find(".arh"); + TEST_EXIT(sPos >= 0)("Failed to find file postfix!\n"); + string name = filename.substr(0, sPos); + std::vector<int> macroIdx; + + Mesh* mesh_ = mesh ? mesh : vecs[0]->getFeSpace()->getMesh(); + + if (MPI::COMM_WORLD.Get_rank() == 0) { + writeParallelFile(name + ".parh", + mesh ? mesh : vecs[0]->getFeSpace()->getMesh(), + filenameType); + } + + TEST_EXIT(filenameType == "cont")("Only filename type \"cont\".\n"); + filename = name + "-p" + lexical_cast<string>(MPI::COMM_WORLD.Get_rank()) + "-.arh"; + } +#endif //if mesh exists, the meshes in vecs should be the same. if(mesh) { @@ -64,16 +137,11 @@ namespace AMDiS { namespace io { TEST_EXIT(mesh == vecs[i]->getFeSpace()->getMesh()) ("The mesh of DOFVector %i in vecs is not equal to the second parameter.\n", i); } - writeAux(filename, mesh, vecs, writeParallel); + writeAux(filename, mesh, vecs, writeParallel, cps, dataformat); } //multiple meshes are allowed here. else { - if(vecs.empty()) - { - WARNING("There is nothing to be writen.\n"); - return; - } vector<bool> visited(vecs.size(), false); vector<DOFVector<double>*> splitedVecs(0); bool moreMesh = false; @@ -113,23 +181,32 @@ namespace AMDiS { namespace io { newfilename = filename + "." + tmpMesh->getName() + ".arh"; } - writeAux(newfilename, splitedVecs[0]->getFeSpace()->getMesh(), splitedVecs, writeParallel); + writeAux(newfilename, splitedVecs[0]->getFeSpace()->getMesh(), splitedVecs, writeParallel, cps, dataformat); } } - } + } } int writeHeader(ofstream& file, Mesh *mesh, vector<DOFVector<double>*> vecs, - map<const FiniteElemSpace*, vector<int> >& feSpaces) + map<const FiniteElemSpace*, vector<int> >& feSpaces, + Cpsformat cps, + string dataformat) { FUNCNAME("Arh2Writer::detail::writeHeader()"); + int nbits = boost::lexical_cast<int>(dataformat.substr(2, 2)); TEST_EXIT(file.is_open())("the file is not open. should not happen.\n"); - - uint32_t namesLen = 0; - for(size_t i = 0; i < vecs.size(); i++) - namesLen += vecs[i]->getName().length(); + + map<const FiniteElemSpace*, string> AFEDfileName; + + uint32_t valueNamesLen = 0, fileNamesLen = 0; + for (size_t i = 0; i < vecs.size(); i++) + valueNamesLen += vecs[i]->getName().length(); + + map<const FiniteElemSpace*, vector<int> >::iterator feSpaceIt; + for (feSpaceIt = feSpaces.begin(); feSpaceIt != feSpaces.end(); feSpaceIt++) + AFEDfileName.insert(make_pair(feSpaceIt->first, string())); uint32_t nValueVectors = vecs.size(); uint32_t nFeSpaces = feSpaces.size(); @@ -145,17 +222,20 @@ namespace AMDiS { namespace io { uint32_t dow = mesh->getGeo(WORLD); uint32_t dim = mesh->getDim(); - uint32_t headerLen = 34 + //fixed part of header - nMacroElements * 8 + //macroElemnts table - nFeSpaces * 16 + //feSpaces table - namesLen + //value vector table - nValueVectors * 8; //also value vector table - string typeId = "arh2", cps("null"); -#ifdef HAVE_COMPRESSION - cps = "zlib"; + uint32_t headerLen = 34 + //fixed part of header + nMacroElements * 12 + 12 + //macroElemnts table + fileNamesLen + //feSpaces table + nFeSpaces * 20 + //feSpaces table + valueNamesLen + //value vector table + nValueVectors * 12; //also value vector table + string typeId = "sarh"; +#ifndef HAVE_COMPRESSION + cps = NONE; #endif - uint8_t *major = const_cast<uint8_t*>(&(AMDiS::io::Arh2Writer::MAJOR)); - uint8_t *minor = const_cast<uint8_t*>(&(AMDiS::io::Arh2Writer::MINOR)); + uint8_t *major = const_cast<uint8_t*>(&(AMDiS::io::Arh2Reader::MAJOR)); + uint8_t *minor = const_cast<uint8_t*>(&(AMDiS::io::Arh2Reader::MINOR)); + int cpsflag = static_cast<int>(cps); + uint32_t minus1 = -1; //fixed header file.write(typeId.c_str(), 4); @@ -167,78 +247,79 @@ namespace AMDiS { namespace io { file.write(reinterpret_cast<char*>(&nFeSpaces), 4); file.write(reinterpret_cast<char*>(&nValueVectors), 4); file.write(reinterpret_cast<char*>(&nMacroElements), 4); - file.write(cps.c_str(), 4); + file.write(reinterpret_cast<char*>(&cpsflag), 4); //macro table deque<MacroElement*>::const_iterator macroIter = mesh->firstMacroElement(); + while(macroIter != mesh->endOfMacroElements()) { - uint32_t macroIndex = (*macroIter)->getIndex(), macroPos = 0; + uint32_t macroIndex = (*macroIter)->getIndex(); file.write(reinterpret_cast<char*>(¯oIndex), 4); - file.write(reinterpret_cast<char*>(¯oPos), 4); + file.write(reinterpret_cast<char*>(&minus1), 4); + file.write(reinterpret_cast<char*>(&minus1), 4); macroIter++; } + file.write(reinterpret_cast<char*>(&minus1), 4); + file.write(reinterpret_cast<char*>(&minus1), 4); + file.write(reinterpret_cast<char*>(&minus1), 4); - map<const FiniteElemSpace*, vector<int> >::iterator feSpaceIt; vector<int> feSpaceNumOfVecs(vecs.size()); - uint32_t posDOFs = 0, vecNameLen = 0; - string vecName(""); + uint32_t posDOFs = 0, nameStrLen = 0; + string nameStr(""); size_t i = 0; //feSpace table for(feSpaceIt = feSpaces.begin(); feSpaceIt != feSpaces.end(); feSpaceIt++, i++) { + nameStr = AFEDfileName[feSpaceIt->first]; + nameStrLen = nameStr.length(); + file.write(reinterpret_cast<char*>(&nameStrLen), 4); + file.write(nameStr.c_str(), nameStrLen); DimVec<int>* nDOF = feSpaceIt->first->getBasisFcts()->getNumberOfDofs(); - for(int j = 0; j < nDOF->getSize(); j++) - { + // + for(size_t j = 1; j < nDOF->getSize(); j++) { posDOFs = (*nDOF)[j]; file.write(reinterpret_cast<char*>(&posDOFs), 4); } - for(size_t j = nDOF->getSize(); j < 4 ; j++) - { + for(size_t j = nDOF->getSize(); j < 4 ; j++) { posDOFs = 0; file.write(reinterpret_cast<char*>(&posDOFs), 4); } + posDOFs = (*nDOF)[0]; + file.write(reinterpret_cast<char*>(&posDOFs), 4); + // for(size_t j = 0; j < feSpaceIt->second.size(); j++) - { feSpaceNumOfVecs[feSpaceIt->second[j]] = i; - } } //vector table for(i = 0; i < vecs.size(); i++) { - vecName = vecs[i]->getName(); - vecNameLen = vecs[i]->getName().length(); - file.write(reinterpret_cast<char*>(&vecNameLen), 4); - file.write(vecName.c_str(), vecNameLen); + nameStr = vecs[i]->getName(); + nameStrLen = nameStr.length(); + file.write(reinterpret_cast<char*>(&nameStrLen), 4); + file.write(nameStr.c_str(), nameStrLen); file.write(reinterpret_cast<char*>(&feSpaceNumOfVecs[i]), 4); + file.write(dataformat.c_str(), 4); } return headerLen; } void writeAux(string filename, Mesh *mesh, vector<DOFVector<double>*> vecs, - bool writeParallel) + bool writeParallel, + Cpsformat cps, + string dataformat) { FUNCNAME("Arh2Writer::detail::writeAux()"); -#ifdef HAVE_PARALLEL_DOMAIN_AMDIS - if (writeParallel) { - using boost::lexical_cast; - - int sPos = filename.find(".arh"); - TEST_EXIT(sPos >= 0)("Failed to find file postfix!\n"); - string name = filename.substr(0, sPos); - filename = name + "-p" + lexical_cast<string>(MPI::COMM_WORLD.Get_rank()) + "-.arh"; - } -#endif //initialization ofstream file; file.open(filename.c_str(), ios::out | ios::binary | ios::trunc); map<const FiniteElemSpace*, vector<int> > sortedFeSpaces; map<const FiniteElemSpace*, vector<int> >::iterator feSpaceIt; - vector<int> macroBlockSize; + vector<pair<int, int> > macroSize; // (uncompressed size, compressed size) DegreeOfFreedom globalDof; size_t i = 0, j = 0; @@ -250,7 +331,7 @@ namespace AMDiS { namespace io { vector<std::set<DegreeOfFreedom> > visited(sortedFeSpaces.size()); pair<std::set<DegreeOfFreedom>::iterator,bool> ret; //file header information - writeHeader(file, mesh, vecs, sortedFeSpaces); + int headerLen = writeHeader(file, mesh, vecs, sortedFeSpaces, cps, dataformat); //macro elements information MeshStructure elementStructure; @@ -263,18 +344,17 @@ namespace AMDiS { namespace io { if (elInfo->getLevel() == 0) { if (macroElIndex != -1) { elementStructure.commit(); - macroBlockSize.push_back(writeMacroElement(file, elementStructure, values, sortedFeSpaces)); + macroSize.push_back(writeMacroElement(file, elementStructure, values, sortedFeSpaces, cps, dataformat)); } elementStructure.clear(); macroElIndex = elInfo->getElement()->getIndex(); - for (j = 0; j < vecs.size(); j++) { + + for (j = 0; j < vecs.size(); j++) values[j].clear(); - } + for (j = 0; j < sortedFeSpaces.size(); j++) - { - visited[j].clear(); - } + visited[j].clear(); } elementStructure.insertElement(elInfo->getElement()->isLeaf()); @@ -371,30 +451,39 @@ namespace AMDiS { namespace io { // And write the last macro element to file. TEST_EXIT_DBG(macroElIndex != -1)("Should not happen!\n"); elementStructure.commit(); - macroBlockSize.push_back(writeMacroElement(file, elementStructure, values, sortedFeSpaces)); - TEST_EXIT(macroBlockSize.size() == (unsigned)mesh->getNumberOfMacros())("Should not happen.\n"); + macroSize.push_back(writeMacroElement(file, elementStructure, values, sortedFeSpaces, cps, dataformat)); + TEST_EXIT(macroSize.size() == (unsigned)mesh->getNumberOfMacros())("Should not happen.\n"); //reset the macro positions in file - setMacrosPos(file, macroBlockSize); + setMacrosPos(file, headerLen, macroSize); file.close(); MSG("ARH file written to: %s\n", filename.c_str()); } - void setMacrosPos(ofstream& file, - vector<int>& macroBlockSize) + void setMacrosPos(ofstream& file, int headerLen, + vector<pair<int, int> >& macroSize) { file.seekp(34); - for(size_t i = 0; i < macroBlockSize.size(); i++) + long pos = 0; + int startPos = headerLen; + for(size_t i = 0; i < macroSize.size(); i++) { - long pos = file.tellp(); + pos = file.tellp(); file.seekp(pos + 4); - file.write(reinterpret_cast<char*>(¯oBlockSize[i]), 4); + file.write(reinterpret_cast<char*>(&startPos), 4); + file.write(reinterpret_cast<char*>(¯oSize[i].first), 4); + startPos += macroSize[i].second; } + pos = file.tellp(); + file.seekp(pos + 4); + file.write(reinterpret_cast<char*>(&startPos), 4); } - int writeMacroElement(ofstream &file, + pair<int, int> writeMacroElement(ofstream &file, MeshStructure &code, vector<vector<double> >& values, - map<const FiniteElemSpace*, vector<int> >& feSpaces) + map<const FiniteElemSpace*, vector<int> >& feSpaces, + Cpsformat cps, + string dataformat) { stringstream dataStream(ios::out | ios::in | ios::binary); @@ -417,24 +506,92 @@ namespace AMDiS { namespace io { moreSize += 4; for (size_t i = 0; i < it->second.size(); i++) - { - dataStream.write(reinterpret_cast<char*>(&(values[valuePos + i][0])), 8 * nValuesPerVector); - moreSize += 8 * nValuesPerVector; - } + moreSize += writeValues(dataStream, dataformat, values[valuePos + i]); + valuePos += it->second.size(); } } stringstream tmp(ios::out | ios::in | ios::binary); boost::iostreams::filtering_streambuf<boost::iostreams::input> in; #ifdef HAVE_COMPRESSION - in.push(boost::iostreams::zlib_compressor()); + switch(cps) + { + case ZLIB: + in.push(boost::iostreams::zlib_compressor()); + break; + case BZIP2: + in.push(boost::iostreams::bzip2_compressor()); + break; + case NONE: + break; + default: + MSG("NOT correct compression flag.\n"); + } #endif in.push(dataStream); boost::iostreams::copy(in, tmp); file << tmp.rdbuf(); - return tmp.str().length(); + return make_pair(dataStream.str().length(), tmp.str().length()); } + template<typename T> + int writeValues(stringstream& file, vector<double>& values) + { + int size = values.size(); + T data[size]; + for (size_t i = 0; i < size; i++) + data[i] = static_cast<T>(values[i]); + + file.write(reinterpret_cast<char*>(&data[0]), sizeof(T) * size); + return sizeof(T) * size; + } + + int writeValues(stringstream& file, + string dataformat, + vector<double>& values) + { + FUNCNAME("Arh2Writer::detail::writeValues()"); + int newsize = 0; + std::map<string,Valformat>::const_iterator it = dataformatMap.find(dataformat); + + TEST_EXIT(it != dataformatMap.end())("Wrong data format.\n"); + + switch(it->second) { + case SI08: + newsize = writeValues<int8_t>(file, values); + break; + case SI16: + newsize = writeValues<int16_t>(file, values); + break; + case SI32: + newsize = writeValues<int32_t>(file, values); + break; + case SI64: + newsize = writeValues<int64_t>(file, values); + break; + case UI08: + newsize = writeValues<uint8_t>(file, values); + break; + case UI16: + newsize = writeValues<uint16_t>(file, values); + break; + case UI32: + newsize = writeValues<uint32_t>(file, values); + break; + case UI64: + newsize = writeValues<uint64_t>(file, values); + break; + case SF32: + newsize = writeValues<float>(file, values); + break; + case SF64: + newsize = writeValues<double>(file, values); + break; + default: + ERROR_EXIT("Wrong data format.\n"); + } + return newsize; + } }//end namespace detail } // end namespace Arh2Writer } } // end namespace io, AMDiS diff --git a/AMDiS/src/io/detail/Arh2Writer.h b/AMDiS/src/io/detail/Arh2Writer.h index 90e6612936d4d07bb4f9dffa634bdea8cd45e2b7..967f8a465014b804093d87ddf4a52068b22a043f 100644 --- a/AMDiS/src/io/detail/Arh2Writer.h +++ b/AMDiS/src/io/detail/Arh2Writer.h @@ -6,11 +6,33 @@ #include "MeshStructure.h" #include "DOFVector.h" #include "SystemVector.h" +#include "boost/assign.hpp" namespace AMDiS { namespace io { namespace Arh2Writer { + typedef enum{ + NONE = 0, + ZLIB = 1, + BZIP2 = 2 + } Cpsformat; + + typedef enum{SI08, SI16, SI32, SI64, UI08, UI16, UI32, UI64, SF32, SF64} Valformat; + + using namespace boost::assign; + + static const std::map<std::string, Valformat> dataformatMap = map_list_of("SI08", SI08) + ("SI16", SI16) + ("SI32", SI32) + ("SI64", SI64) + ("UI08", UI08) + ("UI16", UI16) + ("UI32", UI32) + ("UI64", UI64) + ("SF32", SF32) + ("SF64", SF64); + namespace detail { //Maybe remove this later @@ -18,7 +40,10 @@ namespace AMDiS { namespace io { DOFVector<double>* vec0 = NULL, DOFVector<double>* vec1 = NULL, DOFVector<double>* vec2 = NULL, - bool writeParallel = true); + bool writeParallel = true, + Cpsformat cps = NONE, + std::string dataformat = "SF64", + std::string filenameType = "cont"); /** * \ingroup Output @@ -43,27 +68,47 @@ namespace AMDiS { namespace io { void write(std::string filename, Mesh* mesh, std::vector<DOFVector<double>*> vecs, - bool writeParallel = true); + bool writeParallel = true, + Cpsformat cps = NONE, + std::string dataformat = "SF64", + std::string filenameType = "cont"); void writeAux(std::string filename, Mesh *mesh, std::vector<DOFVector<double>*> vecs, - bool writeParallel); + bool writeParallel, Cpsformat cps, + std::string dataformat); ///\return the size of the macro block in file - int writeMacroElement(std::ofstream &file, + std::pair<int, int> writeMacroElement(std::ofstream &file, MeshStructure &code, std::vector<std::vector<double> >& values, - std::map<const FiniteElemSpace*, std::vector<int> >& feSpaces); + std::map<const FiniteElemSpace*, + std::vector<int> >& feSpaces, + Cpsformat cps, std::string dataformat); + + int writeValues(std::stringstream& file, + std::string dataformat, + std::vector<double>& values); + + template<typename T> + int writeValues(std::stringstream& file, std::vector<double>& values); int writeHeader(std::ofstream& file, Mesh* mesh, std::vector<DOFVector<double>*> vecs, - std::map<const FiniteElemSpace*, std::vector<int> >& feSpaces); + std::map<const FiniteElemSpace*, + std::vector<int> >& feSpaces, + Cpsformat cps, std::string dataformat); ///internal method, don't call - void setMacrosPos(std::ofstream& file, - std::vector<int>& macrosPosVec); - + void setMacrosPos(std::ofstream& file, int headerLen, + std::vector<std::pair<int, int> >& macroSize); + +#ifdef HAVE_PARALLEL_DOMAIN_AMDIS + void writeParallelFile(std::string filename, + Mesh* mesh, + std::string filenameType); +#endif }//end namespace detail } // end namespace Arh2Writer } } // end namespace io, AMDiS diff --git a/AMDiS/src/parallel/MeshDistributor.cc b/AMDiS/src/parallel/MeshDistributor.cc index 39ca881652cf47cee04ebd72d77fe2f09be2ec34..f6e7b2a6bcc9adb5a7c8bfe065d133cf4c8f14f6 100644 --- a/AMDiS/src/parallel/MeshDistributor.cc +++ b/AMDiS/src/parallel/MeshDistributor.cc @@ -266,9 +266,9 @@ namespace AMDiS { namespace Parallel { debug::ElementIdxToCoords macroCoords; debug::createNodeCoords(macroMesh, macroCoords); - for (size_t i = 1; i < meshes.size(); i++) { + for (size_t i = 1; i < meshes.size(); i++) debug::testNodeCoords(meshes[i], macroCoords); - } + #endif // Initialize dof communicators which have been created in addProblemStat. diff --git a/AMDiS/src/parallel/MeshDistributor.h b/AMDiS/src/parallel/MeshDistributor.h index efad03e2494ffb706b852644a45deab03b37fb47..157dbb783662672b9403e2f3129ee23a09a79c0b 100644 --- a/AMDiS/src/parallel/MeshDistributor.h +++ b/AMDiS/src/parallel/MeshDistributor.h @@ -196,6 +196,11 @@ namespace AMDiS { namespace Parallel { { return intBoundary[level]; } + + std::map<int, int>& getPartitionMap() + { + return partitionMap; + } inline long getLastMeshChangeIndex() {