Merge branch 'master' of bitbucket.org:glavaux/cosmotool

This commit is contained in:
Guilhem Lavaux 2015-02-13 15:45:31 +01:00
commit 48bdd03947
4 changed files with 178 additions and 75 deletions

View File

@ -37,10 +37,15 @@ knowledge of the CeCILL license and that you accept its terms.
#define __DETAILS_EUCLIDIAN_MAPS #define __DETAILS_EUCLIDIAN_MAPS
#include <cmath> #include <cmath>
#include <boost/multi_array.hpp>
namespace CosmoTool namespace CosmoTool
{ {
namespace details {
static void no_free_euclidian_map(void *) {}
}
template<typename T> template<typename T>
class EuclidianFourierMapBase: public FourierMap<T> class EuclidianFourierMapBase: public FourierMap<T>
{ {
@ -61,6 +66,19 @@ namespace CosmoTool
m_size *= m_dims[i]; m_size *= m_dims[i];
} }
template<typename ArrayType>
EuclidianFourierMapBase(ArrayType& indata)
{
m_data = boost::shared_ptr<T>(
indata.origin(),
std::ptr_fun(details::no_free_euclidian_map));
m_dims = DimArray(indata.num_dimensions());
m_size = indata.num_elements();
for (int i = 0; i < m_dims.size(); i++)
m_dims[i] = indata.shape()[i];
}
virtual ~EuclidianFourierMapBase() virtual ~EuclidianFourierMapBase()
{ {
} }
@ -71,6 +89,14 @@ namespace CosmoTool
virtual T *data() { return m_data.get(); } virtual T *data() { return m_data.get(); }
virtual long size() const { return m_size; } virtual long size() const { return m_size; }
boost::multi_array_ref<T, 1>& array() {
return boost::multi_array_ref<T, 1>(m_data.get(), boost::extents[size]);
}
boost::const_multi_array_ref<T, 1>& array() const {
return boost::const_multi_array_ref<T, 1>(m_data.get(), boost::extents[size]);
}
virtual FourierMap<T> *copy() const virtual FourierMap<T> *copy() const
{ {
FourierMap<T> *m = this->mimick(); FourierMap<T> *m = this->mimick();
@ -90,6 +116,12 @@ namespace CosmoTool
: EuclidianFourierMapBase<T>(indata, indims) : EuclidianFourierMapBase<T>(indata, indims)
{} {}
template<typename ArrayType>
EuclidianFourierMapReal(ArrayType& indata)
: EuclidianFourierMapBase<T>(indata)
{}
virtual FourierMap<T> *mimick() const virtual FourierMap<T> *mimick() const
{ {
return new EuclidianFourierMapReal<T>( return new EuclidianFourierMapReal<T>(
@ -125,18 +157,34 @@ namespace CosmoTool
int dim0, int dim0,
const DimArray& indims, const DimArray& indims,
const std::vector<double>& dk) const std::vector<double>& dk)
: EuclidianFourierMapBase<std::complex<T> >(indata, indims), delta_k(dk), m_dim0(dim0), even0((dim0 % 2)==0) : EuclidianFourierMapBase<std::complex<T> >(indata, indims),
delta_k(dk), m_dim0(dim0), even0((dim0 % 2)==0)
{ {
assert(dk.size() == indims.size()); assert(dk.size() == indims.size());
plane_size = 1; plane_size = 1;
alleven = true; alleven = true;
for (int q = 1; q < indims.size(); q++) for (int q = 1; q < indims.size(); q++) {
{
plane_size *= indims[q]; plane_size *= indims[q];
alleven = alleven && ((indims[q]%2)==0); alleven = alleven && ((indims[q]%2)==0);
} }
} }
template<typename ArrayType>
EuclidianFourierMapComplex(ArrayType& indata,
int dim0,
const std::vector<double>& dk)
: EuclidianFourierMapBase<std::complex<T> >(indata),
delta_k(dk), m_dim0(dim0), even0((dim0 % 2)==0)
{
assert(dk.size() == indata.num_dimensions());
plane_size = 1;
alleven = true;
for (int q = 1; q < this->m_dims.size(); q++) {
plane_size *= this->m_dims[q];
alleven = alleven && ((this->m_dims[q]%2)==0);
}
}
virtual FourierMap<std::complex<T> > *mimick() const virtual FourierMap<std::complex<T> > *mimick() const
{ {
return return
@ -162,8 +210,7 @@ namespace CosmoTool
assert(kvec.size() == dims.size()); assert(kvec.size() == dims.size());
kvec[0] = ik[0] * delta_k[0]; kvec[0] = ik[0] * delta_k[0];
for (int q = 1; q < ik.size(); q++) for (int q = 1; q < ik.size(); q++) {
{
int dk = ik[q]; int dk = ik[q];
if (dk > dims[q]/2) if (dk > dims[q]/2)
dk = dk - dims[q]; dk = dk - dims[q];
@ -201,8 +248,7 @@ namespace CosmoTool
double k2 = 0; double k2 = 0;
k2 += CosmoTool::square(ik[0]*delta_k[0]); k2 += CosmoTool::square(ik[0]*delta_k[0]);
for (int q = 1; q < ik.size(); q++) for (int q = 1; q < ik.size(); q++) {
{
int dk = ik[q]; int dk = ik[q];
if (dk > dims[q]/2) if (dk > dims[q]/2)
@ -231,7 +277,8 @@ namespace CosmoTool
virtual std::complex<T> dot_product(const FourierMap<std::complex<T> >& other) const virtual std::complex<T> dot_product(const FourierMap<std::complex<T> >& other) const
throw(std::bad_cast) throw(std::bad_cast)
{ {
const EuclidianFourierMapComplex<T>& m2 = dynamic_cast<const EuclidianFourierMapComplex<T>&>(other); const EuclidianFourierMapComplex<T>& m2 =
dynamic_cast<const EuclidianFourierMapComplex<T>&>(other);
if (this->size() != m2.size()) if (this->size() != m2.size())
throw std::bad_cast(); throw std::bad_cast();
@ -241,17 +288,14 @@ namespace CosmoTool
int N0 = dims[0] + (even0 ? 0 : 1); int N0 = dims[0] + (even0 ? 0 : 1);
std::complex<T> result = 0; std::complex<T> result = 0;
for (long q0 = 1; q0 < N0-1; q0++) for (long q0 = 1; q0 < N0-1; q0++) {
{ for (long p = 0; p < plane_size; p++) {
for (long p = 0; p < plane_size; p++)
{
long idx = q0+dims[0]*p; long idx = q0+dims[0]*p;
assert(idx < this->size()); assert(idx < this->size());
result += T(2)*(std::conj(d1[idx]) * d2[idx]).real(); result += T(2)*(std::conj(d1[idx]) * d2[idx]).real();
} }
} }
if (even0) if (even0) {
{
for (long p = 0; p < plane_size; p++) for (long p = 0; p < plane_size; p++)
{ {
long q0 = N0*p, q1 = (p+1)*N0-1; long q0 = N0*p, q1 = (p+1)*N0-1;

View File

@ -96,14 +96,18 @@ namespace CosmoTool
std::ptr_fun(calls::free)), std::ptr_fun(calls::free)),
m_dims); m_dims);
fourierMap = new EuclidianFourierMapComplex<T>( fourierMap = new EuclidianFourierMapComplex<T>(
boost::shared_ptr<std::complex<T> >((std::complex<T>*)calls::alloc_complex(Nc), boost::shared_ptr<std::complex<T> >(
(std::complex<T>*)calls::alloc_complex(Nc),
std::ptr_fun(calls::free)), std::ptr_fun(calls::free)),
dims[0], m_dims_hc, dk); dims[0], m_dims_hc, dk);
{ {
m_analysis = calls::plan_dft_r2c(dims.size(), &swapped_dims[0], m_analysis = calls::plan_dft_r2c(
realMap->data(), (typename calls::complex_type *)fourierMap->data(), dims.size(), &swapped_dims[0],
realMap->data(),
(typename calls::complex_type *)fourierMap->data(),
FFTW_DESTROY_INPUT|FFTW_MEASURE); FFTW_DESTROY_INPUT|FFTW_MEASURE);
m_synthesis = calls::plan_dft_c2r(dims.size(), &swapped_dims[0], m_synthesis = calls::plan_dft_c2r(
dims.size(), &swapped_dims[0],
(typename calls::complex_type *)fourierMap->data(), realMap->data(), (typename calls::complex_type *)fourierMap->data(), realMap->data(),
FFTW_DESTROY_INPUT|FFTW_MEASURE); FFTW_DESTROY_INPUT|FFTW_MEASURE);
} }

View File

@ -68,6 +68,8 @@ public: \
static void free(void *p) { fftw_free(p); } \ static void free(void *p) { fftw_free(p); } \
\ \
static void execute(plan_type p) { prefix ## _execute(p); } \ static void execute(plan_type p) { prefix ## _execute(p); } \
static void execute_r2c(plan_type p, real_type *in, complex_type *out) { prefix ## _execute_dft_r2c(p, in, out); } \
static void execute_c2r(plan_type p, complex_type *in, real_type *out) { prefix ## _execute_dft_c2r(p, in, out); } \
static plan_type plan_dft_r2c_2d(int Nx, int Ny, \ static plan_type plan_dft_r2c_2d(int Nx, int Ny, \
real_type *in, complex_type *out, \ real_type *in, complex_type *out, \
unsigned flags) \ unsigned flags) \
@ -88,6 +90,13 @@ public: \
{ \ { \
return prefix ## _plan_dft_r2c_3d(Nx, Ny, Nz, in, out, flags); \ return prefix ## _plan_dft_r2c_3d(Nx, Ny, Nz, in, out, flags); \
} \ } \
static plan_type plan_dft_c2r_3d(int Nx, int Ny, int Nz, \
complex_type *in, real_type *out, \
unsigned flags) \
{ \
return prefix ## _plan_dft_c2r_3d(Nx, Ny, Nz, in, out, flags); \
} \
\
static plan_type plan_dft_r2c(int rank, const int *n, real_type *in, \ static plan_type plan_dft_r2c(int rank, const int *n, real_type *in, \
complex_type *out, unsigned flags) \ complex_type *out, unsigned flags) \
{ \ { \

View File

@ -97,13 +97,13 @@ namespace CosmoTool {
//! \author leo Goodstadt (04 March 2013) //! \author leo Goodstadt (04 March 2013)
//! //!
//!_______________________________________________________________________________________ //!_______________________________________________________________________________________
template<typename T, std::size_t DIMENSIONS, typename hdf5_data_type> template<typename ArrayType, typename hdf5_data_type>
void hdf5_write_array(H5::CommonFG& fg, const std::string& data_set_name, void hdf5_write_array(H5::CommonFG& fg, const std::string& data_set_name,
const boost::multi_array<T, DIMENSIONS>& data, const ArrayType& data,
const hdf5_data_type& datatype) const hdf5_data_type& datatype)
{ {
std::vector<hsize_t> dimensions(data.shape(), data.shape() + DIMENSIONS); std::vector<hsize_t> dimensions(data.shape(), data.shape() + data.num_dimensions());
H5::DataSpace dataspace(DIMENSIONS, dimensions.data()); H5::DataSpace dataspace(data.num_dimensions(), dimensions.data());
H5::DataSet dataset = fg.createDataSet(data_set_name, datatype, dataspace); H5::DataSet dataset = fg.createDataSet(data_set_name, datatype, dataspace);
@ -134,20 +134,28 @@ namespace CosmoTool {
} }
}; };
template<typename T, std::size_t DIMENSIONS> template<> struct get_hdf5_data_type<std::complex<float> > {
void hdf5_write_array(H5::CommonFG& fg, const std::string& data_set_name, const boost::multi_array<T, DIMENSIONS>& data ) static H5::DataType type() {
return hdf5_ComplexType<float>::ctype()->type;
}
};
template<> struct get_hdf5_data_type<std::complex<double> > {
static H5::DataType type() {
return hdf5_ComplexType<double>::ctype()->type;
}
};
template<typename ArrayType>
void hdf5_write_array(H5::CommonFG& fg, const std::string& data_set_name, const ArrayType& data )
{ {
typedef typename ArrayType::element T;
get_hdf5_data_type<T> hdf_data_type; get_hdf5_data_type<T> hdf_data_type;
hdf5_write_array(fg, data_set_name, data, hdf_data_type.type()); hdf5_write_array(fg, data_set_name, data, hdf_data_type.type());
} }
template<typename T, std::size_t DIMENSIONS>
void hdf5_write_array(H5::CommonFG& fg, const std::string& data_set_name, const boost::multi_array<std::complex<T>, DIMENSIONS>& data )
{
hdf5_write_array(fg, data_set_name, data, hdf5_ComplexType<T>::ctype()->type);
}
// HDF5 array reader // HDF5 array reader
// //
// Author Guilhem Lavaux (May 2014) // Author Guilhem Lavaux (May 2014)
@ -173,38 +181,76 @@ namespace CosmoTool {
} }
}; };
template<typename T, std::size_t DIMENSIONS, typename hdf5_data_type>
template<typename Array> class array_has_resize {
struct Fallback { int resize; };
struct Derived: Array, Fallback {};
typedef char yes[1];
typedef char no[2];
template<typename U, U> struct Check;
template<typename U>
static yes& func(Check<int Fallback::*, &U::resize> *);
template<typename U>
static no& func(...);
public:
typedef array_has_resize type;
enum { value = sizeof(func<Derived>(0)) == sizeof(no) };
};
template<typename ArrayType>
typename boost::enable_if<
array_has_resize<ArrayType>
>::type
hdf5_resize_array(ArrayType& data, std::vector<hsize_t>& dims) {
data.resize(
hdf5_extent_gen<ArrayType::dimensionality>::build(dims.data())
);
}
template<typename ArrayType>
typename boost::disable_if<
array_has_resize<ArrayType>
>::type
hdf5_resize_array(ArrayType& data, std::vector<hsize_t>& dims) {
for (long i = 0; i < data.num_dimensions(); i++) {
assert (data.shape()[i] == dims[i]);
}
}
template<typename ArrayType, typename hdf5_data_type>
void hdf5_read_array(H5::CommonFG& fg, const std::string& data_set_name, void hdf5_read_array(H5::CommonFG& fg, const std::string& data_set_name,
boost::multi_array<T, DIMENSIONS>& data, ArrayType& data,
const hdf5_data_type& datatype) const hdf5_data_type& datatype)
{ {
H5::DataSet dataset = fg.openDataSet(data_set_name); H5::DataSet dataset = fg.openDataSet(data_set_name);
H5::DataSpace dataspace = dataset.getSpace(); H5::DataSpace dataspace = dataset.getSpace();
std::vector<hsize_t> dimensions(DIMENSIONS); std::vector<hsize_t> dimensions(data.num_dimensions());
if (dataspace.getSimpleExtentNdims() != DIMENSIONS) if (dataspace.getSimpleExtentNdims() != data.num_dimensions())
{ {
throw InvalidDimensions(); throw InvalidDimensions();
} }
dataspace.getSimpleExtentDims(dimensions.data()); dataspace.getSimpleExtentDims(dimensions.data());
data.resize(hdf5_extent_gen<DIMENSIONS>::build(dimensions.data())); hdf5_resize_array(data, dimensions);
dataset.read(data.data(), datatype); dataset.read(data.data(), datatype);
} }
template<typename T, std::size_t DIMENSIONS> template<typename ArrayType>
void hdf5_read_array(H5::CommonFG& fg, const std::string& data_set_name, boost::multi_array<T, DIMENSIONS>& data ) void hdf5_read_array(H5::CommonFG& fg, const std::string& data_set_name, ArrayType& data )
{ {
typedef typename ArrayType::element T;
get_hdf5_data_type<T> hdf_data_type; get_hdf5_data_type<T> hdf_data_type;
hdf5_read_array(fg, data_set_name, data, hdf_data_type.type()); hdf5_read_array(fg, data_set_name, data, hdf_data_type.type());
} }
template<typename T, std::size_t DIMENSIONS>
void hdf5_read_array(H5::CommonFG& fg, const std::string& data_set_name, boost::multi_array<std::complex<T>, DIMENSIONS>& data )
{
hdf5_read_array(fg, data_set_name, data, hdf5_ComplexType<T>::ctype()->type);
}
#define CTOOL_HDF5_NAME(STRUCT) BOOST_PP_CAT(hdf5_,STRUCT) #define CTOOL_HDF5_NAME(STRUCT) BOOST_PP_CAT(hdf5_,STRUCT)
#define CTOOL_HDF5_INSERT_ELEMENT(r, STRUCT, element) \ #define CTOOL_HDF5_INSERT_ELEMENT(r, STRUCT, element) \