/*
* Copyright 2009-2019 The VOTCA Development Team (http://www.votca.org)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
#pragma once
#ifndef VOTCA_XTP_CHECKPOINT_TABLE_H
#define VOTCA_XTP_CHECKPOINT_TABLE_H
#include <H5Cpp.h>
#include <cstddef>
#include <cstring>
#include <iostream>
#include <sstream>
#include <stdexcept>
#include <string>
#include <vector>
#include <votca/xtp/checkpoint_utils.h>
#define CPT_MEM_FROM_STRUCT(m, s) HOFFSET(s, m)
#define CPT_MEMBER(m, s) HOFFSET(s, m)
namespace votca {
namespace xtp {
using namespace checkpoint_utils;
class CptTable {
public:
CptTable() = default;
CptTable(const std::string& name, const std::size_t& rowSize,
const std::size_t& nRows)
: _name(name),
_rowStructure(rowSize),
_nRows(nRows),
_props(H5::DSetCreatPropList(H5::DSetCreatPropList::DEFAULT)){};
CptTable(const std::string& name, const std::size_t& rowSize,
const CptLoc& loc)
: _name(name), _loc(loc), _inited(true), _rowStructure(rowSize) {
_dataset = _loc.openDataSet(_name);
_dp = _dataset.getSpace();
hsize_t dims[2];
_dp.getSimpleExtentDims(dims, nullptr);
_nRows = dims[0];
}
template <typename U>
typename std::enable_if<std::is_fundamental<U>::value>::type addCol(
const U&, const std::string& name, const size_t& offset) {
_rowStructure.insertMember(name, offset, *InferDataType<U>::get());
}
void addCol(const std::string&, const std::string& name,
const size_t& offset) {
_rowStructure.insertMember(name, offset,
*InferDataType<std::string>::get());
}
void addCol(const char*, const std::string& name, const size_t& offset) {
H5::DataType fixedWidth(H5T_STRING, MaxStringSize);
_rowStructure.insertMember(name, offset, fixedWidth);
}
void initialize(const CptLoc& loc, bool compact) {
// create the dataspace...
if (_inited) {
std::stringstream message;
message << "Checkpoint tables cannot be reinitialized. " << _name
<< " has either already been initialized or already exists."
<< std::endl;
throw std::runtime_error(message.str());
}
_dims[0] = _nRows;
_dims[1] = 1;
_dp = H5::DataSpace(2, _dims);
_loc = loc;
if (compact) {
_props.setLayout(H5D_layout_t::H5D_COMPACT);
}
try {
_dataset = _loc.createDataSet(_name.c_str(), _rowStructure, _dp, _props);
} catch (H5::Exception&) {
std::stringstream message;
message << "Could not write " << _name << " from " << _loc.getFileName();
throw std::runtime_error(message.str());
}
_inited = true;
}
void write(void* buffer, const std::size_t& startIdx,
const std::size_t& endIdx) {
if (!_inited) {
std::stringstream message;
message << "Checkpoint table uninitialized." << std::endl;
throw std::runtime_error(message.str());
}
hsize_t s = (hsize_t)(startIdx);
hsize_t e = (hsize_t)(endIdx);
hsize_t l = e - s;
hsize_t fStart[2] = {s, 0};
hsize_t fCount[2] = {l, 1};
hsize_t mStart[2] = {s, 0};
hsize_t mCount[2] = {l, 1};
hsize_t mDim[2] = {l, 1};
H5::DataSpace mspace(2, mDim);
_dp.selectHyperslab(H5S_SELECT_SET, fCount, fStart);
mspace.selectHyperslab(H5S_SELECT_SET, mCount, mStart);
try {
_dataset.write(buffer, _rowStructure, mspace, _dp);
} catch (H5::Exception&) {
std::stringstream message;
message << "Could not write " << _name << " from " << _loc.getFileName();
throw std::runtime_error(message.str());
}
}
void writeToRow(void* buffer, const std::size_t idx) {
write(buffer, idx, idx + 1);
}
template <typename T>
void write(std::vector<T>& dataVec) {
write(dataVec.data(), 0, dataVec.size());
}
void read(void* buffer, const std::size_t& startIdx,
const std::size_t& endIdx) {
if (!_inited) {
std::stringstream message;
message << "Checkpoint table uninitialized." << std::endl;
throw std::runtime_error(message.str());
}
hsize_t s = (hsize_t)(startIdx);
hsize_t e = (hsize_t)(endIdx);
hsize_t l = e - s;
hsize_t fStart[2] = {s, 0};
hsize_t fCount[2] = {l, 1};
hsize_t mStart[2] = {s, 0};
hsize_t mCount[2] = {l, 1};
hsize_t mDim[2] = {l, 1};
H5::DataSpace mspace(2, mDim);
_dp.selectHyperslab(H5S_SELECT_SET, fCount, fStart);
mspace.selectHyperslab(H5S_SELECT_SET, mCount, mStart);
try {
_dataset.read(buffer, _rowStructure, mspace, _dp);
} catch (H5::Exception&) {
std::stringstream message;
message << "Could not read " << _name << " from " << _loc.getFileName();
throw std::runtime_error(message.str());
}
}
void readFromRow(void* buffer, const std::size_t& idx) {
read(buffer, idx, idx + 1);
}
template <typename T>
void read(std::vector<T>& dataVec) {
read(dataVec.data(), 0, dataVec.size());
}
std::size_t numRows() { return _nRows; }
static const std::size_t MaxStringSize = 512;
private:
std::string _name;
CptLoc _loc;
bool _inited = false;
H5::CompType _rowStructure;
std::size_t _nRows;
hsize_t _dims[2];
H5::DataSpace _dp;
H5::DataSet _dataset;
H5::DSetCreatPropList _props;
};
} // namespace xtp
} // namespace votca
#endif // VOTCA_XTP_CHECKPOINT_TABLE_H