Commit 22132ee0 authored by Dave Moxey's avatar Dave Moxey
Browse files

Change structure, move many functions back into FieldIOXml

parent 34b0da28
......@@ -201,8 +201,9 @@ Array<OneD, int> ReadIDsForThisRank(Experiment& exp, FieldIOSharedPtr fio)
std::string infoFile = exp.dataSource + "/Info.xml";
fio->ImportMultiFldFileIDs(infoFile, fileNames, elementList,
fieldmetadatamap);
/// @todo unbreak this
// fio->ImportMultiFldFileIDs(infoFile, fileNames, elementList,
// fieldmetadatamap);
unsigned totalEls = 0;
std::vector<unsigned> elStartFile(elementList.size(), 0);
......
......@@ -33,7 +33,6 @@
//
////////////////////////////////////////////////////////////////////////////////
#include <boost/format.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>
#include <boost/date_time/posix_time/posix_time_io.hpp>
#include <boost/asio/ip/host_name.hpp>
......@@ -62,7 +61,6 @@
namespace ptime = boost::posix_time;
namespace ip = boost::asio::ip;
namespace berrc = boost::system::errc;
namespace Nektar
{
......@@ -223,205 +221,7 @@ namespace Nektar
{
}
/**
*
*/
void FieldIO::WriteMultiFldFileIDs(const std::string &outFile,
const std::vector<std::string> fileNames,
std::vector<std::vector<unsigned int> > &elementList,
const FieldMetaDataMap &fieldmetadatamap)
{
TiXmlDocument doc;
TiXmlDeclaration * decl = new TiXmlDeclaration("1.0", "utf-8", "");
doc.LinkEndChild(decl);
ASSERTL0(fileNames.size() == elementList.size(),
"Outfile names and list of elements ids does not match");
TiXmlElement * root = new TiXmlElement("NEKTAR");
doc.LinkEndChild(root);
AddInfoTag(root, fieldmetadatamap);
for (int t = 0; t < fileNames.size(); ++t)
{
if (elementList[t].size())
{
TiXmlElement * elemIDs = new TiXmlElement("Partition");
root->LinkEndChild(elemIDs);
elemIDs->SetAttribute("FileName", fileNames[t]);
string IDstring;
GenerateSeqString(elementList[t], IDstring);
elemIDs->LinkEndChild(new TiXmlText(IDstring));
}
}
doc.SaveFile(outFile);
}
void FieldIO::Import(const std::string& infilename,
std::vector<FieldDefinitionsSharedPtr> &fielddefs,
std::vector<std::vector<NekDouble> > &fielddata,
FieldMetaDataMap &fieldinfomap,
const Array<OneD, int> ElementIDs)
{
std::string infile = infilename;
fs::path pinfilename(infilename);
if (fs::is_directory(pinfilename)) // check to see that infile is a directory
{
fs::path infofile("Info.xml");
fs::path fullpath = pinfilename / infofile;
infile = PortablePath(fullpath);
std::vector < std::string > filenames;
std::vector < std::vector<unsigned int>
> elementIDs_OnPartitions;
ImportMultiFldFileIDs(infile, filenames,
elementIDs_OnPartitions, fieldinfomap);
// Load metadata
if (GetClassName() == "Xml")
{
ImportFieldMetaData(infile, fieldinfomap);
}
else
{
FieldIOSharedPtr infoReader =
GetFieldIOFactory().CreateInstance("Xml", m_comm, false);
infoReader->ImportFieldMetaData(infile, fieldinfomap);
}
if (ElementIDs == NullInt1DArray) //load all fields
{
for (int i = 0; i < filenames.size(); ++i)
{
fs::path pfilename(filenames[i]);
fullpath = pinfilename / pfilename;
string fname = PortablePath(fullpath);
v_ImportFile(fname, fielddefs, fielddata,
DataSourceSharedPtr());
}
}
else // only load relevant partitions
{
int i, j;
map<int, vector<int> > FileIDs;
map<int, vector<int> >::iterator it;
set<int> LoadFile;
for (i = 0; i < elementIDs_OnPartitions.size(); ++i)
{
for (j = 0; j < elementIDs_OnPartitions[i].size(); ++j)
{
FileIDs[elementIDs_OnPartitions[i][j]].push_back(i);
}
}
for (i = 0; i < ElementIDs.num_elements(); ++i)
{
it = FileIDs.find(ElementIDs[i]);
if (it != FileIDs.end())
{
for (j = 0; j < it->second.size(); ++j)
{
LoadFile.insert(it->second[j]);
}
}
}
set<int>::iterator iter;
for (iter = LoadFile.begin(); iter != LoadFile.end();
++iter)
{
fs::path pfilename(filenames[*iter]);
fullpath = pinfilename / pfilename;
string fname = PortablePath(fullpath);
v_ImportFile(fname, fielddefs, fielddata,
DataSourceSharedPtr());
}
}
}
else // serial format case
{
DataSourceSharedPtr dfile = ImportFieldMetaData(infile,
fieldinfomap);
v_ImportFile(infile, fielddefs, fielddata, dfile);
}
}
/**
*
*/
void FieldIO::ImportMultiFldFileIDs(const std::string &inFile,
std::vector<std::string> &fileNames,
std::vector<std::vector<unsigned int> > &elementList,
FieldMetaDataMap &fieldmetadatamap)
{
TiXmlDocument doc(inFile);
bool loadOkay = doc.LoadFile();
std::stringstream errstr;
errstr << "Unable to load file: " << inFile << std::endl;
errstr << "Reason: " << doc.ErrorDesc() << std::endl;
errstr << "Position: Line " << doc.ErrorRow() << ", Column "
<< doc.ErrorCol() << std::endl;
ASSERTL0(loadOkay, errstr.str());
// Handle on XML document
TiXmlHandle docHandle(&doc);
// Retrieve main NEKTAR tag - XML specification states one
// top-level element tag per file.
TiXmlElement* master = doc.FirstChildElement("NEKTAR");
ASSERTL0(master, "Unable to find NEKTAR tag in file.");
// Partition element tag name
std::string strPartition = "Partition";
// First attempt to get the first Partition element
TiXmlElement* fldfileIDs = master->FirstChildElement(
strPartition.c_str());
if (!fldfileIDs)
{
// If this files try previous name
strPartition = "MultipleFldFiles";
fldfileIDs = master->FirstChildElement("MultipleFldFiles");
}
ASSERTL0(fldfileIDs,
"Unable to find 'Partition' or 'MultipleFldFiles' tag "
"within nektar tag.");
while (fldfileIDs)
{
// Read file name of partition file
const char *attr = fldfileIDs->Attribute("FileName");
ASSERTL0(attr,
"'FileName' not provided as an attribute of '"
+ strPartition + "' tag.");
fileNames.push_back(std::string(attr));
const char* elementIDs = fldfileIDs->GetText();
ASSERTL0(elementIDs, "Element IDs not specified.");
std::string elementIDsStr(elementIDs);
std::vector<unsigned int> idvec;
ParseUtils::GenerateSeqVector(elementIDsStr.c_str(), idvec);
elementList.push_back(idvec);
fldfileIDs = fldfileIDs->NextSiblingElement(
strPartition.c_str());
}
}
/**
* \brief add information about provenance and fieldmetadata
......@@ -551,167 +351,6 @@ namespace Nektar
idString = idStringStream.str();
}
/**
*
*/
std::string FieldIO::SetUpOutput(const std::string outname)
{
ASSERTL0(!outname.empty(), "Empty path given to SetUpOutput()");
int nprocs = m_comm->GetSize();
int rank = m_comm->GetRank();
// Path to output: will be directory if parallel, normal file if
// serial.
fs::path specPath(outname);
fs::path fulloutname;
if (nprocs == 1)
{
fulloutname = specPath;
}
else
{
// Guess at filename that might belong to this process.
boost::format pad("P%1$07d.%2$s");
pad % m_comm->GetRank() % GetFileEnding();
// Generate full path name
fs::path poutfile(pad.str());
fulloutname = specPath / poutfile;
}
// Remove any existing file which is in the way
if (m_comm->RemoveExistingFiles())
{
if (m_sharedFilesystem)
{
// First, each process clears up its .fld file. This might
// or might not be there (we might have changed numbers of
// processors between runs, for example), but we can try
// anyway.
try
{
fs::remove_all(fulloutname);
}
catch (fs::filesystem_error& e)
{
ASSERTL0(e.code().value() == berrc::no_such_file_or_directory,
"Filesystem error: " + string(e.what()));
}
}
m_comm->Block();
// Now get rank 0 processor to tidy everything else up.
if (rank == 0 || !m_sharedFilesystem)
{
try
{
fs::remove_all(specPath);
}
catch (fs::filesystem_error& e)
{
ASSERTL0(e.code().value() == berrc::no_such_file_or_directory,
"Filesystem error: " + string(e.what()));
}
}
m_comm->Block();
}
// serial processing just add ending.
if (nprocs == 1)
{
cout << "Writing: " << specPath << endl;
return LibUtilities::PortablePath(specPath);
}
// Create the destination directory
try
{
if (rank == 0 || !m_sharedFilesystem)
{
fs::create_directory(specPath);
}
}
catch (fs::filesystem_error& e)
{
ASSERTL0(false, "Filesystem error: " + string(e.what()));
}
m_comm->Block();
// Return the full path to the partition for this process
return LibUtilities::PortablePath(fulloutname);
}
void FieldIO::SetUpFieldMetaData(
const string outname,
const vector< FieldDefinitionsSharedPtr > &fielddefs,
const FieldMetaDataMap &fieldmetadatamap)
{
ASSERTL0(!outname.empty(), "Empty path given to SetUpFieldMetaData()");
int nprocs = m_comm->GetSize();
int rank = m_comm->GetRank();
fs::path specPath (outname);
// Compute number of elements on this process and share with other
// processes. Also construct list of elements on this process from
// available vector of field definitions.
std::vector<unsigned int> elmtnums(nprocs, 0);
std::vector<unsigned int> idlist;
int i;
for (i = 0; i < fielddefs.size(); ++i)
{
elmtnums[rank] += fielddefs[i]->m_elementIDs.size();
idlist.insert(idlist.end(), fielddefs[i]->m_elementIDs.begin(),
fielddefs[i]->m_elementIDs.end());
}
m_comm->AllReduce(elmtnums, LibUtilities::ReduceMax);
// Collate per-process element lists on root process to generate
// the info file.
if (rank == 0)
{
std::vector < std::vector<unsigned int> > ElementIDs(nprocs);
// Populate the list of element ID lists from all processes
ElementIDs[0] = idlist;
for (i = 1; i < nprocs; ++i)
{
std::vector<unsigned int> tmp(elmtnums[i]);
m_comm->Recv(i, tmp);
ElementIDs[i] = tmp;
}
// Set up output names
std::vector < std::string > filenames;
for (int i = 0; i < nprocs; ++i)
{
boost::format pad("P%1$07d.%2$s");
pad % i % GetFileEnding();
filenames.push_back(pad.str());
}
// Write the Info.xml file
string infofile = LibUtilities::PortablePath(
specPath / fs::path("Info.xml"));
cout << "Writing: " << specPath << endl;
WriteMultiFldFileIDs(infofile, filenames, ElementIDs,
fieldmetadatamap);
}
else
{
// Send this process's ID list to the root process
m_comm->Send(0, idlist);
}
}
/**
*
*/
......
......@@ -193,7 +193,7 @@ namespace Nektar
/// Imports an FLD file.
LIB_UTILITIES_EXPORT
void Import(const std::string& infilename,
inline void Import(const std::string& infilename,
std::vector<FieldDefinitionsSharedPtr> &fielddefs,
std::vector<std::vector<NekDouble> > &fielddata =
NullVectorNekDoubleVector,
......@@ -211,19 +211,6 @@ namespace Nektar
std::vector<FieldDefinitionsSharedPtr> &fielddefs,
bool expChild) = 0;
LIB_UTILITIES_EXPORT
void WriteMultiFldFileIDs(const std::string &outfile,
const std::vector<std::string> fileNames,
std::vector<std::vector<unsigned int> > &elementList,
const FieldMetaDataMap &fieldinfomap =
NullFieldMetaDataMap);
LIB_UTILITIES_EXPORT
void ImportMultiFldFileIDs(const std::string &inFile,
std::vector<std::string> &fileNames,
std::vector<std::vector<unsigned int> > &elementList,
FieldMetaDataMap &fieldmetadatamap);
// Figure out what type of FLD file we have.
// Collective on comm.
static const std::string GetFileType(
......@@ -247,14 +234,6 @@ namespace Nektar
void GenerateSeqString(const std::vector<unsigned int> &elmtids,
std::string &idString);
LIB_UTILITIES_EXPORT
std::string SetUpOutput(const std::string outname);
LIB_UTILITIES_EXPORT void SetUpFieldMetaData(
const std::string outname,
const std::vector<FieldDefinitionsSharedPtr> &fielddefs,
const FieldMetaDataMap &fieldmetadatamap);
LIB_UTILITIES_EXPORT
int CheckFieldDefinition(
const FieldDefinitionsSharedPtr &fielddefs);
......@@ -270,11 +249,14 @@ namespace Nektar
std::vector<std::vector<NekDouble> > &fielddata,
const FieldMetaDataMap &fieldinfomap) = 0;
/// Imports an FLD file.
LIB_UTILITIES_EXPORT
virtual void v_ImportFile(const std::string& fname,
virtual void v_Import(const std::string& infilename,
std::vector<FieldDefinitionsSharedPtr> &fielddefs,
std::vector<std::vector<NekDouble> > &fielddata,
DataSourceSharedPtr dataSource) = 0;
std::vector<std::vector<NekDouble> > &fielddata =
NullVectorNekDoubleVector,
FieldMetaDataMap &fieldinfomap = NullFieldMetaDataMap,
const Array<OneD, int> ElementiDs = NullInt1DArray) = 0;
LIB_UTILITIES_EXPORT
virtual DataSourceSharedPtr v_ImportFieldMetaData(
......@@ -310,6 +292,16 @@ namespace Nektar
v_Write(outFile, fielddefs, fielddata, fieldinfomap);
}
inline void FieldIO::Import(
const std::string& infilename,
std::vector<FieldDefinitionsSharedPtr> &fielddefs,
std::vector<std::vector<NekDouble> > &fielddata,
FieldMetaDataMap &fieldinfomap,
const Array<OneD, int> ElementiDs)
{
v_Import(infilename, fielddefs, fielddata, fieldinfomap, ElementiDs);
}
inline DataSourceSharedPtr FieldIO::ImportFieldMetaData(
std::string filename, FieldMetaDataMap &fieldmetadatamap)
{
......
......@@ -548,12 +548,13 @@ namespace Nektar
// root group and HDF5 file are all closed automatically
void FieldIOHdf5::v_ImportFile(const std::string& infilename,
std::vector<FieldDefinitionsSharedPtr> &fielddefs,
std::vector<std::vector<NekDouble> > &fielddata,
DataSourceSharedPtr dataSource)
{
void FieldIOHdf5::v_Import(const std::string& infilename,
std::vector<FieldDefinitionsSharedPtr> &fielddefs,
std::vector<std::vector<NekDouble> > &fielddata,
FieldMetaDataMap &fieldinfomap,
const Array<OneD, int> ElementiDs)
{
std::stringstream prfx;
prfx << m_comm->GetRank() << ": FieldIOHdf5::v_ImportFile(): ";
double tm0 = 0.0, tm1 = 0.0;
......@@ -567,10 +568,7 @@ namespace Nektar
int rank = m_comm->GetRank();
if (!dataSource)
{
dataSource = H5DataSource::create(infilename);
}
DataSourceSharedPtr dataSource = H5DataSource::create(infilename);
// set properties for parallel file access (if we're in parallel)
////////////////////////////////////////////////////////////////////////////////////
......@@ -625,6 +623,7 @@ namespace Nektar
ASSERTL1(data_fspace, prfx.str() + "cannot open DATA filespace.");
////////////////////////////////////////////////////////////////////////////////////
cout << prfx.str() << "debug1" << endl;
// read the DECOMPOSITION dataset part for this rank
////////////////////////////////////////////////////////////////////////////////////
......@@ -636,6 +635,7 @@ namespace Nektar
decomps_dset->Read(decomps, decomps_fspace, readPL);
////////////////////////////////////////////////////////////////////////////////////
cout << prfx.str() << "debug2" << endl;
// read the INDEXES dataset part for this rank
////////////////////////////////////////////////////////////////////////////////////
imin = rank*MAX_IDXS;
......@@ -648,9 +648,11 @@ namespace Nektar
////////////////////////////////////////////////////////////////////////////////////
cout << prfx.str() << "debug3" << endl;
ImportFieldDefsHdf5(readPL, root, ids_dset, ids_fspace, ids_i, decomps, fielddefs);
if (fielddata != NullVectorNekDoubleVector)
{
cout << prfx.str() << "debug4" << endl;
ImportFieldData(readPL, data_dset, data_fspace, data_i, decomps, fielddefs, fielddata);
}
......
......@@ -109,10 +109,12 @@ namespace Nektar
NullFieldMetaDataMap);
LIB_UTILITIES_EXPORT
virtual void v_ImportFile(const std::string& infilename,
virtual void v_Import(const std::string& infilename,
std::vector<FieldDefinitionsSharedPtr> &fielddefs,
std::vector<std::vector<NekDouble> > &fielddata,
DataSourceSharedPtr dataSource);
std::vector<std::vector<NekDouble> > &fielddata =
NullVectorNekDoubleVector,
FieldMetaDataMap &fieldinfomap = NullFieldMetaDataMap,
const Array<OneD, int> ElementiDs = NullInt1DArray);
LIB_UTILITIES_EXPORT
virtual DataSourceSharedPtr v_ImportFieldMetaData(std::string filename,
......
......@@ -36,6 +36,8 @@
#include <LibUtilities/BasicUtils/FieldIOXml.h>
#include <LibUtilities/BasicUtils/CompressData.h>
#include <boost/format.hpp>
#include "zlib.h"
#ifdef NEKTAR_USE_MPI
......@@ -45,11 +47,12 @@
// Buffer size for zlib compression/decompression
#define CHUNK 16384
namespace berrc = boost::system::errc;
namespace Nektar
{
namespace LibUtilities
{
XmlDataSource::XmlDataSource(TiXmlDocument& doc) :
m_doc(&doc)
{
......@@ -67,6 +70,7 @@ namespace Nektar
<< m_doc->ErrorCol() << std::endl;
ASSERTL0(loadOkay, errstr.str());
}
XmlDataSource::~XmlDataSource()
{
delete m_doc;
......@@ -112,14 +116,14 @@ namespace Nektar
{
std::stringstream prfx;
prfx << m_comm->GetRank() << ": FieldIOXml::v_Write(): ";
double tm0 = 0.0, tm1 = 0.0;
double tm0 = 0.0, tm1 = 0.0;
if (0 == m_comm->GetRank())
{
cout << prfx.str() << "entering..." << endl;
tm0 = m_comm->Wtime();
}
// Check everything seems sensible
{
cout << prfx.str() << "entering..." << endl;
tm0 = m_comm->Wtime();
<