mirror of
https://github.com/triqs/dft_tools
synced 2024-12-25 13:53:40 +01:00
Cleaning h5 interface
This commit is contained in:
parent
3a31077d51
commit
e32602180c
@ -18,7 +18,6 @@
|
|||||||
* TRIQS. If not, see <http://www.gnu.org/licenses/>.
|
* TRIQS. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*
|
*
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
#ifndef TRIQS_ARRAYS_H5_H
|
#pragma once
|
||||||
#define TRIQS_ARRAYS_H5_H
|
|
||||||
#include "./h5/simple_read_write.hpp"
|
#include "./h5/simple_read_write.hpp"
|
||||||
#endif
|
#include "./h5/array_of_non_basic.hpp"
|
||||||
|
111
triqs/arrays/h5/array_of_non_basic.hpp
Normal file
111
triqs/arrays/h5/array_of_non_basic.hpp
Normal file
@ -0,0 +1,111 @@
|
|||||||
|
/*******************************************************************************
|
||||||
|
*
|
||||||
|
* TRIQS: a Toolbox for Research in Interacting Quantum Systems
|
||||||
|
*
|
||||||
|
* Copyright (C) 2011-2013 by O. Parcollet
|
||||||
|
*
|
||||||
|
* TRIQS is free software: you can redistribute it and/or modify it under the
|
||||||
|
* terms of the GNU General Public License as published by the Free Software
|
||||||
|
* Foundation, either version 3 of the License, or (at your option) any later
|
||||||
|
* version.
|
||||||
|
*
|
||||||
|
* TRIQS is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||||
|
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||||
|
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||||
|
* details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License along with
|
||||||
|
* TRIQS. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
******************************************************************************/
|
||||||
|
#pragma once
|
||||||
|
#include <triqs/arrays/array.hpp>
|
||||||
|
#include <triqs/arrays/vector.hpp>
|
||||||
|
#include <triqs/h5.hpp>
|
||||||
|
#include "../cache.hpp"
|
||||||
|
|
||||||
|
namespace triqs {
|
||||||
|
namespace arrays {
|
||||||
|
|
||||||
|
// details for generic save/read of arrays.
|
||||||
|
namespace h5_impl {
|
||||||
|
inline std::string _h5_name() { return ""; }
|
||||||
|
|
||||||
|
template <typename T0, typename... Ts> std::string _h5_name(T0 const& t0, Ts const&... ts) {
|
||||||
|
auto r = std::to_string(t0);
|
||||||
|
auto r1 = _h5_name(ts...);
|
||||||
|
if (r1 != "") r += "_" + r1;
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifndef __cpp_generic_lambdas
|
||||||
|
template <typename ArrayType> struct _save_lambda {
|
||||||
|
ArrayType const& a;
|
||||||
|
h5::group g;
|
||||||
|
template <typename... Is> void operator()(Is const&... is) const { h5_write(g, _h5_name(is...), a(is...)); }
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename ArrayType> struct _load_lambda {
|
||||||
|
ArrayType& a;
|
||||||
|
h5::group g;
|
||||||
|
template <typename... Is> void operator()(Is const&... is) { h5_read(g, _h5_name(is...), a(is...)); }
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
} // details
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Write an array or a view into an hdf5 file when type is not fundamental
|
||||||
|
* ArrayType The type of the array/matrix/vector, etc..
|
||||||
|
* g The h5 group
|
||||||
|
* name The name of the hdf5 array in the file/group where the stack will be stored
|
||||||
|
* A The array to be stored
|
||||||
|
* The HDF5 exceptions will be caught and rethrown as TRIQS_RUNTIME_ERROR (with a full stackstrace, cf triqs doc).
|
||||||
|
*/
|
||||||
|
template <typename ArrayType>
|
||||||
|
std::c14::enable_if_t<is_amv_value_or_view_class<ArrayType>::value && !has_scalar_or_string_value_type<ArrayType>::value>
|
||||||
|
h5_write(h5::group gr, std::string name, ArrayType const& a) {
|
||||||
|
if (a.is_empty()) TRIQS_RUNTIME_ERROR << " Can not save an empty array into hdf5";
|
||||||
|
auto gr2 = gr.create_group(name);
|
||||||
|
gr2.write_triqs_hdf5_data_scheme(a);
|
||||||
|
// save the shape
|
||||||
|
array<int, 1> sha(ArrayType::rank);
|
||||||
|
for (int u = 0; u < ArrayType::rank; ++u) sha(u) = a.shape()[u];
|
||||||
|
h5_write(gr2, "shape", sha);
|
||||||
|
#ifndef __cpp_generic_lambdas
|
||||||
|
foreach(a, h5_impl::_save_lambda<ArrayType>{a, gr2});
|
||||||
|
#else
|
||||||
|
foreach(a, [&](auto... is) { h5_write(gr2, h5_impl::_h5_name(is...), a(is...)); });
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Read an array or a view from an hdf5 file when type is not fundamental
|
||||||
|
* ArrayType The type of the array/matrix/vector, etc..
|
||||||
|
* g The h5 group
|
||||||
|
* name The name of the hdf5 array in the file/group where the stack will be stored
|
||||||
|
* A The array to be stored
|
||||||
|
* The HDF5 exceptions will be caught and rethrown as TRIQS_RUNTIME_ERROR (with a full stackstrace, cf triqs doc).
|
||||||
|
*/
|
||||||
|
template <typename ArrayType>
|
||||||
|
std::c14::enable_if_t<is_amv_value_or_view_class<ArrayType>::value && !has_scalar_or_string_value_type<ArrayType>::value>
|
||||||
|
h5_read(h5::group gr, std::string name, ArrayType& a) {
|
||||||
|
static_assert(!std::is_const<ArrayType>::value, "Can not read in const object");
|
||||||
|
auto gr2 = gr.open_group(name);
|
||||||
|
// TODO checking scheme...
|
||||||
|
// load the shape
|
||||||
|
auto sha2 = a.shape();
|
||||||
|
array<int, 1> sha;
|
||||||
|
h5_read(gr2, "shape", sha);
|
||||||
|
if (first_dim(sha) != sha2.size())
|
||||||
|
TRIQS_RUNTIME_ERROR << " array<array<...>> load : rank mismatch. Expected " << sha2.size()<< " Got " << first_dim(sha);
|
||||||
|
for (int u = 0; u < sha2.size(); ++u) sha2[u] = sha(u);
|
||||||
|
if (a.shape() != sha2) a.resize(sha2);
|
||||||
|
#ifndef __cpp_generic_lambdas
|
||||||
|
foreach(a, h5_impl::_load_lambda<ArrayType>{a, gr2});
|
||||||
|
#else
|
||||||
|
foreach(a, [&](auto... is) { h5_read(gr2, h5_impl::_h5_name(is...), a(is...)); });
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -27,6 +27,18 @@
|
|||||||
namespace triqs {
|
namespace triqs {
|
||||||
namespace arrays {
|
namespace arrays {
|
||||||
|
|
||||||
|
// to be cleaned
|
||||||
|
namespace h5_impl {
|
||||||
|
template <typename A> void* __get_array_data_ptr(A& x) { return h5::get_data_ptr(&(x.storage()[0])); }
|
||||||
|
|
||||||
|
H5::DataSpace data_space_impl(array_stride_info info, bool is_complex);
|
||||||
|
|
||||||
|
template <typename ArrayType> H5::DataSpace data_space(ArrayType const& A) {
|
||||||
|
if (!A.indexmap().is_contiguous()) TRIQS_RUNTIME_ERROR << " h5 : internal error : array not contiguous";
|
||||||
|
return data_space_impl(array_stride_info{A}, triqs::is_complex<typename ArrayType::value_type>::value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// The implementation class
|
/// The implementation class
|
||||||
template <typename T, int R> class array_stack_impl {
|
template <typename T, int R> class array_stack_impl {
|
||||||
static const size_t dim = R;
|
static const size_t dim = R;
|
||||||
|
150
triqs/arrays/h5/simple_read_write.cpp
Normal file
150
triqs/arrays/h5/simple_read_write.cpp
Normal file
@ -0,0 +1,150 @@
|
|||||||
|
/*******************************************************************************
|
||||||
|
*
|
||||||
|
* TRIQS: a Toolbox for Research in Interacting Quantum Systems
|
||||||
|
*
|
||||||
|
* Copyright (C) 2011-2014 by O. Parcollet
|
||||||
|
*
|
||||||
|
* TRIQS is free software: you can redistribute it and/or modify it under the
|
||||||
|
* terms of the GNU General Public License as published by the Free Software
|
||||||
|
* Foundation, either version 3 of the License, or (at your option) any later
|
||||||
|
* version.
|
||||||
|
*
|
||||||
|
* TRIQS is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||||
|
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||||
|
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||||
|
* details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License along with
|
||||||
|
* TRIQS. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
******************************************************************************/
|
||||||
|
#include "./simple_read_write.hpp"
|
||||||
|
|
||||||
|
using dcomplex = std::complex<double>;
|
||||||
|
namespace triqs {
|
||||||
|
namespace arrays {
|
||||||
|
namespace h5_impl {
|
||||||
|
|
||||||
|
// the dataspace corresponding to the array. Contiguous data only...
|
||||||
|
H5::DataSpace data_space_impl(array_stride_info info, bool is_complex) {
|
||||||
|
hsize_t L[info.R], S[info.R];
|
||||||
|
for (int u = 0; u < info.R; ++u) {
|
||||||
|
if (info.strides[u] <= 0) TRIQS_RUNTIME_ERROR << " negative strides not permitted in h5";
|
||||||
|
S[u] = 1;
|
||||||
|
L[u] = info.lengths[u];
|
||||||
|
}
|
||||||
|
return h5::dataspace_from_LS(info.R, is_complex, L, L, S);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// --------------------------- WRITE ---------------------------------------------
|
||||||
|
|
||||||
|
template <typename T> void write_array_impl(h5::group g, std::string const& name, const T* start, array_stride_info info) {
|
||||||
|
static_assert(!std::is_base_of<std::string, T>::value, " Not implemented"); // 1d is below
|
||||||
|
bool is_complex = triqs::is_complex<T>::value;
|
||||||
|
try {
|
||||||
|
H5::DataSet ds = g.create_dataset(name, h5::data_type_file<T>(), data_space_impl(info, is_complex));
|
||||||
|
ds.write(h5::get_data_ptr(start), h5::data_type_memory<T>(), data_space_impl(info, is_complex));
|
||||||
|
// if complex, to be python compatible, we add the __complex__ attribute
|
||||||
|
if (is_complex) h5::write_string_attribute(&ds, "__complex__", "1");
|
||||||
|
}
|
||||||
|
TRIQS_ARRAYS_H5_CATCH_EXCEPTION;
|
||||||
|
}
|
||||||
|
|
||||||
|
template void write_array_impl<int>(h5::group g, std::string const& name, const int* start, array_stride_info info);
|
||||||
|
template void write_array_impl<long>(h5::group g, std::string const& name, const long* start, array_stride_info info);
|
||||||
|
template void write_array_impl<double>(h5::group g, std::string const& name, const double* start, array_stride_info info);
|
||||||
|
template void write_array_impl<dcomplex>(h5::group g, std::string const& name, const dcomplex* start, array_stride_info info);
|
||||||
|
|
||||||
|
|
||||||
|
// overload : special treatment for arrays of strings (one dimension only).
|
||||||
|
void write_array(h5::group g, std::string const& name, vector_const_view<std::string> V) {
|
||||||
|
std::vector<std::string> tmp(V.size());
|
||||||
|
std::copy(begin(V), end(V), begin(tmp));
|
||||||
|
h5_write(g, name, tmp);
|
||||||
|
}
|
||||||
|
|
||||||
|
void write_array(h5::group g, std::string const& name, array_const_view<std::string, 1> V) {
|
||||||
|
std::vector<std::string> tmp(first_dim(V));
|
||||||
|
std::copy(begin(V), end(V), begin(tmp));
|
||||||
|
h5_write(g, name, tmp);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// --------------------------- READ ---------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
|
/* template <typename ArrayType1> void read_array(h5::group g, std::string const& name, ArrayType1&& A, bool C_reorder = true) {
|
||||||
|
typedef typename std::remove_reference<ArrayType1>::type ArrayType;
|
||||||
|
static_assert(!std::is_base_of<std::string, typename ArrayType::value_type>::value, " Not implemented"); // 1d is below
|
||||||
|
try {
|
||||||
|
H5::DataSet ds = g.open_dataset(name);
|
||||||
|
H5::DataSpace dataspace = ds.getSpace();
|
||||||
|
static const unsigned int Rank = ArrayType::rank + (triqs::is_complex<typename ArrayType::value_type>::value ? 1 : 0);
|
||||||
|
int rank = dataspace.getSimpleExtentNdims();
|
||||||
|
if (rank != Rank)
|
||||||
|
TRIQS_RUNTIME_ERROR << "triqs::array::h5::read. Rank mismatch : the array has rank = " << Rank
|
||||||
|
<< " while the array stored in the hdf5 file has rank = " << rank;
|
||||||
|
mini_vector<hsize_t, Rank> dims_out;
|
||||||
|
dataspace.getSimpleExtentDims(&dims_out[0], NULL);
|
||||||
|
mini_vector<size_t, ArrayType::rank> d2;
|
||||||
|
for (size_t u = 0; u < ArrayType::rank; ++u) d2[u] = dims_out[u];
|
||||||
|
resize_or_check(A, d2);
|
||||||
|
if (C_reorder) {
|
||||||
|
read_array(g, name, make_cache(A).view(), false);
|
||||||
|
//read_array(g, name, cache<ArrayType, typename ArrayType::regular_type>(A).view(), false);
|
||||||
|
} else
|
||||||
|
ds.read(__get_array_data_ptr(A), h5::data_type_memory<typename ArrayType::value_type>(), data_space(A), dataspace);
|
||||||
|
}
|
||||||
|
TRIQS_ARRAYS_H5_CATCH_EXCEPTION;
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
std::vector<size_t> get_array_lengths(int R, h5::group g, std::string const& name, bool is_complex) {
|
||||||
|
try {
|
||||||
|
H5::DataSet ds = g.open_dataset(name);
|
||||||
|
H5::DataSpace dataspace = ds.getSpace();
|
||||||
|
int Rank = R + (is_complex ? 1 : 0);
|
||||||
|
int rank = dataspace.getSimpleExtentNdims();
|
||||||
|
if (rank != Rank)
|
||||||
|
TRIQS_RUNTIME_ERROR << "triqs::array::h5::read. Rank mismatch : the array has rank = " << Rank
|
||||||
|
<< " while the array stored in the hdf5 file has rank = " << rank;
|
||||||
|
std::vector<size_t> d2(R);
|
||||||
|
hsize_t dims_out[rank];
|
||||||
|
dataspace.getSimpleExtentDims(&dims_out[0], NULL);
|
||||||
|
for (size_t u = 0; u < R; ++u) d2[u] = dims_out[u];
|
||||||
|
return d2;
|
||||||
|
}
|
||||||
|
TRIQS_ARRAYS_H5_CATCH_EXCEPTION;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T> void read_array_impl(h5::group g, std::string const& name, T* start, array_stride_info info) {
|
||||||
|
static_assert(!std::is_base_of<std::string, T>::value, " Not implemented"); // 1d is below
|
||||||
|
bool is_complex = triqs::is_complex<T>::value;
|
||||||
|
try {
|
||||||
|
H5::DataSet ds = g.open_dataset(name);
|
||||||
|
H5::DataSpace dataspace = ds.getSpace();
|
||||||
|
ds.read(h5::get_data_ptr(start), h5::data_type_memory<T>(), data_space_impl(info, is_complex), dataspace);
|
||||||
|
}
|
||||||
|
TRIQS_ARRAYS_H5_CATCH_EXCEPTION;
|
||||||
|
}
|
||||||
|
|
||||||
|
template void read_array_impl<int>(h5::group g, std::string const& name, int* start, array_stride_info info);
|
||||||
|
template void read_array_impl<long>(h5::group g, std::string const& name, long* start, array_stride_info info);
|
||||||
|
template void read_array_impl<double>(h5::group g, std::string const& name, double* start, array_stride_info info);
|
||||||
|
template void read_array_impl<dcomplex>(h5::group g, std::string const& name, dcomplex* start, array_stride_info info);
|
||||||
|
|
||||||
|
void read_array(h5::group g, std::string const& name, arrays::vector<std::string>& V) {
|
||||||
|
std::vector<std::string> tmp;
|
||||||
|
h5_read(g, name, tmp);
|
||||||
|
V.resize(tmp.size());
|
||||||
|
std::copy(begin(tmp), end(tmp), begin(V));
|
||||||
|
}
|
||||||
|
|
||||||
|
// I can not use the generic code, just because the resize of the array take a shape, not a size_t as std::vector and vector
|
||||||
|
void read_array(h5::group f, std::string const& name, arrays::array<std::string, 1>& V) {
|
||||||
|
arrays::vector<std::string> res;
|
||||||
|
read_array(f, name, res);
|
||||||
|
V = res;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -18,8 +18,7 @@
|
|||||||
* TRIQS. If not, see <http://www.gnu.org/licenses/>.
|
* TRIQS. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*
|
*
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
#ifndef TRIQS_ARRAYS_H5_LOWLEVEL_H
|
#pragma once
|
||||||
#define TRIQS_ARRAYS_H5_LOWLEVEL_H
|
|
||||||
#include <triqs/arrays/array.hpp>
|
#include <triqs/arrays/array.hpp>
|
||||||
#include <triqs/arrays/vector.hpp>
|
#include <triqs/arrays/vector.hpp>
|
||||||
#include <triqs/h5.hpp>
|
#include <triqs/h5.hpp>
|
||||||
@ -29,22 +28,16 @@ namespace triqs {
|
|||||||
namespace arrays {
|
namespace arrays {
|
||||||
namespace h5_impl {
|
namespace h5_impl {
|
||||||
|
|
||||||
template <typename A> const void* __get_array_data_cptr(A const& a) { return h5::get_data_ptr(&(a.storage()[0])); }
|
struct array_stride_info {
|
||||||
template <typename A> void* __get_array_data_ptr(A& x) { return h5::get_data_ptr(&(x.storage()[0])); }
|
int R;
|
||||||
|
size_t const* lengths;
|
||||||
// the dataspace corresponding to the array. Contiguous data only...
|
long const* strides;
|
||||||
template <typename ArrayType> H5::DataSpace data_space(ArrayType const& A) {
|
template<typename A> explicit array_stride_info(A && a) {
|
||||||
if (!A.indexmap().is_contiguous()) TRIQS_RUNTIME_ERROR << " h5 : internal error : array not contiguous";
|
R = std::c14::decay_t<A>::rank;
|
||||||
static const unsigned int R = ArrayType::rank;
|
lengths = a.indexmap().domain().lengths().ptr();
|
||||||
mini_vector<hsize_t, R> S;
|
strides = a.indexmap().strides().ptr();
|
||||||
auto const& S1(A.indexmap().strides());
|
|
||||||
for (int u = 0; u < R; ++u) {
|
|
||||||
if (S1[u] <= 0) TRIQS_RUNTIME_ERROR << " negative strides not permitted in h5";
|
|
||||||
S[u] = 1;
|
|
||||||
}
|
|
||||||
static const bool is_complex = triqs::is_complex<typename ArrayType::value_type>::value;
|
|
||||||
return h5::dataspace_from_LS<R, is_complex>(A.indexmap().domain().lengths(), A.indexmap().domain().lengths(), S);
|
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
|
||||||
/******************** resize or check the size ****************************************************/
|
/******************** resize or check the size ****************************************************/
|
||||||
|
|
||||||
@ -60,92 +53,44 @@ namespace arrays {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*********************************** WRITE array ****************************************************************/
|
/*********************************** WRITE array ****************************************************************/
|
||||||
/*
|
|
||||||
* Write an array or a view into an hdf5 file
|
template <typename T> void write_array_impl(h5::group g, std::string const& name, const T* start, array_stride_info info);
|
||||||
*
|
|
||||||
* f The h5 file or group of type H5::H5File or H5::Group
|
|
||||||
* name The name of the hdf5 array in the file/group where the stack will be stored
|
|
||||||
* A The array to be stored
|
|
||||||
* C_reorder bool If true [default] the data will be stored in C order in the hdf5, hence making a temporary
|
|
||||||
* cache of the data to reorder them in memory.
|
|
||||||
* If false, the array is stored as it [if you know what you are doing]
|
|
||||||
* The HDF5 exceptions will be caught and rethrown as TRIQS_RUNTIME_ERROR (with a full stackstrace, cf triqs doc).
|
|
||||||
*/
|
|
||||||
template <typename T, int R>
|
|
||||||
void write_array_impl(h5::group g, std::string const& name, array_const_view<T, R> A, bool C_reorder) {
|
|
||||||
static_assert(!std::is_base_of<std::string, T>::value, " Not implemented"); // 1d is below
|
|
||||||
if (C_reorder) {
|
|
||||||
write_array_impl(g, name, make_const_cache(A).view(), false);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
H5::DataSet ds = g.create_dataset(name, h5::data_type_file<T>(), data_space(A));
|
|
||||||
ds.write(__get_array_data_cptr(A), h5::data_type_memory<T>(), data_space(A));
|
|
||||||
// if complex, to be python compatible, we add the __complex__ attribute
|
|
||||||
if (triqs::is_complex<T>::value) h5::write_string_attribute(&ds, "__complex__", "1");
|
|
||||||
}
|
|
||||||
TRIQS_ARRAYS_H5_CATCH_EXCEPTION;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename A> void write_array(h5::group g, std::string const& name, A const& a, bool C_reorder = true) {
|
template <typename A> void write_array(h5::group g, std::string const& name, A const& a, bool C_reorder = true) {
|
||||||
write_array_impl(g, name, typename A::const_view_type{a}, C_reorder);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*********************************** READ array ****************************************************************/
|
|
||||||
/*
|
|
||||||
* Read an array or a view from an hdf5 file
|
|
||||||
* ArrayType The type of the array/matrix/vector, etc..
|
|
||||||
* f The h5 file or group of type H5::H5File or H5::Group
|
|
||||||
* name The name of the hdf5 array in the file/group where the stack will be stored
|
|
||||||
* A The array to be stored
|
|
||||||
* C_reorder bool If true [default] the data will be stored in C order in the hdf5, hence making a temporary
|
|
||||||
* cache of the data to reorder them in memory. If false, the array is stored as it [if you know what you are doing]
|
|
||||||
* The HDF5 exceptions will be caught and rethrown as TRIQS_RUNTIME_ERROR (with a full stackstrace, cf triqs doc).
|
|
||||||
*/
|
|
||||||
template <typename ArrayType1> void read_array(h5::group g, std::string const& name, ArrayType1&& A, bool C_reorder = true) {
|
|
||||||
typedef typename std::remove_reference<ArrayType1>::type ArrayType;
|
|
||||||
static_assert(!std::is_base_of<std::string, typename ArrayType::value_type>::value, " Not implemented"); // 1d is below
|
|
||||||
try {
|
|
||||||
H5::DataSet ds = g.open_dataset(name);
|
|
||||||
H5::DataSpace dataspace = ds.getSpace();
|
|
||||||
static const unsigned int Rank = ArrayType::rank + (triqs::is_complex<typename ArrayType::value_type>::value ? 1 : 0);
|
|
||||||
int rank = dataspace.getSimpleExtentNdims();
|
|
||||||
if (rank != Rank)
|
|
||||||
TRIQS_RUNTIME_ERROR << "triqs::array::h5::read. Rank mismatch : the array has rank = " << Rank
|
|
||||||
<< " while the array stored in the hdf5 file has rank = " << rank;
|
|
||||||
mini_vector<hsize_t, Rank> dims_out;
|
|
||||||
dataspace.getSimpleExtentDims(&dims_out[0], NULL);
|
|
||||||
mini_vector<size_t, ArrayType::rank> d2;
|
|
||||||
for (size_t u = 0; u < ArrayType::rank; ++u) d2[u] = dims_out[u];
|
|
||||||
resize_or_check(A, d2);
|
|
||||||
if (C_reorder) {
|
if (C_reorder) {
|
||||||
read_array(g, name, make_cache(A).view(), false);
|
auto b = make_const_cache(a).view();
|
||||||
//read_array(g, name, cache<ArrayType, typename ArrayType::regular_type>(A).view(), false);
|
write_array_impl(g, name, b.data_start(), array_stride_info{b});
|
||||||
} else
|
} else
|
||||||
ds.read(__get_array_data_ptr(A), h5::data_type_memory<typename ArrayType::value_type>(), data_space(A), dataspace);
|
write_array_impl(g, name, a.data_start(), array_stride_info{a});
|
||||||
}
|
|
||||||
TRIQS_ARRAYS_H5_CATCH_EXCEPTION;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// overload : special treatment for arrays of strings (one dimension only).
|
// overload : special treatment for arrays of strings (one dimension only).
|
||||||
inline void write_array(h5::group f, std::string const& name, vector_const_view<std::string> V) {
|
void write_array(h5::group g, std::string const& name, vector_const_view<std::string> V);
|
||||||
h5::detail::write_1darray_vector_of_string_impl(f, name, V);
|
void write_array(h5::group g, std::string const& name, array_const_view<std::string, 1> V);
|
||||||
|
|
||||||
|
/*********************************** READ array ****************************************************************/
|
||||||
|
|
||||||
|
std::vector<size_t> get_array_lengths(int R, h5::group g, std::string const& name, bool is_complex);
|
||||||
|
template <typename T> void read_array_impl(h5::group g, std::string const& name, T* start, array_stride_info info);
|
||||||
|
|
||||||
|
template <typename A> void read_array(h5::group g, std::string const& name, A&& a, bool C_reorder = true) {
|
||||||
|
resize_or_check(a, get_array_lengths(a.rank, g, name, triqs::is_complex<typename std::c14::decay_t<A>::value_type>::value));
|
||||||
|
if (C_reorder) {
|
||||||
|
{
|
||||||
|
// read_array(g, name, make_cache(a).view(), false);
|
||||||
|
// return ;
|
||||||
|
auto b = make_cache(a);
|
||||||
|
// auto b = make_cache(a).view();
|
||||||
|
read_array_impl(g, name, b.view().data_start(), array_stride_info{b.view()});
|
||||||
|
// read_array_impl(g, name, b.data_start(), array_stride_info{b});
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
read_array_impl(g, name, a.data_start(), array_stride_info{a});
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void write_array(h5::group f, std::string const& name, array_const_view<std::string, 1> V) {
|
// overload : special treatment for arrays of strings (one dimension only).
|
||||||
write_array(f, name, vector_const_view<std::string>(V));
|
void read_array(h5::group g, std::string const& name, arrays::vector<std::string>& V);
|
||||||
}
|
void read_array(h5::group f, std::string const& name, arrays::array<std::string, 1>& V);
|
||||||
|
|
||||||
inline void read_array(h5::group f, std::string const& name, arrays::vector<std::string>& V) {
|
|
||||||
h5::detail::read_1darray_vector_of_string_impl(f, name, V);
|
|
||||||
}
|
|
||||||
|
|
||||||
// I can not use the generic code, just because the resize of the array take a shape, not a size_t as std::vector and vector
|
|
||||||
inline void read_array(h5::group f, std::string const& name, arrays::array<std::string, 1>& V) {
|
|
||||||
arrays::vector<std::string> res;
|
|
||||||
read_array(f, name, res);
|
|
||||||
V = res;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace h5_impl
|
} // namespace h5_impl
|
||||||
|
|
||||||
@ -162,9 +107,7 @@ namespace arrays {
|
|||||||
template <typename ArrayType>
|
template <typename ArrayType>
|
||||||
TYPE_ENABLE_IFC(std::string, is_amv_value_or_view_class<ArrayType>::value) get_triqs_hdf5_data_scheme(ArrayType const&) {
|
TYPE_ENABLE_IFC(std::string, is_amv_value_or_view_class<ArrayType>::value) get_triqs_hdf5_data_scheme(ArrayType const&) {
|
||||||
using triqs::get_triqs_hdf5_data_scheme; // for the basic types, not found by ADL
|
using triqs::get_triqs_hdf5_data_scheme; // for the basic types, not found by ADL
|
||||||
std::stringstream fs;
|
return "array<" + get_triqs_hdf5_data_scheme(typename ArrayType::value_type()) + "," + std::to_string(ArrayType::rank) + ">";
|
||||||
fs << "array<" << get_triqs_hdf5_data_scheme(typename ArrayType::value_type()) << "," << ArrayType::rank << ">";
|
|
||||||
return fs.str();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -196,86 +139,5 @@ namespace arrays {
|
|||||||
h5_impl::write_array(g, name, array_const_view<typename ArrayType::value_type, ArrayType::rank>(A));
|
h5_impl::write_array(g, name, array_const_view<typename ArrayType::value_type, ArrayType::rank>(A));
|
||||||
}
|
}
|
||||||
|
|
||||||
// details for generic save/read of arrays.
|
}}
|
||||||
namespace h5_impl {
|
|
||||||
inline std::string _h5_name() { return ""; }
|
|
||||||
|
|
||||||
template <typename T0, typename... Ts> std::string _h5_name(T0 const& t0, Ts const&... ts) {
|
|
||||||
auto r = std::to_string(t0);
|
|
||||||
auto r1 = _h5_name(ts...);
|
|
||||||
if (r1 != "") r += "_" + r1;
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifndef __cpp_generic_lambdas
|
|
||||||
template <typename ArrayType> struct _save_lambda {
|
|
||||||
ArrayType const& a;
|
|
||||||
h5::group g;
|
|
||||||
template <typename... Is> void operator()(Is const&... is) const { h5_write(g, _h5_name(is...), a(is...)); }
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename ArrayType> struct _load_lambda {
|
|
||||||
ArrayType& a;
|
|
||||||
h5::group g;
|
|
||||||
template <typename... Is> void operator()(Is const&... is) { h5_read(g, _h5_name(is...), a(is...)); }
|
|
||||||
};
|
|
||||||
#endif
|
|
||||||
} // details
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Write an array or a view into an hdf5 file when type is not fundamental
|
|
||||||
* ArrayType The type of the array/matrix/vector, etc..
|
|
||||||
* g The h5 group
|
|
||||||
* name The name of the hdf5 array in the file/group where the stack will be stored
|
|
||||||
* A The array to be stored
|
|
||||||
* The HDF5 exceptions will be caught and rethrown as TRIQS_RUNTIME_ERROR (with a full stackstrace, cf triqs doc).
|
|
||||||
*/
|
|
||||||
template <typename ArrayType>
|
|
||||||
std::c14::enable_if_t<is_amv_value_or_view_class<ArrayType>::value && !has_scalar_or_string_value_type<ArrayType>::value>
|
|
||||||
h5_write(h5::group gr, std::string name, ArrayType const& a) {
|
|
||||||
if (a.is_empty()) TRIQS_RUNTIME_ERROR << " Can not save an empty array into hdf5";
|
|
||||||
auto gr2 = gr.create_group(name);
|
|
||||||
gr2.write_triqs_hdf5_data_scheme(a);
|
|
||||||
// save the shape
|
|
||||||
array<int, 1> sha(ArrayType::rank);
|
|
||||||
for (int u = 0; u < ArrayType::rank; ++u) sha(u) = a.shape()[u];
|
|
||||||
h5_write(gr2, "shape", sha);
|
|
||||||
#ifndef __cpp_generic_lambdas
|
|
||||||
foreach(a, h5_impl::_save_lambda<ArrayType>{a, gr2});
|
|
||||||
#else
|
|
||||||
foreach(a, [&](auto... is) { h5_write(gr2, h5_impl::_h5_name(is...), a(is...)); });
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Read an array or a view from an hdf5 file when type is not fundamental
|
|
||||||
* ArrayType The type of the array/matrix/vector, etc..
|
|
||||||
* g The h5 group
|
|
||||||
* name The name of the hdf5 array in the file/group where the stack will be stored
|
|
||||||
* A The array to be stored
|
|
||||||
* The HDF5 exceptions will be caught and rethrown as TRIQS_RUNTIME_ERROR (with a full stackstrace, cf triqs doc).
|
|
||||||
*/
|
|
||||||
template <typename ArrayType>
|
|
||||||
std::c14::enable_if_t<is_amv_value_or_view_class<ArrayType>::value && !has_scalar_or_string_value_type<ArrayType>::value>
|
|
||||||
h5_read(h5::group gr, std::string name, ArrayType& a) {
|
|
||||||
static_assert(!std::is_const<ArrayType>::value, "Can not read in const object");
|
|
||||||
auto gr2 = gr.open_group(name);
|
|
||||||
// TODO checking scheme...
|
|
||||||
// load the shape
|
|
||||||
auto sha2 = a.shape();
|
|
||||||
array<int, 1> sha;
|
|
||||||
h5_read(gr2, "shape", sha);
|
|
||||||
if (first_dim(sha) != sha2.size())
|
|
||||||
TRIQS_RUNTIME_ERROR << " array<array<...>> load : rank mismatch. Expected " << sha2.size()<< " Got " << first_dim(sha);
|
|
||||||
for (int u = 0; u < sha2.size(); ++u) sha2[u] = sha(u);
|
|
||||||
if (a.shape() != sha2) a.resize(sha2);
|
|
||||||
#ifndef __cpp_generic_lambdas
|
|
||||||
foreach(a, h5_impl::_load_lambda<ArrayType>{a, gr2});
|
|
||||||
#else
|
|
||||||
foreach(a, [&](auto... is) { h5_read(gr2, h5_impl::_h5_name(is...), a(is...)); });
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
122
triqs/arrays/python/numpy_extractor.cpp
Normal file
122
triqs/arrays/python/numpy_extractor.cpp
Normal file
@ -0,0 +1,122 @@
|
|||||||
|
/*******************************************************************************
|
||||||
|
*
|
||||||
|
* TRIQS: a Toolbox for Research in Interacting Quantum Systems
|
||||||
|
*
|
||||||
|
* Copyright (C) 2011 by O. Parcollet
|
||||||
|
*
|
||||||
|
* TRIQS is free software: you can redistribute it and/or modify it under the
|
||||||
|
* terms of the GNU General Public License as published by the Free Software
|
||||||
|
* Foundation, either version 3 of the License, or (at your option) any later
|
||||||
|
* version.
|
||||||
|
*
|
||||||
|
* TRIQS is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||||
|
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||||
|
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||||
|
* details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License along with
|
||||||
|
* TRIQS. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
******************************************************************************/
|
||||||
|
#include "../impl/common.hpp"
|
||||||
|
#include "../impl/traits.hpp"
|
||||||
|
#include "../impl/flags.hpp"
|
||||||
|
#include "../../utility/mini_vector.hpp"
|
||||||
|
#include "./numpy_extractor.hpp"
|
||||||
|
#ifdef TRIQS_WITH_PYTHON_SUPPORT
|
||||||
|
|
||||||
|
namespace triqs { namespace arrays { namespace numpy_interface {
|
||||||
|
|
||||||
|
|
||||||
|
PyObject * numpy_extractor_impl ( PyObject * X, bool allow_copy, std::string type_name,
|
||||||
|
int elementsType, int rank, size_t * lengths, std::ptrdiff_t * strides, size_t size_of_ValueType) {
|
||||||
|
|
||||||
|
PyObject * numpy_obj;
|
||||||
|
|
||||||
|
if (X==NULL) TRIQS_RUNTIME_ERROR<<"numpy interface : the python object is NULL !";
|
||||||
|
if (_import_array()!=0) TRIQS_RUNTIME_ERROR <<"Internal Error in importing numpy";
|
||||||
|
|
||||||
|
static const char * error_msg = " A deep copy of the object would be necessary while views are supposed to guarantee to present a *view* of the python data.\n";
|
||||||
|
|
||||||
|
if (!allow_copy) {
|
||||||
|
if (!PyArray_Check(X)) throw copy_exception () << error_msg<<" Indeed the object was not even an array !\n";
|
||||||
|
if ( elementsType != PyArray_TYPE((PyArrayObject*)X))
|
||||||
|
throw copy_exception () << error_msg<<" The deep copy is caused by a type mismatch of the elements. Expected "<< type_name<< " and found XXX \n";
|
||||||
|
PyArrayObject *arr = (PyArrayObject *)X;
|
||||||
|
#ifdef TRIQS_NUMPY_VERSION_LT_17
|
||||||
|
if ( arr->nd != rank) throw copy_exception () << error_msg<<" Rank mismatch . numpy array is of rank "<< arr->nd << "while you ask for rank "<< rank<<". \n";
|
||||||
|
#else
|
||||||
|
if ( PyArray_NDIM(arr) != rank) throw copy_exception () << error_msg<<" Rank mismatch . numpy array is of rank "<< PyArray_NDIM(arr) << "while you ask for rank "<< rank<<". \n";
|
||||||
|
#endif
|
||||||
|
numpy_obj = X; Py_INCREF(X);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// From X, we ask the numpy library to make a numpy, and of the correct type.
|
||||||
|
// This handles automatically the cases where :
|
||||||
|
// - we have list, or list of list/tuple
|
||||||
|
// - the numpy type is not the one we want.
|
||||||
|
// - adjust the dimension if needed
|
||||||
|
// If X is an array :
|
||||||
|
// - if Order is same, don't change it
|
||||||
|
// - else impose it (may provoque a copy).
|
||||||
|
// if X is not array :
|
||||||
|
// - Order = FortranOrder or SameOrder - > Fortran order otherwise C
|
||||||
|
|
||||||
|
//bool ForceCast = false;// Unless FORCECAST is present in flags, this call will generate an error if the data type cannot be safely obtained from the object.
|
||||||
|
int flags = 0; //(ForceCast ? NPY_FORCECAST : 0) ;// do NOT force a copy | (make_copy ? NPY_ENSURECOPY : 0);
|
||||||
|
if (!(PyArray_Check(X) ))
|
||||||
|
//flags |= ( IndexMapType::traversal_order == indexmaps::mem_layout::c_order(rank) ? NPY_C_CONTIGUOUS : NPY_F_CONTIGUOUS); //impose mem order
|
||||||
|
#ifdef TRIQS_NUMPY_VERSION_LT_17
|
||||||
|
flags |= (NPY_C_CONTIGUOUS); //impose mem order
|
||||||
|
#else
|
||||||
|
flags |= (NPY_ARRAY_C_CONTIGUOUS); //impose mem order
|
||||||
|
#endif
|
||||||
|
numpy_obj= PyArray_FromAny(X,PyArray_DescrFromType(elementsType), rank,rank, flags , NULL );
|
||||||
|
|
||||||
|
// do several checks
|
||||||
|
if (!numpy_obj) {// The convertion of X to a numpy has failed !
|
||||||
|
if (PyErr_Occurred()) {
|
||||||
|
//PyErr_Print();
|
||||||
|
PyErr_Clear();
|
||||||
|
}
|
||||||
|
TRIQS_RUNTIME_ERROR<<"numpy interface : the python object is not convertible to a numpy. ";
|
||||||
|
}
|
||||||
|
assert (PyArray_Check(numpy_obj)); assert((numpy_obj->ob_refcnt==1) || ((numpy_obj ==X)));
|
||||||
|
|
||||||
|
PyArrayObject *arr_obj;
|
||||||
|
arr_obj = (PyArrayObject *)numpy_obj;
|
||||||
|
try {
|
||||||
|
#ifdef TRIQS_NUMPY_VERSION_LT_17
|
||||||
|
if (arr_obj->nd!=rank) TRIQS_RUNTIME_ERROR<<"numpy interface : internal error : dimensions do not match";
|
||||||
|
if (arr_obj->descr->type_num != elementsType)
|
||||||
|
TRIQS_RUNTIME_ERROR<<"numpy interface : internal error : incorrect type of element :" <<arr_obj->descr->type_num <<" vs "<<elementsType;
|
||||||
|
#else
|
||||||
|
if ( PyArray_NDIM(arr_obj) !=rank) TRIQS_RUNTIME_ERROR<<"numpy interface : internal error : dimensions do not match";
|
||||||
|
if ( PyArray_DESCR(arr_obj)->type_num != elementsType)
|
||||||
|
TRIQS_RUNTIME_ERROR<<"numpy interface : internal error : incorrect type of element :" <<PyArray_DESCR(arr_obj)->type_num <<" vs "<<elementsType;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
catch(...) { Py_DECREF(numpy_obj); throw;} // make sure that in case of problem, the reference counting of python is still ok...
|
||||||
|
}
|
||||||
|
|
||||||
|
// extract strides and lengths
|
||||||
|
PyArrayObject *arr_obj;
|
||||||
|
arr_obj = (PyArrayObject *)numpy_obj;
|
||||||
|
#ifdef TRIQS_NUMPY_VERSION_LT_17
|
||||||
|
const size_t dim =arr_obj->nd; // we know that dim == rank
|
||||||
|
for (size_t i=0; i< dim ; ++i) {
|
||||||
|
lengths[i] = size_t(arr_obj-> dimensions[i]);
|
||||||
|
strides[i] = std::ptrdiff_t(arr_obj-> strides[i])/ size_of_ValueType;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
const size_t dim = PyArray_NDIM(arr_obj); // we know that dim == rank
|
||||||
|
for (size_t i=0; i< dim ; ++i) {
|
||||||
|
lengths[i] = size_t( PyArray_DIMS(arr_obj)[i]);
|
||||||
|
strides[i] = std::ptrdiff_t( PyArray_STRIDES(arr_obj)[i])/ size_of_ValueType;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return numpy_obj;
|
||||||
|
}
|
||||||
|
}}}
|
||||||
|
#endif
|
@ -21,13 +21,15 @@
|
|||||||
#ifndef TRIQS_ARRAYS_NUMPY_EXTRACTOR_H
|
#ifndef TRIQS_ARRAYS_NUMPY_EXTRACTOR_H
|
||||||
#define TRIQS_ARRAYS_NUMPY_EXTRACTOR_H
|
#define TRIQS_ARRAYS_NUMPY_EXTRACTOR_H
|
||||||
|
|
||||||
#ifdef TRIQS_WITH_PYTHON_SUPPORT
|
|
||||||
#include "../storages/shared_block.hpp"
|
#include "../storages/shared_block.hpp"
|
||||||
#include "triqs/utility/exceptions.hpp"
|
#include "triqs/utility/exceptions.hpp"
|
||||||
|
#ifdef TRIQS_WITH_PYTHON_SUPPORT
|
||||||
#include "numpy/arrayobject.h"
|
#include "numpy/arrayobject.h"
|
||||||
|
|
||||||
namespace triqs { namespace arrays { namespace numpy_interface {
|
namespace triqs { namespace arrays { namespace numpy_interface {
|
||||||
|
|
||||||
|
using utility::mini_vector;
|
||||||
|
|
||||||
inline std::string object_to_string (PyObject * p) {
|
inline std::string object_to_string (PyObject * p) {
|
||||||
if (!PyString_Check(p)) TRIQS_RUNTIME_ERROR<<" Internal error, expected a python string .....";
|
if (!PyString_Check(p)) TRIQS_RUNTIME_ERROR<<" Internal error, expected a python string .....";
|
||||||
return PyString_AsString(p);
|
return PyString_AsString(p);
|
||||||
@ -58,97 +60,8 @@ namespace triqs { namespace arrays { namespace numpy_interface {
|
|||||||
struct copy_exception : public triqs::runtime_error {};
|
struct copy_exception : public triqs::runtime_error {};
|
||||||
|
|
||||||
// return a NEW (owned) reference
|
// return a NEW (owned) reference
|
||||||
//
|
PyObject * numpy_extractor_impl ( PyObject * X, bool allow_copy, std::string type_name,
|
||||||
inline PyObject * numpy_extractor_impl ( PyObject * X, bool allow_copy, std::string type_name,
|
int elementsType, int rank, size_t * lengths, std::ptrdiff_t * strides, size_t size_of_ValueType);
|
||||||
int elementsType, int rank, size_t * lengths, std::ptrdiff_t * strides, size_t size_of_ValueType) {
|
|
||||||
|
|
||||||
PyObject * numpy_obj;
|
|
||||||
|
|
||||||
if (X==NULL) TRIQS_RUNTIME_ERROR<<"numpy interface : the python object is NULL !";
|
|
||||||
if (_import_array()!=0) TRIQS_RUNTIME_ERROR <<"Internal Error in importing numpy";
|
|
||||||
|
|
||||||
static const char * error_msg = " A deep copy of the object would be necessary while views are supposed to guarantee to present a *view* of the python data.\n";
|
|
||||||
|
|
||||||
if (!allow_copy) {
|
|
||||||
if (!PyArray_Check(X)) throw copy_exception () << error_msg<<" Indeed the object was not even an array !\n";
|
|
||||||
if ( elementsType != PyArray_TYPE((PyArrayObject*)X))
|
|
||||||
throw copy_exception () << error_msg<<" The deep copy is caused by a type mismatch of the elements. Expected "<< type_name<< " and found XXX \n";
|
|
||||||
PyArrayObject *arr = (PyArrayObject *)X;
|
|
||||||
#ifdef TRIQS_NUMPY_VERSION_LT_17
|
|
||||||
if ( arr->nd != rank) throw copy_exception () << error_msg<<" Rank mismatch . numpy array is of rank "<< arr->nd << "while you ask for rank "<< rank<<". \n";
|
|
||||||
#else
|
|
||||||
if ( PyArray_NDIM(arr) != rank) throw copy_exception () << error_msg<<" Rank mismatch . numpy array is of rank "<< PyArray_NDIM(arr) << "while you ask for rank "<< rank<<". \n";
|
|
||||||
#endif
|
|
||||||
numpy_obj = X; Py_INCREF(X);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
// From X, we ask the numpy library to make a numpy, and of the correct type.
|
|
||||||
// This handles automatically the cases where :
|
|
||||||
// - we have list, or list of list/tuple
|
|
||||||
// - the numpy type is not the one we want.
|
|
||||||
// - adjust the dimension if needed
|
|
||||||
// If X is an array :
|
|
||||||
// - if Order is same, don't change it
|
|
||||||
// - else impose it (may provoque a copy).
|
|
||||||
// if X is not array :
|
|
||||||
// - Order = FortranOrder or SameOrder - > Fortran order otherwise C
|
|
||||||
|
|
||||||
//bool ForceCast = false;// Unless FORCECAST is present in flags, this call will generate an error if the data type cannot be safely obtained from the object.
|
|
||||||
int flags = 0; //(ForceCast ? NPY_FORCECAST : 0) ;// do NOT force a copy | (make_copy ? NPY_ENSURECOPY : 0);
|
|
||||||
if (!(PyArray_Check(X) ))
|
|
||||||
//flags |= ( IndexMapType::traversal_order == indexmaps::mem_layout::c_order(rank) ? NPY_C_CONTIGUOUS : NPY_F_CONTIGUOUS); //impose mem order
|
|
||||||
#ifdef TRIQS_NUMPY_VERSION_LT_17
|
|
||||||
flags |= (NPY_C_CONTIGUOUS); //impose mem order
|
|
||||||
#else
|
|
||||||
flags |= (NPY_ARRAY_C_CONTIGUOUS); //impose mem order
|
|
||||||
#endif
|
|
||||||
numpy_obj= PyArray_FromAny(X,PyArray_DescrFromType(elementsType), rank,rank, flags , NULL );
|
|
||||||
|
|
||||||
// do several checks
|
|
||||||
if (!numpy_obj) {// The convertion of X to a numpy has failed !
|
|
||||||
if (PyErr_Occurred()) {
|
|
||||||
//PyErr_Print();
|
|
||||||
PyErr_Clear();
|
|
||||||
}
|
|
||||||
TRIQS_RUNTIME_ERROR<<"numpy interface : the python object is not convertible to a numpy. ";
|
|
||||||
}
|
|
||||||
assert (PyArray_Check(numpy_obj)); assert((numpy_obj->ob_refcnt==1) || ((numpy_obj ==X)));
|
|
||||||
|
|
||||||
PyArrayObject *arr_obj;
|
|
||||||
arr_obj = (PyArrayObject *)numpy_obj;
|
|
||||||
try {
|
|
||||||
#ifdef TRIQS_NUMPY_VERSION_LT_17
|
|
||||||
if (arr_obj->nd!=rank) TRIQS_RUNTIME_ERROR<<"numpy interface : internal error : dimensions do not match";
|
|
||||||
if (arr_obj->descr->type_num != elementsType)
|
|
||||||
TRIQS_RUNTIME_ERROR<<"numpy interface : internal error : incorrect type of element :" <<arr_obj->descr->type_num <<" vs "<<elementsType;
|
|
||||||
#else
|
|
||||||
if ( PyArray_NDIM(arr_obj) !=rank) TRIQS_RUNTIME_ERROR<<"numpy interface : internal error : dimensions do not match";
|
|
||||||
if ( PyArray_DESCR(arr_obj)->type_num != elementsType)
|
|
||||||
TRIQS_RUNTIME_ERROR<<"numpy interface : internal error : incorrect type of element :" <<PyArray_DESCR(arr_obj)->type_num <<" vs "<<elementsType;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
catch(...) { Py_DECREF(numpy_obj); throw;} // make sure that in case of problem, the reference counting of python is still ok...
|
|
||||||
}
|
|
||||||
|
|
||||||
// extract strides and lengths
|
|
||||||
PyArrayObject *arr_obj;
|
|
||||||
arr_obj = (PyArrayObject *)numpy_obj;
|
|
||||||
#ifdef TRIQS_NUMPY_VERSION_LT_17
|
|
||||||
const size_t dim =arr_obj->nd; // we know that dim == rank
|
|
||||||
for (size_t i=0; i< dim ; ++i) {
|
|
||||||
lengths[i] = size_t(arr_obj-> dimensions[i]);
|
|
||||||
strides[i] = std::ptrdiff_t(arr_obj-> strides[i])/ size_of_ValueType;
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
const size_t dim = PyArray_NDIM(arr_obj); // we know that dim == rank
|
|
||||||
for (size_t i=0; i< dim ; ++i) {
|
|
||||||
lengths[i] = size_t( PyArray_DIMS(arr_obj)[i]);
|
|
||||||
strides[i] = std::ptrdiff_t( PyArray_STRIDES(arr_obj)[i])/ size_of_ValueType;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return numpy_obj;
|
|
||||||
}
|
|
||||||
|
|
||||||
// a little template class
|
// a little template class
|
||||||
template<typename IndexMapType, typename ValueType > struct numpy_extractor {
|
template<typename IndexMapType, typename ValueType > struct numpy_extractor {
|
||||||
|
@ -129,7 +129,7 @@ namespace gfs {
|
|||||||
h5_write(gr, "max", ((Fermion ? 1 : 0) + 2 * m.size()) * M_PI / beta);
|
h5_write(gr, "max", ((Fermion ? 1 : 0) + 2 * m.size()) * M_PI / beta);
|
||||||
h5_write(gr, "kind", 2);
|
h5_write(gr, "kind", 2);
|
||||||
} else { // A strange way : to preserve backward compatibility for old archive.
|
} else { // A strange way : to preserve backward compatibility for old archive.
|
||||||
h5_write(gr, "start_at_0", m._positive_only);
|
h5_write(gr, "start_at_0", (m._positive_only?1:0));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -138,11 +138,11 @@ namespace gfs {
|
|||||||
h5::group gr = fg.open_group(subgroup_name);
|
h5::group gr = fg.open_group(subgroup_name);
|
||||||
typename matsubara_freq_mesh::domain_t dom;
|
typename matsubara_freq_mesh::domain_t dom;
|
||||||
int L;
|
int L;
|
||||||
bool s = true;
|
int s = 1;
|
||||||
h5_read(gr, "domain", dom);
|
h5_read(gr, "domain", dom);
|
||||||
h5_read(gr, "size", L);
|
h5_read(gr, "size", L);
|
||||||
if (gr.has_key("start_at_0")) h5_read(gr, "start_at_0", s);
|
if (gr.has_key("start_at_0")) h5_read(gr, "start_at_0", s);
|
||||||
m = matsubara_freq_mesh{std::move(dom), L, s};
|
m = matsubara_freq_mesh{std::move(dom), L, (s==1)};
|
||||||
}
|
}
|
||||||
|
|
||||||
friend class boost::serialization::access;
|
friend class boost::serialization::access;
|
||||||
|
96
triqs/h5/base.cpp
Normal file
96
triqs/h5/base.cpp
Normal file
@ -0,0 +1,96 @@
|
|||||||
|
/*******************************************************************************
|
||||||
|
*
|
||||||
|
* TRIQS: a Toolbox for Research in Interacting Quantum Systems
|
||||||
|
*
|
||||||
|
* Copyright (C) 2011-2014 by O. Parcollet
|
||||||
|
*
|
||||||
|
* TRIQS is free software: you can redistribute it and/or modify it under the
|
||||||
|
* terms of the GNU General Public License as published by the Free Software
|
||||||
|
* Foundation, either version 3 of the License, or (at your option) any later
|
||||||
|
* version.
|
||||||
|
*
|
||||||
|
* TRIQS is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||||
|
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||||
|
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||||
|
* details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License along with
|
||||||
|
* TRIQS. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
******************************************************************************/
|
||||||
|
#include "./base.hpp"
|
||||||
|
#include <hdf5_hl.h>
|
||||||
|
|
||||||
|
namespace triqs {
|
||||||
|
|
||||||
|
namespace h5 {
|
||||||
|
|
||||||
|
// dataspace from lengths and strides. Correct for the complex. strides must be >0
|
||||||
|
H5::DataSpace dataspace_from_LS(int R, bool is_complex, hsize_t const *Ltot, hsize_t const *L, hsize_t const *S,
|
||||||
|
hsize_t const *offset) {
|
||||||
|
int rank = R + (is_complex ? 1 : 0);
|
||||||
|
hsize_t totdimsf[rank], dimsf[rank], stridesf[rank], offsetf[rank]; // dataset dimensions
|
||||||
|
for (size_t u = 0; u < R; ++u) {
|
||||||
|
offsetf[u] = (offset ? offset[u] : 0);
|
||||||
|
dimsf[u] = L[u];
|
||||||
|
totdimsf[u] = Ltot[u];
|
||||||
|
stridesf[u] = S[u];
|
||||||
|
}
|
||||||
|
if (is_complex) {
|
||||||
|
offsetf[rank - 1] = 0;
|
||||||
|
dimsf[rank - 1] = 2;
|
||||||
|
totdimsf[rank - 1] = 2;
|
||||||
|
stridesf[rank - 1] = 1;
|
||||||
|
}
|
||||||
|
H5::DataSpace ds(rank, totdimsf);
|
||||||
|
ds.selectHyperslab(H5S_SELECT_SET, dimsf, offsetf, stridesf);
|
||||||
|
return ds;
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************** Write string attribute *********************************************/
|
||||||
|
|
||||||
|
void write_string_attribute(H5::H5Object const *obj, std::string name, std::string value) {
|
||||||
|
H5::DataSpace attr_dataspace = H5::DataSpace(H5S_SCALAR);
|
||||||
|
// Create new string datatype for attribute
|
||||||
|
H5::StrType strdatatype(H5::PredType::C_S1, value.size());
|
||||||
|
// Set up write buffer for attribute
|
||||||
|
// const H5std_string strwritebuf (value);
|
||||||
|
// Create attribute and write to it
|
||||||
|
H5::Attribute myatt_in = obj->createAttribute(name.c_str(), strdatatype, attr_dataspace);
|
||||||
|
// myatt_in.write(strdatatype, strwritebuf);
|
||||||
|
myatt_in.write(strdatatype, (void *)(value.c_str()));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/****************** Read string attribute *********************************************/
|
||||||
|
|
||||||
|
/// Return the attribute name of obj, and "" if the attribute does not exist.
|
||||||
|
std::string read_string_attribute(H5::H5Object const *obj, std::string name) {
|
||||||
|
std::string value = "";
|
||||||
|
H5::Attribute attr;
|
||||||
|
if (H5LTfind_attribute(obj->getId(), name.c_str()) == 0) return value; // not present
|
||||||
|
// can not find how to get the size with hl. Using full interface
|
||||||
|
// herr_t err2 = H5LTget_attribute_string(gr.getId(), x.c_str(), name.c_str() , &(buf.front()) ) ;
|
||||||
|
// value.append( &(buf.front()) );
|
||||||
|
try {
|
||||||
|
attr = obj->openAttribute(name.c_str());
|
||||||
|
}
|
||||||
|
catch (H5::AttributeIException) {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
H5::DataSpace dataspace = attr.getSpace();
|
||||||
|
int rank = dataspace.getSimpleExtentNdims();
|
||||||
|
if (rank != 0) TRIQS_RUNTIME_ERROR << "Reading a string attribute and got rank !=0";
|
||||||
|
size_t size = attr.getStorageSize();
|
||||||
|
H5::StrType strdatatype(H5::PredType::C_S1, size + 1);
|
||||||
|
std::vector<char> buf(size + 1, 0x00);
|
||||||
|
attr.read(strdatatype, (void *)(&buf[0]));
|
||||||
|
value.append(&(buf.front()));
|
||||||
|
}
|
||||||
|
TRIQS_ARRAYS_H5_CATCH_EXCEPTION;
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -2,7 +2,7 @@
|
|||||||
*
|
*
|
||||||
* TRIQS: a Toolbox for Research in Interacting Quantum Systems
|
* TRIQS: a Toolbox for Research in Interacting Quantum Systems
|
||||||
*
|
*
|
||||||
* Copyright (C) 2011-2013 by O. Parcollet
|
* Copyright (C) 2011-2014 by O. Parcollet
|
||||||
*
|
*
|
||||||
* TRIQS is free software: you can redistribute it and/or modify it under the
|
* TRIQS is free software: you can redistribute it and/or modify it under the
|
||||||
* terms of the GNU General Public License as published by the Free Software
|
* terms of the GNU General Public License as published by the Free Software
|
||||||
@ -18,12 +18,10 @@
|
|||||||
* TRIQS. If not, see <http://www.gnu.org/licenses/>.
|
* TRIQS. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*
|
*
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
#ifndef TRIQS_H5_BASE_H
|
#pragma once
|
||||||
#define TRIQS_H5_BASE_H
|
|
||||||
#include <triqs/utility/mini_vector.hpp>
|
#include <triqs/utility/mini_vector.hpp>
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
#include <H5Cpp.h>
|
#include <H5Cpp.h>
|
||||||
#include "hdf5_hl.h"
|
|
||||||
#include <triqs/utility/is_complex.hpp>
|
#include <triqs/utility/is_complex.hpp>
|
||||||
|
|
||||||
namespace triqs {
|
namespace triqs {
|
||||||
@ -108,21 +106,9 @@ namespace triqs {
|
|||||||
get_data_ptr (S * p) {return p;}
|
get_data_ptr (S * p) {return p;}
|
||||||
|
|
||||||
// dataspace from lengths and strides. Correct for the complex. strides must be >0
|
// dataspace from lengths and strides. Correct for the complex. strides must be >0
|
||||||
template<int R, bool IsComplex>
|
// used in array and vectors
|
||||||
H5::DataSpace dataspace_from_LS (
|
H5::DataSpace dataspace_from_LS(int R, bool is_complex, hsize_t const *Ltot, hsize_t const *L, hsize_t const *S,
|
||||||
mini_vector<hsize_t, R> const & Ltot,
|
hsize_t const *offset = NULL);
|
||||||
mini_vector<hsize_t, R> const & L,
|
|
||||||
mini_vector<hsize_t, R> const & S,
|
|
||||||
mini_vector<hsize_t, R> const & offset = mini_vector<hsize_t,R>() )
|
|
||||||
{
|
|
||||||
static const unsigned int rank = R + (IsComplex ? 1 : 0);
|
|
||||||
hsize_t totdimsf[rank], dimsf [rank], stridesf[rank], offsetf[rank]; // dataset dimensions
|
|
||||||
for (size_t u=0; u<R ; ++u) { offsetf[u] = offset[u]; dimsf[u] = L[u]; totdimsf[u] = Ltot[u]; stridesf[u] = S[u]; }
|
|
||||||
if (IsComplex) { offsetf[rank-1]=0; dimsf[rank-1]=2; totdimsf[rank-1] = 2; stridesf[rank-1]=1; }
|
|
||||||
H5::DataSpace ds ( rank, totdimsf );
|
|
||||||
ds.selectHyperslab (H5S_SELECT_SET , dimsf, offsetf, stridesf);
|
|
||||||
return ds;
|
|
||||||
}
|
|
||||||
|
|
||||||
#define TRIQS_ARRAYS_H5_CATCH_EXCEPTION \
|
#define TRIQS_ARRAYS_H5_CATCH_EXCEPTION \
|
||||||
catch( triqs::runtime_error const & error) { throw triqs::runtime_error() << error.what();}\
|
catch( triqs::runtime_error const & error) { throw triqs::runtime_error() << error.what();}\
|
||||||
@ -138,47 +124,12 @@ namespace triqs {
|
|||||||
catch( H5::ReferenceException const & error ) { error.printError(); TRIQS_RUNTIME_ERROR<<"H5 ReferenceException error"; }\
|
catch( H5::ReferenceException const & error ) { error.printError(); TRIQS_RUNTIME_ERROR<<"H5 ReferenceException error"; }\
|
||||||
catch(...) { TRIQS_RUNTIME_ERROR<<"H5 unknown error";}
|
catch(...) { TRIQS_RUNTIME_ERROR<<"H5 unknown error";}
|
||||||
|
|
||||||
/****************** Write string attribute *********************************************/
|
/****************** Read/Write string attribute *********************************************/
|
||||||
|
|
||||||
inline void write_string_attribute ( H5::H5Object const * obj, std::string name, std::string value ) {
|
void write_string_attribute(H5::H5Object const *obj, std::string name, std::string value);
|
||||||
H5::DataSpace attr_dataspace = H5::DataSpace(H5S_SCALAR);
|
|
||||||
// Create new string datatype for attribute
|
|
||||||
H5::StrType strdatatype(H5::PredType::C_S1, value.size());
|
|
||||||
// Set up write buffer for attribute
|
|
||||||
//const H5std_string strwritebuf (value);
|
|
||||||
// Create attribute and write to it
|
|
||||||
H5::Attribute myatt_in = obj->createAttribute(name.c_str(), strdatatype, attr_dataspace);
|
|
||||||
//myatt_in.write(strdatatype, strwritebuf);
|
|
||||||
myatt_in.write(strdatatype, (void *)(value.c_str()));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
/// Returns the attribute name of obj, and "" if the attribute does not exist.
|
||||||
/****************** Read string attribute *********************************************/
|
std::string read_string_attribute(H5::H5Object const *obj, std::string name);
|
||||||
|
|
||||||
/// Return the attribute name of obj, and "" if the attribute does not exist.
|
|
||||||
inline std::string read_string_attribute (H5::H5Object const * obj, std::string name ) {
|
|
||||||
std::string value ="";
|
|
||||||
H5::Attribute attr;
|
|
||||||
if (H5LTfind_attribute(obj -> getId(), name.c_str() )==0) return value;// not present
|
|
||||||
// can not find how to get the size with hl. Using full interface
|
|
||||||
//herr_t err2 = H5LTget_attribute_string(gr.getId(), x.c_str(), name.c_str() , &(buf.front()) ) ;
|
|
||||||
//value.append( &(buf.front()) );
|
|
||||||
try { attr= obj->openAttribute(name.c_str());}
|
|
||||||
catch (H5::AttributeIException) { return value;}
|
|
||||||
try {
|
|
||||||
H5::DataSpace dataspace = attr.getSpace();
|
|
||||||
int rank = dataspace.getSimpleExtentNdims();
|
|
||||||
if (rank != 0) TRIQS_RUNTIME_ERROR << "Reading a string attribute and got rank !=0";
|
|
||||||
size_t size = attr.getStorageSize();
|
|
||||||
H5::StrType strdatatype(H5::PredType::C_S1, size+1);
|
|
||||||
std::vector<char> buf(size+1, 0x00);
|
|
||||||
attr.read(strdatatype, (void *)(&buf[0]));
|
|
||||||
value.append( &(buf.front()) );
|
|
||||||
}
|
|
||||||
TRIQS_ARRAYS_H5_CATCH_EXCEPTION;
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
|
|
||||||
}}
|
}}
|
||||||
#endif
|
|
||||||
|
|
||||||
|
@ -1,16 +1,114 @@
|
|||||||
#include "./group.hpp"
|
#include "./group.hpp"
|
||||||
|
#include <hdf5_hl.h>
|
||||||
|
|
||||||
namespace triqs { namespace h5 {
|
namespace triqs {
|
||||||
|
namespace h5 {
|
||||||
|
|
||||||
|
group::group(H5::Group g, H5::Group parent, std::string name_in_parent)
|
||||||
|
: _g(g), _parent(parent), _name_in_parent(name_in_parent) {}
|
||||||
|
|
||||||
|
//group::group(H5::Group g) : _g(g) {}
|
||||||
|
|
||||||
|
group::group(H5::H5File f) : _g(f.openGroup("/")) {} // can not fail, right ?
|
||||||
|
|
||||||
|
group::group(std::string const &filename, int flag) {
|
||||||
|
H5::H5File f(filename, H5F_ACC_TRUNC);
|
||||||
|
*this = group(f);
|
||||||
|
}
|
||||||
|
|
||||||
|
group::group(hid_t id_, bool is_group) {
|
||||||
|
if (is_group) {
|
||||||
|
_g.setId(id_);
|
||||||
|
} else {
|
||||||
|
H5::H5File f;
|
||||||
|
f.setId(id_);
|
||||||
|
*this = group(f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void group::_write_triqs_hdf5_data_scheme(const char *a) { h5::write_string_attribute(&_g, "TRIQS_HDF5_data_scheme", a); }
|
||||||
|
|
||||||
|
std::string group::read_triqs_hdf5_data_scheme() const { return read_string_attribute(&_g, "TRIQS_HDF5_data_scheme"); }
|
||||||
|
|
||||||
|
bool group::has_key(std::string const &key) const { return (H5Lexists(_g.getId(), key.c_str(), H5P_DEFAULT)); }
|
||||||
|
|
||||||
|
void group::unlink_key_if_exists(std::string const &key) const {
|
||||||
|
if (this->has_key(key)) _g.unlink(key.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
group group::open_group(std::string const &key) const {
|
||||||
|
if (!has_key(key)) TRIQS_RUNTIME_ERROR << "no subgroup " << key << " in the group";
|
||||||
|
group res;
|
||||||
|
try {
|
||||||
|
res = group(_g.openGroup(key.c_str()), _g, key);
|
||||||
|
} // has a parent
|
||||||
|
catch (H5::GroupIException const &e) {
|
||||||
|
TRIQS_RUNTIME_ERROR << "Error in opening the subgroup " << key << "\n H5 error message : \n " << e.getCDetailMsg();
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// Open an existing DataSet. Throw it if does not exists
|
||||||
|
H5::DataSet group::open_dataset(std::string const &key) const {
|
||||||
|
if (!has_key(key)) TRIQS_RUNTIME_ERROR << "no dataset " << key << " in the group";
|
||||||
|
H5::DataSet res;
|
||||||
|
try {
|
||||||
|
res = _g.openDataSet(key.c_str());
|
||||||
|
}
|
||||||
|
catch (H5::GroupIException const &e) {
|
||||||
|
TRIQS_RUNTIME_ERROR << "Error in opening the dataset " << key << "\n H5 error message : \n " << e.getCDetailMsg();
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* \brief Create a subgroup.
|
||||||
|
* \param key The name of the subgroup
|
||||||
|
* \param delete_if_exists Unlink the group if it exists
|
||||||
|
*/
|
||||||
|
group group::create_group(std::string const &key, bool delete_if_exists) const {
|
||||||
|
unlink_key_if_exists(key);
|
||||||
|
return group(_g.createGroup(key.c_str()), _g, key);
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* \brief Create a dataset.
|
||||||
|
* \param key The name of the subgroup
|
||||||
|
* \param args Other parameters are forwarded to H5::Group
|
||||||
|
*
|
||||||
|
* NB : It unlinks the dataset if it exists.
|
||||||
|
*/
|
||||||
|
|
||||||
|
H5::DataSet group::create_dataset(std::string const &key, const H5::DataType &data_type, const H5::DataSpace &data_space,
|
||||||
|
const H5::DSetCreatPropList &create_plist) const {
|
||||||
|
unlink_key_if_exists(key);
|
||||||
|
H5::DataSet res;
|
||||||
|
try {
|
||||||
|
res = _g.createDataSet(key.c_str(), data_type, data_space, create_plist);
|
||||||
|
}
|
||||||
|
catch (H5::GroupIException const &e) {
|
||||||
|
TRIQS_RUNTIME_ERROR << "Error in creating the dataset " << key << "\n H5 error message : \n " << e.getCDetailMsg();
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
void group::write_string_attribute (std::string const & obj_name, std::string const & attr_name, std::string const & value){
|
||||||
|
herr_t err = H5LTset_attribute_string(_g.getId(),obj_name.c_str(),attr_name.c_str(), value.c_str() ) ;
|
||||||
|
if (err<0) TRIQS_RUNTIME_ERROR << "Error in setting attribute of "<< obj_name<<" named "<< attr_name << " to " << value;
|
||||||
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
herr_t get_group_elements_name_ds(hid_t loc_id, const char *name, void *opdata) {
|
herr_t get_group_elements_name_ds(hid_t loc_id, const char *name, void *opdata) {
|
||||||
H5O_info_t object_info; herr_t err =H5Oget_info_by_name(loc_id,name,&object_info,H5P_DEFAULT );
|
H5O_info_t object_info;
|
||||||
|
herr_t err = H5Oget_info_by_name(loc_id, name, &object_info, H5P_DEFAULT);
|
||||||
if (err < 0) TRIQS_RUNTIME_ERROR << "get_group_elements_name_ds internal";
|
if (err < 0) TRIQS_RUNTIME_ERROR << "get_group_elements_name_ds internal";
|
||||||
if (object_info.type == H5O_TYPE_DATASET) static_cast<std::vector<std::string> *>(opdata)->push_back(name);
|
if (object_info.type == H5O_TYPE_DATASET) static_cast<std::vector<std::string> *>(opdata)->push_back(name);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
herr_t get_group_elements_name_grp(hid_t loc_id, const char *name, void *opdata) {
|
herr_t get_group_elements_name_grp(hid_t loc_id, const char *name, void *opdata) {
|
||||||
H5O_info_t object_info; herr_t err =H5Oget_info_by_name(loc_id,name,&object_info,H5P_DEFAULT );
|
H5O_info_t object_info;
|
||||||
|
herr_t err = H5Oget_info_by_name(loc_id, name, &object_info, H5P_DEFAULT);
|
||||||
if (err < 0) TRIQS_RUNTIME_ERROR << "get_group_elements_name_grp internal";
|
if (err < 0) TRIQS_RUNTIME_ERROR << "get_group_elements_name_grp internal";
|
||||||
if (object_info.type == H5O_TYPE_GROUP) static_cast<std::vector<std::string> *>(opdata)->push_back(name);
|
if (object_info.type == H5O_TYPE_GROUP) static_cast<std::vector<std::string> *>(opdata)->push_back(name);
|
||||||
return 0;
|
return 0;
|
||||||
@ -32,5 +130,15 @@ namespace triqs { namespace h5 {
|
|||||||
return ds_name;
|
return ds_name;
|
||||||
}
|
}
|
||||||
|
|
||||||
}}
|
std::vector<std::string> group::get_all_subgroup_names() const {
|
||||||
|
if (!has_parent()) TRIQS_RUNTIME_ERROR << "Group hdf5 : parent not found";
|
||||||
|
return group(_parent).get_all_subgroup_names(_name_in_parent);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<std::string> group::get_all_dataset_names() const {
|
||||||
|
if (!has_parent()) TRIQS_RUNTIME_ERROR << "Group hdf5 : parent not found";
|
||||||
|
return group(_parent).get_all_dataset_names(_name_in_parent);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@ -18,107 +18,84 @@
|
|||||||
* TRIQS. If not, see <http://www.gnu.org/licenses/>.
|
* TRIQS. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*
|
*
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
#ifndef TRIQS_H5_GROUP_H
|
#pragma once
|
||||||
#define TRIQS_H5_GROUP_H
|
|
||||||
#include "./base.hpp"
|
#include "./base.hpp"
|
||||||
namespace triqs { namespace h5 {
|
|
||||||
|
namespace triqs {
|
||||||
|
namespace h5 {
|
||||||
|
|
||||||
|
// using hid_t = int;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief A local derivative of Group.
|
* \brief A local derivative of Group.
|
||||||
* Rational : use ADL for h5_read/h5_write, catch and rethrow exception, add some policy for opening/creating
|
* Rational : use ADL for h5_read/h5_write, catch and rethrow exception, add some policy for opening/creating
|
||||||
*/
|
*/
|
||||||
class group {
|
class group {
|
||||||
|
// hid_t _g_id, _parent_id;
|
||||||
H5::Group _g, _parent;
|
H5::Group _g, _parent;
|
||||||
std::string _name_in_parent;
|
std::string _name_in_parent;
|
||||||
group(H5::Group g, H5::Group parent, std::string name_in_parent) : _g(g), _parent(parent), _name_in_parent(name_in_parent) {}
|
group(H5::Group g, H5::Group parent, std::string name_in_parent);
|
||||||
|
void _write_triqs_hdf5_data_scheme(const char *a);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
group() = default;
|
group() = default;
|
||||||
group(group const &) = default;
|
group(group const &) = default;
|
||||||
group(H5::Group g) : _g(g) {}
|
group(H5::Group g) : _g(g) {}
|
||||||
|
group(H5::H5File f); /// Takes the "/" group at the top of the file
|
||||||
/// Takes the "/" group at the top of the file.
|
group(std::string const &filename, int flag);
|
||||||
group (H5::H5File f) : _g(f.openGroup("/")) {} // can not fail, right ?
|
group(hid_t id_, bool is_group);
|
||||||
|
|
||||||
group(std::string const & filename, int flag) { H5::H5File f(filename, H5F_ACC_TRUNC); *this = group(f);}
|
|
||||||
|
|
||||||
group(hid_t id_, bool is_group) {
|
|
||||||
if (is_group) { _g.setId(id_); }
|
|
||||||
else { H5::H5File f; f.setId(id_); *this = group(f); }
|
|
||||||
}
|
|
||||||
|
|
||||||
bool has_parent() const { return _name_in_parent != ""; }
|
bool has_parent() const { return _name_in_parent != ""; }
|
||||||
|
|
||||||
/// Write the triqs tag of the group if it is an object.
|
/// Write the triqs tag of the group if it is an object.
|
||||||
template <typename T> void write_triqs_hdf5_data_scheme(T const &obj) {
|
template <typename T> void write_triqs_hdf5_data_scheme(T const &obj) {
|
||||||
h5::write_string_attribute( &_g, "TRIQS_HDF5_data_scheme" , get_triqs_hdf5_data_scheme(obj).c_str() ) ;
|
_write_triqs_hdf5_data_scheme(get_triqs_hdf5_data_scheme(obj).c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Read the triqs tag of the group if it is an object. Returns"" if attribute is not present
|
/// Read the triqs tag of the group if it is an object. Returns"" if attribute is not present
|
||||||
std::string read_triqs_hdf5_data_scheme() const { return read_string_attribute(&_g, "TRIQS_HDF5_data_scheme") ; }
|
std::string read_triqs_hdf5_data_scheme() const;
|
||||||
|
|
||||||
///
|
///
|
||||||
bool has_key (std::string const & key) const { return (H5Lexists(_g.getId(), key.c_str(), H5P_DEFAULT)); }
|
bool has_key(std::string const &key) const;
|
||||||
///
|
///
|
||||||
void unlink_key_if_exists(std::string const & key) const { if (this->has_key(key)) _g.unlink(key.c_str()); }
|
|
||||||
|
void unlink_key_if_exists(std::string const &key) const;
|
||||||
|
|
||||||
/// Open a subgroup. Throw it if does not exists
|
/// Open a subgroup. Throw it if does not exists
|
||||||
group open_group(std::string const & key) const {
|
group open_group(std::string const &key) const;
|
||||||
if (!has_key(key)) TRIQS_RUNTIME_ERROR << "no subgroup "<<key <<" in the group";
|
|
||||||
group res;
|
|
||||||
try { res = group( _g.openGroup(key.c_str()), _g, key) ;} // has a parent
|
|
||||||
catch (H5::GroupIException const & e){ TRIQS_RUNTIME_ERROR << "Error in opening the subgroup "<< key <<"\n H5 error message : \n "<< e.getCDetailMsg(); }
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
/// Open an existing DataSet. Throw it if does not exists
|
/// Open an existing DataSet. Throw it if does not exists
|
||||||
H5::DataSet open_dataset(std::string const & key) const {
|
H5::DataSet open_dataset(std::string const &key) const;
|
||||||
if (!has_key(key)) TRIQS_RUNTIME_ERROR << "no dataset "<<key <<" in the group";
|
|
||||||
H5::DataSet res;
|
|
||||||
try { res = _g.openDataSet(key.c_str());}
|
|
||||||
catch (H5::GroupIException const & e){ TRIQS_RUNTIME_ERROR << "Error in opening the dataset "<< key <<"\n H5 error message : \n "<< e.getCDetailMsg(); }
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
/**
|
/**
|
||||||
* \brief Create a subgroup.
|
* \brief Create a subgroup.
|
||||||
* \param key The name of the subgroup
|
* \param key The name of the subgroup
|
||||||
* \param delete_if_exists Unlink the group if it exists
|
* \param delete_if_exists Unlink the group if it exists
|
||||||
*/
|
*/
|
||||||
group create_group(std::string const & key, bool delete_if_exists = true) const {
|
group create_group(std::string const &key, bool delete_if_exists = true) const;
|
||||||
unlink_key_if_exists(key);
|
|
||||||
return group(_g.createGroup(key.c_str()),_g, key);
|
|
||||||
}
|
|
||||||
/**
|
/**
|
||||||
* \brief Create a dataset.
|
* \brief Create a dataset.
|
||||||
* \param key The name of the subgroup
|
* \param key The name of the subgroup
|
||||||
* \param args Other parameters are forwarded to H5::Group
|
|
||||||
*
|
*
|
||||||
* NB : It unlinks the dataset if it exists.
|
* NB : It unlinks the dataset if it exists.
|
||||||
*/
|
*/
|
||||||
template<typename ... Args>
|
H5::DataSet create_dataset(std::string const &key, const H5::DataType &data_type, const H5::DataSpace &data_space,
|
||||||
H5::DataSet create_dataset(std::string const & key, Args && ... args) const {
|
const H5::DSetCreatPropList &create_plist= H5::DSetCreatPropList::DEFAULT) const;
|
||||||
unlink_key_if_exists(key);
|
|
||||||
H5::DataSet res;
|
|
||||||
try{ res = _g.createDataSet(key.c_str(), std::forward<Args>(args)...);}
|
|
||||||
catch (H5::GroupIException const & e){ TRIQS_RUNTIME_ERROR << "Error in creating the dataset "<< key <<"\n H5 error message : \n "<< e.getCDetailMsg(); }
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns all names of subgroup of key in G
|
/// Returns all names of subgroup of key in G
|
||||||
std::vector<std::string> get_all_subgroup_names(std::string const &key) const;
|
std::vector<std::string> get_all_subgroup_names(std::string const &key) const;
|
||||||
|
|
||||||
std::vector<std::string> get_all_subgroup_names() const {
|
/// Returns all names of subgroup of G
|
||||||
if (!has_parent()) TRIQS_RUNTIME_ERROR << "Group hdf5 : parent not found";
|
std::vector<std::string> get_all_subgroup_names() const;
|
||||||
return group(_parent).get_all_subgroup_names(_name_in_parent);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns all names of dataset of key in G
|
/// Returns all names of dataset of key in G
|
||||||
std::vector<std::string> get_all_dataset_names(std::string const &key) const;
|
std::vector<std::string> get_all_dataset_names(std::string const &key) const;
|
||||||
|
|
||||||
std::vector<std::string> get_all_dataset_names() const {
|
/// Returns all names of dataset of G
|
||||||
if (!has_parent()) TRIQS_RUNTIME_ERROR << "Group hdf5 : parent not found";
|
std::vector<std::string> get_all_dataset_names() const;
|
||||||
return group(_parent).get_all_dataset_names(_name_in_parent);
|
|
||||||
}
|
|
||||||
|
|
||||||
void write_string_attribute (std::string const & obj_name, std::string const & attr_name, std::string const & value){
|
|
||||||
herr_t err = H5LTset_attribute_string(_g.getId(),obj_name.c_str(),attr_name.c_str(), value.c_str() ) ;
|
|
||||||
if (err<0) TRIQS_RUNTIME_ERROR << "Error in setting attribute of "<< obj_name<<" named "<< attr_name << " to " << value;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
void write_string_attribute (std::string const & obj_name, std::string const & attr_name, std::string const & value);
|
||||||
};
|
};
|
||||||
}}
|
}
|
||||||
#endif
|
}
|
||||||
|
74
triqs/h5/scalar.cpp
Normal file
74
triqs/h5/scalar.cpp
Normal file
@ -0,0 +1,74 @@
|
|||||||
|
/*******************************************************************************
|
||||||
|
*
|
||||||
|
* TRIQS: a Toolbox for Research in Interacting Quantum Systems
|
||||||
|
*
|
||||||
|
* Copyright (C) 2011-2014 by O. Parcollet
|
||||||
|
*
|
||||||
|
* TRIQS is free software: you can redistribute it and/or modify it under the
|
||||||
|
* terms of the GNU General Public License as published by the Free Software
|
||||||
|
* Foundation, either version 3 of the License, or (at your option) any later
|
||||||
|
* version.
|
||||||
|
*
|
||||||
|
* TRIQS is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||||
|
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||||
|
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||||
|
* details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License along with
|
||||||
|
* TRIQS. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
******************************************************************************/
|
||||||
|
#include "./scalar.hpp"
|
||||||
|
namespace triqs { namespace h5 {
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
// TODO : Fix complex number ....
|
||||||
|
|
||||||
|
// S must be scalar
|
||||||
|
template <typename S>
|
||||||
|
void h5_write_impl (group g, std::string const & name, S const & A) {
|
||||||
|
try {
|
||||||
|
g.unlink_key_if_exists(name);
|
||||||
|
H5::DataSet ds = g.create_dataset( name, data_type_file<S>(), H5::DataSpace() );
|
||||||
|
ds.write( (void *)(&A), data_type_memory<S>(), H5::DataSpace() );
|
||||||
|
}
|
||||||
|
TRIQS_ARRAYS_H5_CATCH_EXCEPTION;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename S>
|
||||||
|
void h5_read_impl (group g, std::string const & name, S & A) {
|
||||||
|
try {
|
||||||
|
H5::DataSet ds = g.open_dataset(name);
|
||||||
|
H5::DataSpace dataspace = ds.getSpace();
|
||||||
|
int rank = dataspace.getSimpleExtentNdims();
|
||||||
|
if (rank != 0) TRIQS_RUNTIME_ERROR << "triqs::array::h5::read. Rank mismatch : expecting a scalar (rank =0)"
|
||||||
|
<<" while the array stored in the hdf5 file has rank = "<<rank;
|
||||||
|
ds.read( (void *)(&A), data_type_memory<S>(), H5::DataSpace() , H5::DataSpace() );
|
||||||
|
}
|
||||||
|
TRIQS_ARRAYS_H5_CATCH_EXCEPTION;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void h5_write(group g, std::string const &name, int const &x) { h5_write_impl(g, name, x); }
|
||||||
|
void h5_write(group g, std::string const &name, long const &x) { h5_write_impl(g, name, x); }
|
||||||
|
void h5_write(group g, std::string const &name, size_t const &x) { h5_write_impl(g, name, x); }
|
||||||
|
void h5_write(group g, std::string const &name, char const &x) { h5_write_impl(g, name, x); }
|
||||||
|
void h5_write(group g, std::string const &name, bool const &x) { h5_write_impl(g, name, x); }
|
||||||
|
void h5_write(group g, std::string const &name, double const &x) { h5_write_impl(g, name, x); }
|
||||||
|
void h5_write(group g, std::string const &name, std::complex<double> const &x) { h5_write_impl(g, name, x); }
|
||||||
|
|
||||||
|
|
||||||
|
void h5_read(group g, std::string const &name, int &x) { h5_read_impl(g, name, x); }
|
||||||
|
void h5_read(group g, std::string const &name, long &x) { h5_read_impl(g, name, x); }
|
||||||
|
void h5_read(group g, std::string const &name, size_t &x) { h5_read_impl(g, name, x); }
|
||||||
|
void h5_read(group g, std::string const &name, char &x) { h5_read_impl(g, name, x); }
|
||||||
|
void h5_read(group g, std::string const &name, bool &x) { h5_read_impl(g, name, x); }
|
||||||
|
void h5_read(group g, std::string const &name, double &x) { h5_read_impl(g, name, x); }
|
||||||
|
void h5_read(group g, std::string const &name, std::complex<double> &x) { h5_read_impl(g, name, x); }
|
||||||
|
|
||||||
|
|
||||||
|
}}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -18,39 +18,29 @@
|
|||||||
* TRIQS. If not, see <http://www.gnu.org/licenses/>.
|
* TRIQS. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*
|
*
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
#ifndef TRIQS_H5_SCALAR_H
|
#pragma once
|
||||||
#define TRIQS_H5_SCALAR_H
|
|
||||||
#include "./group.hpp"
|
#include "./group.hpp"
|
||||||
namespace triqs { namespace h5 {
|
namespace triqs { namespace h5 {
|
||||||
|
|
||||||
template <typename S>
|
// Issue several types are *implicitly* convertible to bool
|
||||||
typename std::enable_if<std::is_arithmetic<S>::value>::type
|
// it could be confusing. Better to use int in hdf5 files.
|
||||||
h5_write (group g, std::string const & name, S const & A) {
|
void h5_write(group g, std::string const &name, int const &x);
|
||||||
try {
|
void h5_write(group g, std::string const &name, long const &x);
|
||||||
g.unlink_key_if_exists(name);
|
void h5_write(group g, std::string const &name, size_t const &x);
|
||||||
H5::DataSet ds = g.create_dataset( name, data_type_file<S>(), H5::DataSpace() );
|
void h5_write(group g, std::string const &name, bool const &x);
|
||||||
ds.write( (void *)(&A), data_type_memory<S>(), H5::DataSpace() );
|
void h5_write(group g, std::string const &name, char const &x);
|
||||||
|
void h5_write(group g, std::string const &name, double const &x);
|
||||||
|
void h5_write(group g, std::string const &name, std::complex<double> const &x);
|
||||||
|
|
||||||
|
void h5_read(group g, std::string const &name, int &x);
|
||||||
|
void h5_read(group g, std::string const &name, long &x);
|
||||||
|
void h5_read(group g, std::string const &name, size_t &x);
|
||||||
|
void h5_read(group g, std::string const &name, bool &x);
|
||||||
|
void h5_read(group g, std::string const &name, char &x);
|
||||||
|
void h5_read(group g, std::string const &name, double &x);
|
||||||
|
void h5_read(group g, std::string const &name, std::complex<double> &x);
|
||||||
|
|
||||||
|
// the implementation complex number is missing ...
|
||||||
}
|
}
|
||||||
TRIQS_ARRAYS_H5_CATCH_EXCEPTION;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename S>
|
|
||||||
typename std::enable_if<std::is_arithmetic<S>::value>::type
|
|
||||||
h5_read (group g, std::string const & name, S & A) {
|
|
||||||
try {
|
|
||||||
H5::DataSet ds = g.open_dataset(name);
|
|
||||||
H5::DataSpace dataspace = ds.getSpace();
|
|
||||||
int rank = dataspace.getSimpleExtentNdims();
|
|
||||||
if (rank != 0) TRIQS_RUNTIME_ERROR << "triqs::array::h5::read. Rank mismatch : expecting a scalar (rank =0)"
|
|
||||||
<<" while the array stored in the hdf5 file has rank = "<<rank;
|
|
||||||
ds.read( (void *)(&A), data_type_memory<S>(), H5::DataSpace() , H5::DataSpace() );
|
|
||||||
}
|
|
||||||
TRIQS_ARRAYS_H5_CATCH_EXCEPTION;
|
|
||||||
}
|
|
||||||
|
|
||||||
// the complex number is missing here...
|
|
||||||
}}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
51
triqs/h5/string.cpp
Normal file
51
triqs/h5/string.cpp
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
/*******************************************************************************
|
||||||
|
*
|
||||||
|
* TRIQS: a Toolbox for Research in Interacting Quantum Systems
|
||||||
|
*
|
||||||
|
* Copyright (C) 2011-2014 by O. Parcollet
|
||||||
|
*
|
||||||
|
* TRIQS is free software: you can redistribute it and/or modify it under the
|
||||||
|
* terms of the GNU General Public License as published by the Free Software
|
||||||
|
* Foundation, either version 3 of the License, or (at your option) any later
|
||||||
|
* version.
|
||||||
|
*
|
||||||
|
* TRIQS is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||||
|
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||||
|
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||||
|
* details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License along with
|
||||||
|
* TRIQS. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
******************************************************************************/
|
||||||
|
#include "./string.hpp"
|
||||||
|
namespace triqs {
|
||||||
|
|
||||||
|
namespace h5 {
|
||||||
|
|
||||||
|
void h5_write (group g, std::string const & name, std::string const & value) {
|
||||||
|
try {
|
||||||
|
H5::StrType strdatatype(H5::PredType::C_S1, value.size());
|
||||||
|
H5::DataSet ds = g.create_dataset(name, strdatatype, H5::DataSpace());
|
||||||
|
ds.write((void*)(value.c_str()), strdatatype );
|
||||||
|
}
|
||||||
|
TRIQS_ARRAYS_H5_CATCH_EXCEPTION;
|
||||||
|
}
|
||||||
|
|
||||||
|
void h5_read (group g, std::string const & name, std::string & value) {
|
||||||
|
try {
|
||||||
|
H5::DataSet ds = g.open_dataset(name);
|
||||||
|
H5::DataSpace dataspace = ds.getSpace();
|
||||||
|
int rank = dataspace.getSimpleExtentNdims();
|
||||||
|
if (rank != 0) TRIQS_RUNTIME_ERROR << "Reading a string and got rank !=0";
|
||||||
|
size_t size = ds.getStorageSize();
|
||||||
|
H5::StrType strdatatype(H5::PredType::C_S1, size);
|
||||||
|
std::vector<char> buf(size+1, 0x00);
|
||||||
|
ds.read( (void *)(&buf[0]), strdatatype, H5::DataSpace(), H5::DataSpace() );
|
||||||
|
value = ""; value.append( &(buf.front()) );
|
||||||
|
}
|
||||||
|
TRIQS_ARRAYS_H5_CATCH_EXCEPTION;
|
||||||
|
}
|
||||||
|
|
||||||
|
}}
|
||||||
|
|
@ -18,10 +18,10 @@
|
|||||||
* TRIQS. If not, see <http://www.gnu.org/licenses/>.
|
* TRIQS. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*
|
*
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
#ifndef TRIQS_H5_STRING_H
|
#pragma once
|
||||||
#define TRIQS_H5_STRING_H
|
|
||||||
#include "./group.hpp"
|
#include "./group.hpp"
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
|
||||||
namespace triqs {
|
namespace triqs {
|
||||||
|
|
||||||
inline std::string get_triqs_hdf5_data_scheme(std::string const & ) { return "string";}
|
inline std::string get_triqs_hdf5_data_scheme(std::string const & ) { return "string";}
|
||||||
@ -35,14 +35,9 @@ namespace triqs {
|
|||||||
* \param value The string
|
* \param value The string
|
||||||
* \exception The HDF5 exceptions will be caught and rethrown as TRIQS_RUNTIME_ERROR (with a full stackstrace, cf triqs doc).
|
* \exception The HDF5 exceptions will be caught and rethrown as TRIQS_RUNTIME_ERROR (with a full stackstrace, cf triqs doc).
|
||||||
*/
|
*/
|
||||||
inline void h5_write (group g, std::string const & name, std::string const & value) {
|
void h5_write (group g, std::string const & name, std::string const & value);
|
||||||
try {
|
|
||||||
H5::StrType strdatatype(H5::PredType::C_S1, value.size());
|
inline void h5_write (group g, std::string const & name, const char * s) { h5_write(g,name,std::string{s});}
|
||||||
H5::DataSet ds = g.create_dataset(name, strdatatype, H5::DataSpace());
|
|
||||||
ds.write((void*)(value.c_str()), strdatatype );
|
|
||||||
}
|
|
||||||
TRIQS_ARRAYS_H5_CATCH_EXCEPTION;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Read a string from an hdf5 file
|
* \brief Read a string from an hdf5 file
|
||||||
@ -51,74 +46,9 @@ namespace triqs {
|
|||||||
* \param value The string to fill
|
* \param value The string to fill
|
||||||
* \exception The HDF5 exceptions will be caught and rethrown as TRIQS_RUNTIME_ERROR (with a full stackstrace, cf triqs doc).
|
* \exception The HDF5 exceptions will be caught and rethrown as TRIQS_RUNTIME_ERROR (with a full stackstrace, cf triqs doc).
|
||||||
*/
|
*/
|
||||||
inline void h5_read (group g, std::string const & name, std::string & value) {
|
void h5_read (group g, std::string const & name, std::string & value);
|
||||||
try {
|
|
||||||
H5::DataSet ds = g.open_dataset(name);
|
|
||||||
H5::DataSpace dataspace = ds.getSpace();
|
|
||||||
int rank = dataspace.getSimpleExtentNdims();
|
|
||||||
if (rank != 0) TRIQS_RUNTIME_ERROR << "Reading a string and got rank !=0";
|
|
||||||
size_t size = ds.getStorageSize();
|
|
||||||
H5::StrType strdatatype(H5::PredType::C_S1, size);
|
|
||||||
std::vector<char> buf(size+1, 0x00);
|
|
||||||
ds.read( (void *)(&buf[0]), strdatatype, H5::DataSpace(), H5::DataSpace() );
|
|
||||||
value = ""; value.append( &(buf.front()) );
|
|
||||||
}
|
|
||||||
TRIQS_ARRAYS_H5_CATCH_EXCEPTION;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
inline void h5_read (group g, std::string const & name, char * s) = delete;
|
||||||
/*********************************** 1d array and std::vector of string *********************************/
|
|
||||||
namespace detail {
|
|
||||||
|
|
||||||
template<typename ArrayVectorOfStringType>
|
|
||||||
void write_1darray_vector_of_string_impl (group g, std::string const & name, ArrayVectorOfStringType const & V) {
|
|
||||||
size_t s=0; for (auto & x : V) s = std::max(s,x.size());
|
|
||||||
try {
|
|
||||||
H5::DataSet ds;
|
|
||||||
H5::StrType strdatatype(H5::PredType::C_S1, s);
|
|
||||||
const size_t n = V.size();
|
|
||||||
std::vector<char> buf(n*(s+1), 0x00);
|
|
||||||
size_t i=0; for (auto & x : V) {strcpy( &buf[i*s], x.c_str()); ++i;}
|
|
||||||
|
|
||||||
mini_vector<hsize_t,1> L; L[0]=V.size();
|
|
||||||
mini_vector<hsize_t,1> S; S[0]=1;
|
|
||||||
auto d_space = dataspace_from_LS<1,false > (L,L,S);
|
|
||||||
|
|
||||||
ds = g.create_dataset(name, strdatatype, d_space );
|
|
||||||
ds.write( (void *)(&buf[0]),strdatatype, d_space );
|
|
||||||
}
|
|
||||||
TRIQS_ARRAYS_H5_CATCH_EXCEPTION;
|
|
||||||
}
|
|
||||||
|
|
||||||
//------------------------------------------------------------
|
|
||||||
|
|
||||||
template<typename ArrayVectorOfStringType>
|
|
||||||
void read_1darray_vector_of_string_impl (group g, std::string const & name, ArrayVectorOfStringType & V) {
|
|
||||||
try {
|
|
||||||
H5::DataSet ds = g.open_dataset(name);
|
|
||||||
H5::DataSpace dataspace = ds.getSpace();
|
|
||||||
mini_vector<hsize_t,1> dims_out;
|
|
||||||
int ndims = dataspace.getSimpleExtentDims( &dims_out[0], NULL);
|
|
||||||
if (ndims !=1) TRIQS_RUNTIME_ERROR << "triqs::h5 : Trying to read 1d array/vector . Rank mismatch : the array stored in the hdf5 file has rank = "<<ndims;
|
|
||||||
|
|
||||||
size_t Len = dims_out[0];
|
|
||||||
V.resize(Len);
|
|
||||||
size_t size = ds.getStorageSize();
|
|
||||||
H5::StrType strdatatype(H5::PredType::C_S1, size);
|
|
||||||
|
|
||||||
std::vector<char> buf(Len*(size+1), 0x00);
|
|
||||||
|
|
||||||
mini_vector<hsize_t,1> L; L[0]=V.size();
|
|
||||||
mini_vector<hsize_t,1> S; S[0]=1;
|
|
||||||
auto d_space = dataspace_from_LS<1,false > (L,L,S);
|
|
||||||
|
|
||||||
ds.read( (void *)(&buf[0]),strdatatype, d_space );
|
|
||||||
size_t i=0; for (auto & x : V) { x = ""; x.append(&buf[i*(size)]); ++i;}
|
|
||||||
}
|
|
||||||
TRIQS_ARRAYS_H5_CATCH_EXCEPTION;
|
|
||||||
}
|
|
||||||
}// detail
|
|
||||||
|
|
||||||
}}
|
}}
|
||||||
#endif
|
|
||||||
|
|
||||||
|
120
triqs/h5/vector.cpp
Normal file
120
triqs/h5/vector.cpp
Normal file
@ -0,0 +1,120 @@
|
|||||||
|
/*******************************************************************************
|
||||||
|
*
|
||||||
|
* TRIQS: a Toolbox for Research in Interacting Quantum Systems
|
||||||
|
*
|
||||||
|
* Copyright (C) 2011-2014 by O. Parcollet
|
||||||
|
*
|
||||||
|
* TRIQS is free software: you can redistribute it and/or modify it under the
|
||||||
|
* terms of the GNU General Public License as published by the Free Software
|
||||||
|
* Foundation, either version 3 of the License, or (at your option) any later
|
||||||
|
* version.
|
||||||
|
*
|
||||||
|
* TRIQS is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||||
|
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||||
|
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||||
|
* details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License along with
|
||||||
|
* TRIQS. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
******************************************************************************/
|
||||||
|
#include "./vector.hpp"
|
||||||
|
|
||||||
|
namespace triqs {
|
||||||
|
namespace h5 {
|
||||||
|
|
||||||
|
void h5_write (group g, std::string const & name, std::vector<std::string> const & V) {
|
||||||
|
size_t s=0; for (auto & x : V) s = std::max(s,x.size());
|
||||||
|
try {
|
||||||
|
H5::DataSet ds;
|
||||||
|
H5::StrType strdatatype(H5::PredType::C_S1, s);
|
||||||
|
const size_t n = V.size();
|
||||||
|
std::vector<char> buf(n*(s+1), 0x00);
|
||||||
|
size_t i=0; for (auto & x : V) {strcpy( &buf[i*s], x.c_str()); ++i;}
|
||||||
|
|
||||||
|
hsize_t L[1], S[1];
|
||||||
|
L[0] = V.size();
|
||||||
|
S[0] = 1;
|
||||||
|
auto d_space = dataspace_from_LS(1,false,L,L,S);
|
||||||
|
|
||||||
|
ds = g.create_dataset(name, strdatatype, d_space );
|
||||||
|
ds.write( (void *)(&buf[0]),strdatatype, d_space );
|
||||||
|
}
|
||||||
|
TRIQS_ARRAYS_H5_CATCH_EXCEPTION;
|
||||||
|
}
|
||||||
|
|
||||||
|
void h5_read (group g, std::string const & name, std::vector<std::string> & V) {
|
||||||
|
try {
|
||||||
|
H5::DataSet ds = g.open_dataset(name);
|
||||||
|
H5::DataSpace dataspace = ds.getSpace();
|
||||||
|
mini_vector<hsize_t,1> dims_out;
|
||||||
|
int ndims = dataspace.getSimpleExtentDims( &dims_out[0], NULL);
|
||||||
|
if (ndims !=1) TRIQS_RUNTIME_ERROR << "triqs::h5 : Trying to read 1d array/vector . Rank mismatch : the array stored in the hdf5 file has rank = "<<ndims;
|
||||||
|
|
||||||
|
size_t Len = dims_out[0];
|
||||||
|
V.resize(Len);
|
||||||
|
size_t size = ds.getStorageSize();
|
||||||
|
H5::StrType strdatatype(H5::PredType::C_S1, size);
|
||||||
|
|
||||||
|
std::vector<char> buf(Len*(size+1), 0x00);
|
||||||
|
|
||||||
|
hsize_t L[1], S[1];
|
||||||
|
L[0] = V.size();
|
||||||
|
S[0] = 1;
|
||||||
|
auto d_space = dataspace_from_LS(1,false, L,L,S);
|
||||||
|
|
||||||
|
ds.read( (void *)(&buf[0]),strdatatype, d_space );
|
||||||
|
size_t i=0; for (auto & x : V) { x = ""; x.append(&buf[i*(size)]); ++i;}
|
||||||
|
}
|
||||||
|
TRIQS_ARRAYS_H5_CATCH_EXCEPTION;
|
||||||
|
}
|
||||||
|
|
||||||
|
// implementation for vector of double and complex
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
// the dataspace corresponding to the array. Contiguous data only...
|
||||||
|
template <typename T> H5::DataSpace data_space_for_vector(std::vector<T> const &V) {
|
||||||
|
hsize_t L[1], S[1];
|
||||||
|
S[0] = 1;
|
||||||
|
L[0] = V.size();
|
||||||
|
return h5::dataspace_from_LS(1, triqs::is_complex<T>::value, L, L, S);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
inline void h5_write_vector_impl (group g, std::string const & name, std::vector<T> const & V) {
|
||||||
|
try {
|
||||||
|
H5::DataSet ds = g.create_dataset(name, h5::data_type_file<T>(), data_space_for_vector(V) );
|
||||||
|
ds.write( &V[0], h5::data_type_memory<T>(), data_space_for_vector(V) );
|
||||||
|
// if complex, to be python compatible, we add the __complex__ attribute
|
||||||
|
if (triqs::is_complex<T>::value) h5::write_string_attribute(&ds,"__complex__","1");
|
||||||
|
}
|
||||||
|
TRIQS_ARRAYS_H5_CATCH_EXCEPTION;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
inline void h5_read_impl (group g, std::string const & name, std::vector<T> & V) {
|
||||||
|
try {
|
||||||
|
H5::DataSet ds = g.open_dataset(name);
|
||||||
|
H5::DataSpace dataspace = ds.getSpace();
|
||||||
|
static const unsigned int Rank = 1 + (triqs::is_complex<T>::value ? 1 : 0);
|
||||||
|
int rank = dataspace.getSimpleExtentNdims();
|
||||||
|
if (rank != Rank) TRIQS_RUNTIME_ERROR << "triqs : h5 : read vector. Rank mismatch : the array stored in the hdf5 file has rank = "<<rank;
|
||||||
|
mini_vector<hsize_t,Rank> dims_out;
|
||||||
|
dataspace.getSimpleExtentDims( &dims_out[0], NULL);
|
||||||
|
V.resize(dims_out[0]);
|
||||||
|
ds.read( &V[0], h5::data_type_memory<T>(), data_space_for_vector(V) , dataspace );
|
||||||
|
}
|
||||||
|
TRIQS_ARRAYS_H5_CATCH_EXCEPTION;
|
||||||
|
}
|
||||||
|
}// impl namespace
|
||||||
|
|
||||||
|
|
||||||
|
void h5_write (group f, std::string const & name, std::vector<double> const & V) { h5_write_vector_impl(f,name,V);}
|
||||||
|
void h5_write (group f, std::string const & name, std::vector<std::complex<double>> const & V) { h5_write_vector_impl(f,name,V);}
|
||||||
|
void h5_read (group f, std::string const & name, std::vector<double> & V) { h5_read_impl(f,name,V);}
|
||||||
|
void h5_read (group f, std::string const & name, std::vector<std::complex<double>> & V) { h5_read_impl(f,name,V);}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -18,8 +18,7 @@
|
|||||||
* TRIQS. If not, see <http://www.gnu.org/licenses/>.
|
* TRIQS. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*
|
*
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
#ifndef TRIQS_H5_VECTOR_H
|
#pragma once
|
||||||
#define TRIQS_H5_VECTOR_H
|
|
||||||
#include "./group.hpp"
|
#include "./group.hpp"
|
||||||
#include "./string.hpp"
|
#include "./string.hpp"
|
||||||
#include <vector>
|
#include <vector>
|
||||||
@ -28,72 +27,23 @@ namespace triqs {
|
|||||||
|
|
||||||
inline std::string get_triqs_hdf5_data_scheme(std::vector<std::string> const & ) { return "vector<string>";}
|
inline std::string get_triqs_hdf5_data_scheme(std::vector<std::string> const & ) { return "vector<string>";}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T> std::string get_triqs_hdf5_data_scheme(std::vector<T> const&) {
|
||||||
std::string get_triqs_hdf5_data_scheme(std::vector<T> const&) {
|
|
||||||
using triqs::get_triqs_hdf5_data_scheme; // for the basic types, not found by ADL
|
using triqs::get_triqs_hdf5_data_scheme; // for the basic types, not found by ADL
|
||||||
std::stringstream fs;
|
return "std::vector<" + get_triqs_hdf5_data_scheme(T()) + ">";
|
||||||
fs<<"std::vector<"<<get_triqs_hdf5_data_scheme(T())<<">";
|
|
||||||
return fs.str();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace h5 {
|
namespace h5 {
|
||||||
|
|
||||||
// special case of vector of string
|
void h5_write (group f, std::string const & name, std::vector<std::string> const & V);
|
||||||
inline void h5_write (group f, std::string const & name, std::vector<std::string> const & V) {
|
void h5_read (group f, std::string const & name, std::vector<std::string> & V);
|
||||||
detail::write_1darray_vector_of_string_impl(f,name,V);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void h5_read (group f, std::string const & name, std::vector<std::string> & V) {
|
void h5_write (group f, std::string const & name, std::vector<double> const & V);
|
||||||
detail::read_1darray_vector_of_string_impl(f,name,V);
|
void h5_write (group f, std::string const & name, std::vector<std::complex<double>> const & V);
|
||||||
}
|
|
||||||
|
|
||||||
// implementation for vector of double and complex
|
void h5_read (group f, std::string const & name, std::vector<double> & V);
|
||||||
namespace vector_impl {
|
void h5_read (group f, std::string const & name, std::vector<std::complex<double>> & V);
|
||||||
|
|
||||||
// the dataspace corresponding to the array. Contiguous data only...
|
|
||||||
template <typename T>
|
|
||||||
H5::DataSpace data_space_for_vector (std::vector<T> const & V) {
|
|
||||||
mini_vector<hsize_t,1> L,S; S[0]=1;L[0] = V.size();
|
|
||||||
return h5::dataspace_from_LS<1, triqs::is_complex<T>::value > (L,L,S);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
inline void h5_write_vector_impl (group g, std::string const & name, std::vector<T> const & V) {
|
|
||||||
try {
|
|
||||||
H5::DataSet ds = g.create_dataset(name, h5::data_type_file<T>(), data_space_for_vector(V) );
|
|
||||||
ds.write( &V[0], h5::data_type_memory<T>(), data_space_for_vector(V) );
|
|
||||||
// if complex, to be python compatible, we add the __complex__ attribute
|
|
||||||
if (triqs::is_complex<T>::value) h5::write_string_attribute(&ds,"__complex__","1");
|
|
||||||
}
|
|
||||||
TRIQS_ARRAYS_H5_CATCH_EXCEPTION;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
inline void h5_read_impl (group g, std::string const & name, std::vector<T> & V) {
|
|
||||||
try {
|
|
||||||
H5::DataSet ds = g.open_dataset(name);
|
|
||||||
H5::DataSpace dataspace = ds.getSpace();
|
|
||||||
static const unsigned int Rank = 1 + (triqs::is_complex<T>::value ? 1 : 0);
|
|
||||||
int rank = dataspace.getSimpleExtentNdims();
|
|
||||||
if (rank != Rank) TRIQS_RUNTIME_ERROR << "triqs : h5 : read vector. Rank mismatch : the array stored in the hdf5 file has rank = "<<rank;
|
|
||||||
mini_vector<hsize_t,Rank> dims_out;
|
|
||||||
dataspace.getSimpleExtentDims( &dims_out[0], NULL);
|
|
||||||
V.resize(dims_out[0]);
|
|
||||||
ds.read( &V[0], h5::data_type_memory<T>(), data_space_for_vector(V) , dataspace );
|
|
||||||
}
|
|
||||||
TRIQS_ARRAYS_H5_CATCH_EXCEPTION;
|
|
||||||
}
|
|
||||||
}// impl namespace
|
|
||||||
|
|
||||||
|
|
||||||
inline void h5_write (group f, std::string const & name, std::vector<double> const & V) { vector_impl::h5_write_vector_impl(f,name,V);}
|
|
||||||
inline void h5_write (group f, std::string const & name, std::vector<std::complex<double>> const & V) { vector_impl::h5_write_vector_impl(f,name,V);}
|
|
||||||
|
|
||||||
inline void h5_read (group f, std::string const & name, std::vector<double> & V) { vector_impl::h5_read_impl(f,name,V);}
|
|
||||||
inline void h5_read (group f, std::string const & name, std::vector<std::complex<double>> & V) { vector_impl::h5_read_impl(f,name,V);}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user