Commit 96d0b4bc authored by Siqi Ling's avatar Siqi Ling

change in arh, parh file. update with meshconv

parent 92b1e9ce
......@@ -5,6 +5,12 @@
#include "SystemVector.h"
#include "detail/Arh3Writer.h"
#ifdef HAVE_PARALLEL_DOMAIN_AMDIS
#define WRITE_MACRO false
#else
#define WRITE_MACRO true
#endif
namespace AMDiS { namespace io {
/** \ingroup Output
......@@ -45,21 +51,23 @@ namespace AMDiS { namespace io {
std::string filename,
bool writeParallel = true,
Cpsformat cps = NONE,
std::string dataformat = "SF64")
std::string dataformat = "SF64",
bool writeMacro = WRITE_MACRO)
{
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, cps, dataformat);
detail::write(filename, NULL, vecs, writeParallel, cps, dataformat, writeMacro);
}
inline void writeFile(SystemVector &sysVec,
std::string filename,
bool writeParallel = true,
Cpsformat cps = NONE,
std::string dataformat = "SF64")
std::string dataformat = "SF64",
bool writeMacro = WRITE_MACRO)
{
writeFile(&sysVec, filename, writeParallel, cps, dataformat);
writeFile(&sysVec, filename, writeParallel, cps, dataformat, writeMacro);
}
/// write the meshstructure and the dof values of DOFVectors in vec0
......@@ -68,11 +76,12 @@ namespace AMDiS { namespace io {
std::string filename,
bool writeParallel = true,
Cpsformat cps = NONE,
std::string dataformat = "SF64")
std::string dataformat = "SF64",
bool writeMacro = WRITE_MACRO)
{
std::vector<DOFVector<double>*> vecs;
vecs.push_back(vec0);
detail::write(filename, NULL, vecs, writeParallel, cps, dataformat);
detail::write(filename, NULL, vecs, writeParallel, cps, dataformat, writeMacro);
}
/// write the meshstructure and the dof values of DOFVectors in vec0
......@@ -81,9 +90,10 @@ namespace AMDiS { namespace io {
std::string filename,
bool writeParallel = true,
Cpsformat cps = NONE,
std::string dataformat = "SF64")
std::string dataformat = "SF64",
bool writeMacro = WRITE_MACRO)
{
writeFile(&vec0, filename, writeParallel, cps, dataformat);
writeFile(&vec0, filename, writeParallel, cps, dataformat, writeMacro);
}
/// write the meshstructure and the dof values of DOFVectors in vecs
......@@ -92,9 +102,10 @@ namespace AMDiS { namespace io {
std::string filename,
bool writeParallel = true,
Cpsformat cps = NONE,
std::string dataformat = "SF64")
std::string dataformat = "SF64",
bool writeMacro = WRITE_MACRO)
{
detail::write(filename, NULL, vecs, writeParallel, cps, dataformat);
detail::write(filename, NULL, vecs, writeParallel, cps, dataformat, writeMacro);
}
/// write the meshstructure of the mesh to arh file.
......@@ -102,10 +113,11 @@ namespace AMDiS { namespace io {
std::string filename,
bool writeParallel = true,
Cpsformat cps = NONE,
std::string dataformat = "SF64")
std::string dataformat = "SF64",
bool writeMacro = WRITE_MACRO)
{
std::vector<DOFVector<double>*> vecs;
detail::write(filename, mesh, vecs, writeParallel, cps, dataformat);
detail::write(filename, mesh, vecs, writeParallel, cps, dataformat, writeMacro);
}
#ifdef HAVE_PARALLEL_DOMAIN_AMDIS
......
......@@ -73,6 +73,13 @@ namespace AMDiS
for (size_t i = 0; i < solutionVecs.size(); i++)
solutionNames.push_back(solutionVecs[i]->getName());
std::set<Mesh*> meshset;
for (size_t i = 0; i < solutionVecs.size(); i++)
if (solutionVecs[i])
meshset.insert(solutionVecs[i]->getFeSpace()->getMesh());
multiMesh = meshset.size() > 1;
}
......@@ -201,8 +208,17 @@ namespace AMDiS
Arh2Writer::writeFile(solutionVecs, fn_ + ".arh");
else if (writeArh1)
ArhWriter::write(fn_ + ".arh", feSpace->getMesh(), solutionVecs);
else if (writeArh3 || writeArhFormat)
Arh3Writer::writeFile(solutionVecs, fn_ + ".arh");
else if (writeArh3 || writeArhFormat) {
#if HAVE_PARALLEL_DOMAIN_AMDIS
if (MPI::COMM_WORLD.Get_rank() == 0) {
TEST_EXIT(!multiMesh) ("Multi mesh arh writer is not supported in parallel.\n");
Arh3Writer::detail::writeParallelFile(paraFilename + arhParallelFileExt,
feSpace->getMesh(),
createSubDir > 0);
}
#endif
Arh3Writer::writeFile(solutionVecs, fn + ".arh");
}
#ifdef HAVE_PNG
......
......@@ -102,6 +102,9 @@ namespace AMDiS {
/// Reads all file writer dependend parameters from the init file.
virtual void readParameters(std::string name) override;
/// Multi mesh flag
bool multiMesh;
/// Name of the writer.
std::string name;
......@@ -117,6 +120,12 @@ namespace AMDiS {
/// Parallel VTK file extension.
std::string paraviewParallelFileExt;
/// Parallel ARH file extension.
std::string arhParallelFileExt;
/// Time ARH file extension.
std::string arhTimeFileExt;
/// Periodic file extension.
std::string periodicFileExt;
......
......@@ -119,10 +119,13 @@ namespace AMDiS
template<typename T>
void FileWriter<T>::initialize()
{
multiMesh = false;
amdisMeshExt = ".mesh";
amdisDataExt = ".dat";
paraviewFileExt = ".vtu";
paraviewParallelFileExt = ".pvtu";
arhParallelFileExt = ".parh";
arhTimeFileExt = ".tarh";
periodicFileExt = ".per";
writeAMDiSFormat = 0;
writeParaViewFormat = 0;
......
......@@ -24,6 +24,20 @@ namespace AMDiS { namespace io {
{
namespace detail
{
void firstRead(std::string id_, uint8_t major_, uint8_t minor_, //version in file
std::string id, uint8_t major, uint8_t minor) //class version
{
TEST_EXIT(id == id_)
("Cannot read Arh format: this file is not \"%s\" format.\n", id.c_str());
TEST_EXIT(major == major_)
("Cannot read Arh format: Arh2Reader major version is %i, the file major version is %i. \n",
major, major_);
TEST_EXIT(minor >= minor_)
("Cannot read Arh format: ArhReader minor version is %i is smaller than the file minor version %i.\n",
minor, minor_);
}
void firstRead(ifstream& file, string id, uint8_t major, uint8_t minor)
{
......@@ -34,18 +48,10 @@ namespace AMDiS { namespace io {
string typeId(4, ' ');
file.read(const_cast<char*>(typeId.data()), 4);
TEST_EXIT(typeId == id)
("Cannot read Arh format: this file is not \"%s\" format.\n", id.c_str());
file.read(reinterpret_cast<char*>(&major_), 1);
TEST_EXIT(major == major_)
("Cannot read Arh format: Arh2Reader major version is %i, the file major version is %i. \n",
major, major_);
file.read(reinterpret_cast<char*>(&minor_), 1);
TEST_EXIT(minor <= minor_)
("Cannot read Arh format: ArhReader minor version is %i is smaller than the file minor version %i.\n",
minor, minor_);
firstRead(typeId, major_, minor_, id, major, minor);
}
void setDofValues(int macroElIndex, Mesh *mesh,
......@@ -315,7 +321,19 @@ namespace AMDiS { namespace io {
tmpString.resize(4, ' ');
file.read(const_cast<char*>(tmpString.data()), 4);
dataformat.push_back(tmpString);
}
}
// Read macroFile_nl
uint32_t macroFile_nl = 0;
file.read(reinterpret_cast<char*>(&macroFile_nl), 4);
if (macroFile_nl > 0) {
string tmpString("");
tmpString.resize(macroFile_nl, ' ');
file.read(const_cast<char*>(tmpString.data()), macroFile_nl);
}
//================header is over==================//
// Adjust and check vecs
if(byName)
{
......@@ -546,38 +564,49 @@ namespace AMDiS { namespace io {
}
if (writeParallel) {
using boost::lexical_cast;
using namespace boost::filesystem;
path file_name = filename;
path file_onlyname = file_name.filename();
int sPos = filename.find(".arh");
TEST_EXIT(sPos >= 0)("Failed to find file postfix!\n");
string name = filename.substr(0, sPos);
string filenameWithoutExt = filename.substr(0, sPos);
sPos = file_onlyname.string().find(".arh");
string onlynameWithoutExt = file_onlyname.string().substr(0, sPos);
string parh = filenameWithoutExt + ".parh";
string basedir = "";
path file_path = file_name.remove_filename();
int nProcs_ = 0, nMacros_ = 0, nMacros = 0;
vector<int> partition;
bool parhExists = exists(parh);
if (parhExists)
basedir = readParallelFile(parh, partition, nProcs_, nMacros_);
if (basedir != "")
filenameWithoutExt = file_path.string() + '/' + basedir + onlynameWithoutExt;
if (nProcs == -1) {
#ifdef HAVE_PARALLEL_DOMAIN_AMDIS
string procFilename = name + "-p" + lexical_cast<string>(MPI::COMM_WORLD.Get_rank()) + "-.arh";
string procFilename = filenameWithoutExt + "-p" + lexical_cast<string>(MPI::COMM_WORLD.Get_rank()) + "-.arh";
read(procFilename, mesh, vecs, byName);
MSG("ARH file read from: %s\n", procFilename.c_str());
#else
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;
bool parh = boost::filesystem::exists(parhfn);
if (parh)
readParallelFile(parhfn, filenameType, partition, nProcs_, nMacros_);
else {
if (!parhExists) {
for (; nProcs_ < nProcs + 1; nProcs_++) {
string fn = name + "-p" + boost::lexical_cast<string>(nProcs_) + "-.arh";
string fn = filenameWithoutExt + "-p" + boost::lexical_cast<string>(nProcs_) + "-.arh";
if(!boost::filesystem::exists(fn)) break;
}
}
TEST_EXIT(nProcs_ == nProcs)
("Number of arh files doesn't match number of processors: %d vs %d\n", nProcs_, nProcs);
if (!parh) {
if (!parhExists) {
#ifdef HAVE_PARALLEL_DOMAIN_AMDIS
if(MPI::COMM_WORLD.Get_rank() == 0)
if (MPI::COMM_WORLD.Get_rank() == 0)
#endif
for(int i = 0; i < nProcs; i++)
nMacros_ += readNumOfMacrosFromSgArh(filename, i);
......@@ -594,9 +623,9 @@ namespace AMDiS { namespace io {
nMacros, nMacros_);
}
if (!parh) {
if (!parhExists) {
for (int i = 0; i < nProcs; i++) {
string procFilename = name + "-p" + lexical_cast<string>(i) + "-.arh";
string procFilename = filenameWithoutExt + "-p" + lexical_cast<string>(i) + "-.arh";
read(procFilename, mesh, vecs, byName);
}
} else {
......@@ -607,7 +636,7 @@ namespace AMDiS { namespace io {
std::set<int>::iterator it2 = needFiles.begin();
for (;it2 != needFiles.end(); it2++) {
string procFilename = name + "-p" + lexical_cast<string>(*it2) + "-.arh";
string procFilename = filenameWithoutExt + "-p" + lexical_cast<string>(*it2) + "-.arh";
read(procFilename, mesh, vecs, byName);
}
}
......@@ -693,7 +722,15 @@ namespace AMDiS { namespace io {
tmpString.resize(4, ' ');
file.read(const_cast<char*>(tmpString.data()), 4);
dataformat.push_back(tmpString);
}
}
// Read macroFile_nl
uint32_t macroFile_nl = 0;
file.read(reinterpret_cast<char*>(&macroFile_nl), 4);
string tmpString("");
file.read(const_cast<char*>(tmpString.data()), macroFile_nl);
//================header is over==================//
for (uint32_t i = 0; i < nMacroElements; i++) {
stringstream dataStream(ios::out | ios::in | ios::binary);
......@@ -799,32 +836,41 @@ namespace AMDiS { namespace io {
return nMacroElements;
}
void readParallelFile(string filename, string& filenameType, vector<int>& partition, int& nFiles, int& nMacros)
std::string readParallelFile(string filename, 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;
string fd(16, ' ');
file.read(const_cast<char*>(fd.data()), 16);
string Id = fd.substr(0, 4);
int major = boost::lexical_cast<int>(fd.substr(5, 1));
int minor = boost::lexical_cast<int>(fd.substr(7, 1));
firstRead(Id, major, minor, "parh", 1, 0);
filenameType.resize(4, ' ');
uint32_t baseDirLen = 0, macroFile_nl = 0;
string baseDir, macroFilename;
file.read(reinterpret_cast<char*>(&baseDirLen), 4);
baseDir.resize(baseDirLen, ' ');
file.read(const_cast<char*>(baseDir.data()), baseDirLen);
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*>(&macroFile_nl), 4);
macroFilename.resize(macroFile_nl, ' ');
file.read(const_cast<char*>(macroFilename.data()), macroFile_nl);
if (macroFile_nl > 0) {
macroFilename.resize(macroFile_nl, ' ');
file.read(const_cast<char*>(macroFilename.data()), macroFile_nl);
}
file.read(reinterpret_cast<char*>(&nMacros), 4);
uint32_t rank = 0;
for (int i = 0; i < nMacros; i++) {
file.read(reinterpret_cast<char*>(&rank), 4);
partition.push_back(rank);
}
return baseDir;
}
} // end namespace detail
......
......@@ -23,6 +23,8 @@ namespace AMDiS { namespace io {
* 3. the minor version of Arh2Reader is bigger than the one in the file.
* return value: minor version
*/
void firstRead(std::string, uint8_t, uint8_t, std::string, uint8_t, uint8_t);
void firstRead(std::ifstream& file, std::string, uint8_t, uint8_t);
void setDofValues(int macroElIndex, Mesh *mesh,
......@@ -80,8 +82,7 @@ namespace AMDiS { namespace io {
int readNumOfMacrosFromSgArh(std::string filename, int nProc = -1);
void readParallelFile(std::string filename,
std::string& filenameType,
std::string readParallelFile(std::string filename,
std::vector<int>& partition,
int& nFiles,
int& nMacros);
......
#include <fstream>
#include <stdint.h>
#include <iostream>
#include <streambuf>
#include "Arh3Writer.h"
#include "Mesh.h"
......@@ -31,7 +32,7 @@ namespace AMDiS { namespace io {
bool writeParallel,
Cpsformat cps,
string dataformat,
string filenameType)
bool writeMacro)
{
vector<DOFVector<double>*> vecs(0);
if (vec0 != NULL)
......@@ -41,35 +42,53 @@ namespace AMDiS { namespace io {
if (vec2 != NULL)
vecs.push_back(vec2);
write(filename, NULL, vecs, writeParallel, cps, dataformat, filenameType);
write(filename, NULL, vecs, writeParallel, cps, dataformat, writeMacro);
}
#ifdef HAVE_PARALLEL_DOMAIN_AMDIS
void writeParallelFile(string filename, Mesh* mesh, string filenameType)
void writeParallelFile(string filename, Mesh* mesh, bool createSubDir, bool writeMacro)
{
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 = "";
string typeId = "parh", macroFilename = "", perFilename = "";
string baseDir = createSubDir ? "./data/" : "";
string macroData = "", periodicData = "";
uint32_t baseDirLen = baseDir.length();
Parameters::get(mesh->getName() + "->macro file name", macroFilename);
uint8_t major = 1;
uint8_t minor = 0;
Parameters::get(mesh->getName() + "->periodic file", perFilename);
int major = 1, minor = 0;
uint32_t nFiles = MPI::COMM_WORLD.Get_size();
uint32_t macroFile_nl = macroFilename.length();
uint32_t macroFile_nl = 0;
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);
uint32_t nMacros = partitionMap.size();
typeId += '_' + boost::lexical_cast<string>(major) + '.' + boost::lexical_cast<string>(minor);
if (typeId.length() <= 16) { // 16 is the Id size
string rest(16 - typeId.length(), ' ');
typeId.append(rest);
}
else
ERROR_EXIT("Should not happen.\n");
file.write(typeId.c_str(), 16);
file.write(reinterpret_cast<char*>(&baseDirLen), 4);
file.write(baseDir.c_str(), baseDirLen);
file.write(reinterpret_cast<char*>(&nFiles), 4);
file.write(filenameType.c_str(), 4);
file.write(reinterpret_cast<char*>(&nMacros), 4);
if (writeMacro && macroFilename.length()) {
macroFile_nl = 13;
readFileToString(macroFilename, macroData);
if (perFilename.length()) {
macroFile_nl = 27;
readFileToString(perFilename, periodicData);
}
}
file.write(reinterpret_cast<char*>(&macroFile_nl), 4);
file.write(macroFilename.c_str(), macroFile_nl);
file.write(reinterpret_cast<char*>(&nMacros), 4);
map<int, int>::const_iterator it = partitionMap.begin();
uint32_t rank = 0;
......@@ -77,6 +96,29 @@ namespace AMDiS { namespace io {
rank = it->second;
file.write(reinterpret_cast<char*>(&rank), 4);
}
// write macro and periodic file
if (writeMacro && macroFilename.length()) {
file.seekp(0, ios_base::end);
long macroPos = file.tellp(), perPos = 0;
file.write(macroData.c_str(), macroData.length());
if (perFilename.length()) {
perPos = file.tellp();
file.write(periodicData.c_str(), periodicData.length());
}
// update macroFile_nl
int offset = 16 + //typeId
4 + //baseDirLen
baseDirLen + //baseDir
4 + //nFiles
4; //macroFile_nl
file.seekp(offset);
file << "this:" << macroPos;
if (perFilename.length())
file << ";this:" << perPos;
}
}
#endif
......@@ -86,100 +128,74 @@ namespace AMDiS { namespace io {
bool writeParallel,
Cpsformat cps,
string dataformat,
string filenameType)
bool writeMacro)
{
FUNCNAME("Arh3Writer::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;
for(size_t i = 0; i < vecs.size(); i++)
{
std::set<Mesh*> meshset;
std::set<string> nameset;
if (mesh)
meshset.insert(mesh);
for (size_t i = 0; i < vecs.size(); i++) {
TEST_EXIT(vecs[i] != NULL)("Vecs[%i] is NULL. Please check.\n", i);
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_, filenameType);
}
meshset.insert(vecs[i]->getFeSpace()->getMesh());
nameset.insert(vecs[i]->getName());
}
TEST_EXIT(filenameType == "cont")("Only filename type \"cont\".\n");
filename = name + "-p" + lexical_cast<string>(MPI::COMM_WORLD.Get_rank()) + "-.arh";
if (meshset.size() == 0) {
WARNING("There is nothing to be writen.\n");
return;
}
#endif
TEST_EXIT(nameset.size() == vecs.size())
("DOFVectors in vecs cannot have idential name. Please check.\n");
bool multiMesh = meshset.size() > 1;
//if mesh exists, the meshes in vecs should be the same.
if(mesh)
{
for(size_t i = 0; i < vecs.size(); i++)
{
if (mesh) {
for (size_t i = 0; i < vecs.size(); i++)
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, cps, dataformat);
}
//multiple meshes are allowed here.
else
{
vector<bool> visited(vecs.size(), false);
vector<DOFVector<double>*> splitedVecs(0);
bool moreMesh = false;
Mesh* tmpMesh = vecs[0]->getFeSpace()->getMesh();
for(size_t i = 1; i < vecs.size(); i++)
{
if(vecs[i]->getFeSpace()->getMesh() != tmpMesh)
{