mirror of
https://github.com/Cantera/cantera.git
synced 2025-02-25 18:55:29 -06:00
[FileIO] Add 'overwrite' option to save routines
This commit is contained in:
parent
243fac5acf
commit
fe807d5986
@ -182,8 +182,10 @@ public:
|
||||
* @param fname Name of HDF container file
|
||||
* @param id Identifier of root location within the container file
|
||||
* @param desc Description
|
||||
* @param overwrite Force overwrite if id exists; optional (default=false)
|
||||
*/
|
||||
static void writeHeader(const string& fname, const string& id, const string& desc);
|
||||
static void writeHeader(const string& fname, const string& id, const string& desc,
|
||||
bool overwrite=false);
|
||||
|
||||
/*!
|
||||
* Write header data to AnyMap.
|
||||
@ -191,8 +193,10 @@ public:
|
||||
* @param root Root node of AnyMap structure
|
||||
* @param id Identifier of root location within the container file
|
||||
* @param desc Description
|
||||
* @param overwrite Force overwrite if id exists; optional (default=false)
|
||||
*/
|
||||
static void writeHeader(AnyMap& root, const string& id, const string& desc);
|
||||
static void writeHeader(AnyMap& root, const string& id, const string& desc,
|
||||
bool overwrite=false);
|
||||
|
||||
/*!
|
||||
* Write SolutionArray data to container file.
|
||||
@ -200,10 +204,11 @@ public:
|
||||
* @param fname Name of HDF container file
|
||||
* @param id Identifier of root location within the container file
|
||||
* @param sub Name identifier for the subgroup holding actual data
|
||||
* @param overwrite Force overwrite if sub exists; optional (default=false)
|
||||
* @param compression Compression level; optional (default=0; HDF only)
|
||||
*/
|
||||
void writeEntry(const string& fname, const string& id,
|
||||
const string& sub, int compression=0);
|
||||
void writeEntry(const string& fname, const string& id, const string& sub,
|
||||
bool overwrite=false, int compression=0);
|
||||
|
||||
/*!
|
||||
* Write SolutionArray data to AnyMap.
|
||||
@ -211,8 +216,10 @@ public:
|
||||
* @param root Root node of AnyMap structure
|
||||
* @param id Identifier of root location within the container file
|
||||
* @param sub Name identifier for the subgroup holding actual data
|
||||
* @param overwrite Force overwrite if sub exists; optional (default=false)
|
||||
*/
|
||||
void writeEntry(AnyMap& root, const string& id, const string& sub);
|
||||
void writeEntry(AnyMap& root, const string& id, const string& sub,
|
||||
bool overwrite=false);
|
||||
|
||||
/*!
|
||||
* Save current SolutionArray and header to a container file.
|
||||
@ -221,11 +228,11 @@ public:
|
||||
* @param id Identifier of root location within the container file
|
||||
* @param sub Name identifier for the subgroup holding actual data
|
||||
* @param desc Custom comment describing the dataset to be stored
|
||||
* @param overwrite Force overwrite if sub exists; optional (default=false)
|
||||
* @param compression Compression level; optional (default=0; HDF only)
|
||||
*/
|
||||
string save(const string& fname, const string& id,
|
||||
const string& sub,
|
||||
const string& desc, int compression=0);
|
||||
string save(const string& fname, const string& id, const string& sub,
|
||||
const string& desc, bool overwrite=false, int compression=0);
|
||||
|
||||
/*!
|
||||
* Read header data from container file.
|
||||
|
@ -53,11 +53,18 @@ public:
|
||||
bool hasGroup(const string& id) const;
|
||||
|
||||
//! Check whether path location exists.
|
||||
//! If the file has write access, create location; otherwise exceptions are thrown.
|
||||
//! If the location does not exist, an exception is thrown unless the *permissive*
|
||||
//! flag is set; in this case, the method attempts to create a new location if the
|
||||
//! file is accessed in write mode.
|
||||
//! @param id storage location within file
|
||||
//! @param permissive if true, do not raise exceptions
|
||||
//! @param permissive if true, do not raise exceptions (default=false)
|
||||
//! @returns boolean indicating whether id is pre-existing
|
||||
bool checkGroup(const string& id, bool permissive=false);
|
||||
|
||||
//! Delete group
|
||||
//! @param id storage location within file
|
||||
void deleteGroup(const string& id);
|
||||
|
||||
//! Retrieve contents of file from a specified location
|
||||
//! @param id storage location within file
|
||||
//! @returns pair containing size and list of entry names of stored data set
|
||||
|
@ -134,10 +134,12 @@ public:
|
||||
* @param id Identifier of solution within the container file
|
||||
* @param desc Description of the solution
|
||||
* @param loglevel Level of diagnostic output
|
||||
* @param overwrite Force overwrite if name exists; optional (default=`False`)
|
||||
* @param compression Compression level (optional; HDF only)
|
||||
*/
|
||||
void save(const std::string& fname, const std::string& id,
|
||||
const std::string& desc, int loglevel=1, int compression=0);
|
||||
const std::string& desc, int loglevel=1,
|
||||
bool overwrite=false, int compression=0);
|
||||
|
||||
/**
|
||||
* Save the residual of the current solution to a container file.
|
||||
@ -145,9 +147,12 @@ public:
|
||||
* @param id Identifier of solution within the container file
|
||||
* @param desc Description of the solution
|
||||
* @param loglevel Level of diagnostic output
|
||||
* @param overwrite Force overwrite if name exists; optional (default=`False`)
|
||||
* @param compression Compression level (optional; HDF only)
|
||||
*/
|
||||
void saveResidual(const std::string& fname, const std::string& id,
|
||||
const std::string& desc, int loglevel=1);
|
||||
const std::string& desc, int loglevel=1,
|
||||
bool overwrite=false, int compression=0);
|
||||
|
||||
/**
|
||||
* Initialize the solution with a previously-saved solution.
|
||||
|
@ -71,7 +71,7 @@ SolutionArray::SolutionArray(const SolutionArray& other,
|
||||
, m_active(selected)
|
||||
{
|
||||
for (auto loc : m_active) {
|
||||
if (loc < 0 || loc >= m_dataSize) {
|
||||
if (loc < 0 || loc >= (int)m_dataSize) {
|
||||
IndexError("SolutionArray::SolutionArray", "indices", loc, m_dataSize);
|
||||
}
|
||||
}
|
||||
@ -123,7 +123,7 @@ void SolutionArray::reset()
|
||||
size_t nState = m_sol->thermo()->stateSize();
|
||||
vector<double> state(nState);
|
||||
m_sol->thermo()->saveState(state); // thermo contains current state
|
||||
for (int k = 0; k < m_size; ++k) {
|
||||
for (size_t k = 0; k < m_size; ++k) {
|
||||
std::copy(state.begin(), state.end(), m_data->data() + m_active[k] * m_stride);
|
||||
}
|
||||
for (auto& [key, extra] : *m_extra) {
|
||||
@ -415,7 +415,7 @@ void SolutionArray::setLoc(size_t loc, bool restore)
|
||||
"Both current and buffered indices are invalid.");
|
||||
}
|
||||
return;
|
||||
} else if (m_active[loc] == m_loc) {
|
||||
} else if (m_active[loc] == (int)m_loc) {
|
||||
return;
|
||||
} else if (loc >= m_size) {
|
||||
throw IndexError("SolutionArray::setLoc", "indices", loc, m_size - 1);
|
||||
@ -584,22 +584,33 @@ AnyMap& openField(AnyMap& root, const string& id)
|
||||
}
|
||||
|
||||
void SolutionArray::writeHeader(const string& fname, const string& id,
|
||||
const string& desc)
|
||||
const string& desc, bool overwrite)
|
||||
{
|
||||
Storage file(fname, true);
|
||||
file.checkGroup(id, true);
|
||||
if (file.checkGroup(id, true)) {
|
||||
if (!overwrite) {
|
||||
throw CanteraError("SolutionArray::writeHeader",
|
||||
"Group id '{}' exists; use 'overwrite' argument to overwrite.", id);
|
||||
}
|
||||
file.deleteGroup(id);
|
||||
file.checkGroup(id, true);
|
||||
}
|
||||
file.writeAttributes(id, preamble(desc));
|
||||
}
|
||||
|
||||
void SolutionArray::writeHeader(AnyMap& root, const string& id,
|
||||
const string& desc)
|
||||
const string& desc, bool overwrite)
|
||||
{
|
||||
AnyMap& data = openField(root, id);
|
||||
if (!data.empty() && !overwrite) {
|
||||
throw CanteraError("SolutionArray::writeHeader",
|
||||
"Field id '{}' exists; use 'overwrite' argument to overwrite.", id);
|
||||
}
|
||||
data.update(preamble(desc));
|
||||
}
|
||||
|
||||
void SolutionArray::writeEntry(const string& fname, const string& id,
|
||||
const string& sub, int compression)
|
||||
void SolutionArray::writeEntry(const string& fname, const string& id, const string& sub,
|
||||
bool overwrite, int compression)
|
||||
{
|
||||
if (id == "") {
|
||||
throw CanteraError("SolutionArray::writeEntry",
|
||||
@ -619,7 +630,14 @@ void SolutionArray::writeEntry(const string& fname, const string& id,
|
||||
} else {
|
||||
path += "/data";
|
||||
}
|
||||
file.checkGroup(path, true);
|
||||
if (file.checkGroup(path, true)) {
|
||||
if (!overwrite) {
|
||||
throw CanteraError("SolutionArray::writeEntry",
|
||||
"Group id '{}' exists; use 'overwrite' argument to overwrite.", id);
|
||||
}
|
||||
file.deleteGroup(path);
|
||||
file.checkGroup(path, true);
|
||||
}
|
||||
file.writeAttributes(path, m_meta);
|
||||
AnyMap more;
|
||||
if (apiNdim() == 1) {
|
||||
@ -665,8 +683,8 @@ void SolutionArray::writeEntry(const string& fname, const string& id,
|
||||
}
|
||||
}
|
||||
|
||||
void SolutionArray::writeEntry(AnyMap& root,
|
||||
const string& id, const string& sub)
|
||||
void SolutionArray::writeEntry(AnyMap& root, const string& id, const string& sub,
|
||||
bool overwrite)
|
||||
{
|
||||
if (id == "") {
|
||||
throw CanteraError("SolutionArray::writeEntry",
|
||||
@ -684,6 +702,10 @@ void SolutionArray::writeEntry(AnyMap& root,
|
||||
}
|
||||
AnyMap& data = openField(root, path);
|
||||
bool preexisting = !data.empty();
|
||||
if (preexisting && !overwrite) {
|
||||
throw CanteraError("SolutionArray::writeEntry",
|
||||
"Field id '{}' exists; use 'overwrite' argument to overwrite.", id);
|
||||
}
|
||||
if (apiNdim() == 1) {
|
||||
data["size"] = int(m_dataSize);
|
||||
} else {
|
||||
@ -759,9 +781,8 @@ void SolutionArray::append(const vector<double>& state, const AnyMap& extra)
|
||||
}
|
||||
}
|
||||
|
||||
string SolutionArray::save(const string& fname, const string& id,
|
||||
const string& sub, const string& desc,
|
||||
int compression)
|
||||
string SolutionArray::save(const string& fname, const string& id, const string& sub,
|
||||
const string& desc, bool overwrite, int compression)
|
||||
{
|
||||
if (m_size < m_dataSize) {
|
||||
throw NotImplementedError("SolutionArray::save",
|
||||
@ -770,8 +791,8 @@ string SolutionArray::save(const string& fname, const string& id,
|
||||
size_t dot = fname.find_last_of(".");
|
||||
string extension = (dot != npos) ? toLowerCopy(fname.substr(dot + 1)) : "";
|
||||
if (extension == "h5" || extension == "hdf" || extension == "hdf5") {
|
||||
writeEntry(fname, id, sub, compression);
|
||||
writeHeader(fname, id, desc);
|
||||
writeHeader(fname, id, desc, overwrite);
|
||||
writeEntry(fname, id, sub, true, compression);
|
||||
return id;
|
||||
}
|
||||
if (extension == "yaml" || extension == "yml") {
|
||||
@ -780,8 +801,8 @@ string SolutionArray::save(const string& fname, const string& id,
|
||||
if (std::ifstream(fname).good()) {
|
||||
data = AnyMap::fromYamlFile(fname);
|
||||
}
|
||||
writeEntry(data, id, sub);
|
||||
writeHeader(data, id, desc);
|
||||
writeHeader(data, id, desc, overwrite);
|
||||
writeEntry(data, id, sub, true);
|
||||
|
||||
// Write the output file and remove the now-outdated cached file
|
||||
std::ofstream out(fname);
|
||||
|
@ -122,7 +122,7 @@ bool Storage::checkGroupWrite(const string& id, bool permissive)
|
||||
"Specified group with id '{}' does not exist.", id);
|
||||
}
|
||||
m_file->createGroup(id);
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
if (m_file->getObjectType(id) != h5::ObjectType::Group) {
|
||||
throw CanteraError("Storage::checkGroupWrite",
|
||||
@ -153,6 +153,17 @@ bool Storage::checkGroup(const string& id, bool permissive)
|
||||
}
|
||||
}
|
||||
|
||||
void Storage::deleteGroup(const string& id)
|
||||
{
|
||||
try {
|
||||
m_file->unlink(id);
|
||||
} catch (const std::exception& err) {
|
||||
// convert HighFive exception
|
||||
throw CanteraError("Storage::deleteGroup",
|
||||
"Encountered exception while deleting group '{}':\n{}", id, err.what());
|
||||
}
|
||||
}
|
||||
|
||||
std::pair<size_t, set<string>> Storage::contents(const string& id) const
|
||||
{
|
||||
try {
|
||||
@ -581,6 +592,12 @@ bool Storage::checkGroup(const string& id, bool permissive)
|
||||
"Saving to HDF requires HighFive installation.");
|
||||
}
|
||||
|
||||
void Storage::deleteGroup(const string& id)
|
||||
{
|
||||
throw CanteraError("Storage::deleteGroup",
|
||||
"Saving to HDF requires HighFive installation.");
|
||||
}
|
||||
|
||||
std::pair<size_t, set<string>> Storage::contents(const string& id) const
|
||||
{
|
||||
throw CanteraError("Storage::contents",
|
||||
|
@ -115,16 +115,16 @@ void Sim1D::setProfile(size_t dom, size_t comp,
|
||||
}
|
||||
|
||||
void Sim1D::save(const std::string& fname, const std::string& id,
|
||||
const std::string& desc, int loglevel, int compression)
|
||||
const std::string& desc, int loglevel, bool overwrite, int compression)
|
||||
{
|
||||
size_t dot = fname.find_last_of(".");
|
||||
string extension = (dot != npos) ? toLowerCopy(fname.substr(dot+1)) : "";
|
||||
if (extension == "h5" || extension == "hdf" || extension == "hdf5") {
|
||||
SolutionArray::writeHeader(fname, id, desc, overwrite);
|
||||
for (auto dom : m_dom) {
|
||||
auto arr = dom->asArray(m_x.data() + dom->loc());
|
||||
arr->writeEntry(fname, id, dom->id(), compression);
|
||||
arr->writeEntry(fname, id, dom->id(), overwrite, compression);
|
||||
}
|
||||
SolutionArray::writeHeader(fname, id, desc);
|
||||
if (loglevel > 0) {
|
||||
writelog("Solution saved to file '{}' as group '{}'.\n", fname, id);
|
||||
}
|
||||
@ -136,11 +136,11 @@ void Sim1D::save(const std::string& fname, const std::string& id,
|
||||
if (std::ifstream(fname).good()) {
|
||||
data = AnyMap::fromYamlFile(fname);
|
||||
}
|
||||
SolutionArray::writeHeader(data, id, desc);
|
||||
SolutionArray::writeHeader(data, id, desc, overwrite);
|
||||
|
||||
for (auto dom : m_dom) {
|
||||
auto arr = dom->asArray(m_x.data() + dom->loc());
|
||||
arr->writeEntry(data, id, dom->id());
|
||||
arr->writeEntry(data, id, dom->id(), overwrite);
|
||||
}
|
||||
|
||||
// Write the output file and remove the now-outdated cached file
|
||||
@ -152,22 +152,24 @@ void Sim1D::save(const std::string& fname, const std::string& id,
|
||||
}
|
||||
return;
|
||||
}
|
||||
throw CanteraError("Sim1D::save",
|
||||
"Unsupported file format '{}'", extension);
|
||||
throw CanteraError("Sim1D::save", "Unsupported file format '{}'.", extension);
|
||||
}
|
||||
|
||||
void Sim1D::saveResidual(const std::string& fname, const std::string& id,
|
||||
const std::string& desc, int loglevel)
|
||||
const std::string& desc,
|
||||
int loglevel, bool overwrite, int compression)
|
||||
{
|
||||
vector_fp res(m_x.size(), -999);
|
||||
OneDim::eval(npos, &m_x[0], &res[0], 0.0);
|
||||
// Temporarily put the residual into m_x, since this is the vector that the save()
|
||||
// function reads.
|
||||
std::swap(res, m_x);
|
||||
save(fname, id, desc, loglevel);
|
||||
save(fname, id, desc, loglevel, overwrite, compression);
|
||||
std::swap(res, m_x);
|
||||
}
|
||||
|
||||
namespace { // restrict scope of helper function to local translation unit
|
||||
|
||||
//! convert data format used by Python h5py export (Cantera < 3.0)
|
||||
AnyMap legacyH5(shared_ptr<SolutionArray> arr, const AnyMap& header={})
|
||||
{
|
||||
@ -251,6 +253,8 @@ AnyMap legacyH5(shared_ptr<SolutionArray> arr, const AnyMap& header={})
|
||||
return out;
|
||||
}
|
||||
|
||||
} // end unnamed namespace
|
||||
|
||||
AnyMap Sim1D::restore(const std::string& fname, const std::string& id,
|
||||
int loglevel)
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user