diff --git a/CMakeLists.txt b/CMakeLists.txt index faaa590..6c4dd9b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -11,16 +11,32 @@ option(BUILD_SHARED_LIBS "Build shared libraries." OFF) option(BUILD_STATIC_LIBS "Build static libraries." ON) find_path(NETCDF_INCLUDE_PATH NAMES netcdf.h) +find_path(NETCDFCPP_INCLUDE_PATH NAMES netcdfcpp.h netcdf) find_path(GSL_INCLUDE_PATH NAMES gsl/gsl_blas.h) +IF(EXISTS ${NETCDFCPP_INCLUDE_PATH}/netcdf) + SET(FOUND_NETCDF4 1) + FILE(WRITE ${CMAKE_BINARY_DIR}/src/ctool_netcdf_ver.hpp "#define NETCDFCPP4 1") +ELSE(EXISTS ${NETCDFCPP_INCLUDE_PATH}/netcdf) + SET(FOUND_NETCDF3 1) + FILE(WRITE ${CMAKE_BINARY_DIR}/src/ctool_netcdf_ver.hpp "#undef NETCDFCPP4") +ENDIF(EXISTS ${NETCDFCPP_INCLUDE_PATH}/netcdf) + find_library(NETCDF_LIBRARY netcdf) -find_library(NETCDFCPP_LIBRARY netcdf_c++) +find_library(NETCDFCPP_LIBRARY NAMES netcdf_c++ netcdf_c++4) find_library(GSL_LIBRARY gsl) find_library(GSLCBLAS_LIBRARY gslcblas) -set(HDF5_FIND_COMPONENTS CXX) +set(HDF5_FIND_COMPONENTS HL CXX) +if(HDF5_ROOTDIR) + SET(ENV{HDF5_ROOT} ${HDF5_ROOTDIR}) +endif(HDF5_ROOTDIR) include(FindHDF5) +include(FindPkgConfig) + +pkg_check_modules(FFTW3 fftw3>=3.3) +pkg_check_modules(EIGEN3 eigen3) include(FindPackageHandleStandardArgs) set(NETCDF_FIND_REQUIRED TRUE) diff --git a/sample/CMakeLists.txt b/sample/CMakeLists.txt index 408ccf8..3a18be0 100644 --- a/sample/CMakeLists.txt +++ b/sample/CMakeLists.txt @@ -1,5 +1,5 @@ SET(tolink ${GSL_LIBRARIES} CosmoTool ${CosmoTool_LIBS}) -include_directories(${CMAKE_SOURCE_DIR}/src ${NETCDF_INCLUDE_PATH} ${GSL_INCLUDE_PATH}) +include_directories(${CMAKE_SOURCE_DIR}/src ${FFTW3_INCLUDE_DIRS} ${EIGEN3_INCLUDE_DIRS} ${NETCDF_INCLUDE_PATH} ${GSL_INCLUDE_PATH}) add_executable(testBQueue testBQueue.cpp) target_link_libraries(testBQueue ${tolink}) @@ -36,3 +36,11 @@ target_link_libraries(testEskow ${tolink}) add_executable(testAlgo testAlgo.cpp) target_link_libraries(testAlgo ${tolink}) + +add_executable(testBSP testBSP.cpp) +target_link_libraries(testBSP ${tolink}) + +if (FFTW3_FOUND AND EIGEN3_FOUND) + add_executable(test_fft_calls test_fft_calls) + target_link_libraries(test_fft_calls ${tolink} ${FFTW3_LIBRARIES}) +endif (FFTW3_FOUND AND EIGEN3_FOUND) diff --git a/sample/testBSP.cpp b/sample/testBSP.cpp index 38bbd2a..f142fc2 100644 --- a/sample/testBSP.cpp +++ b/sample/testBSP.cpp @@ -1,3 +1,4 @@ +#if 0 #include "bsp_simple.hpp" int main(int argc, char **argv) @@ -10,3 +11,5 @@ int main(int argc, char **argv) return 0; } +#endif +int main() {} diff --git a/sample/testEskow.cpp b/sample/testEskow.cpp index 2f173a6..60c1821 100644 --- a/sample/testEskow.cpp +++ b/sample/testEskow.cpp @@ -50,6 +50,8 @@ int main(int argc, char **argv) chol.cholesky(M, M.N, norm_E); + cout << "norm_E = " << norm_E << endl; + for (int i = 0; i < M.N; i++) { for (int j = 0; j < M.N; j++) diff --git a/sample/testReadFlash.cpp b/sample/testReadFlash.cpp index 4b1c320..61d038e 100644 --- a/sample/testReadFlash.cpp +++ b/sample/testReadFlash.cpp @@ -9,7 +9,7 @@ using namespace std; int main () { - char* filename = "lss_read_hdf5_chk_0000"; + const char* filename = "lss_read_hdf5_chk_0000"; SimuData* data = CosmoTool::loadFlashMulti(filename, 0, 0); diff --git a/sample/test_fft_calls.cpp b/sample/test_fft_calls.cpp new file mode 100644 index 0000000..35eeb12 --- /dev/null +++ b/sample/test_fft_calls.cpp @@ -0,0 +1,12 @@ +#include "fourier/euclidian.hpp" + +using namespace CosmoTool; + +int main() +{ + EuclidianFourierTransform_2d dft(128,128,1.0,1.0); + + dft.realSpace().eigen().setRandom(); + dft.analysis(); + return 0; +} diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 8e05ccc..c99918e 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -6,11 +6,19 @@ SET(CosmoTool_SRCS loadRamses.cpp octTree.cpp powerSpectrum.cpp - yorick.cpp miniargs.cpp growthFactor.cpp ) +IF(FOUND_NETCDF3) + SET(CosmoTool_SRCS ${CosmoTool_SRCS} yorick_nc3.cpp) +ELSE(FOUND_NETCDF3) +IF(FOUND_NETCDF4) + SET(CosmoTool_SRCS ${CosmoTool_SRCS} yorick_nc4.cpp) +ENDIF(FOUND_NETCDF4) +ENDIF(FOUND_NETCDF3) + + if (HDF5_FOUND) set(CosmoTool_SRCS ${CosmoTool_SRCS} h5_readFlash.cpp @@ -46,15 +54,14 @@ SET(CosmoTool_SRCS ${CosmoTool_SRCS} growthFactor.hpp ) -include_directories(${GSL_INCLUDE_PATH} ${NETCDF_INCLUDE_PATH}) +include_directories(${GSL_INCLUDE_PATH} ${NETCDF_INCLUDE_PATH} ${NETCDFCPP_INCLUDE_PATH} ${CMAKE_BINARY_DIR}/src) -set(CosmoTool_LIBS ${NETCDF_LIBRARY} ${NETCDFCPP_LIBRARY} ${GSL_LIBRARIES}) +set(CosmoTool_LIBS ${NETCDFCPP_LIBRARY} ${NETCDF_LIBRARY} ${GSL_LIBRARIES}) if (HDF5_FOUND) set(CosmoTool_LIBS ${CosmoTool_LIBS} ${HDF5_CXX_LIBRARIES} ${HDF5_LIBRARIES}) include_directories(${HDF5_INCLUDE_DIRS}) endif (HDF5_FOUND) -message("${CosmoTool_LIBS}") set(CosmoTool_LIBS ${CosmoTool_LIBS} PARENT_SCOPE) if (BUILD_SHARED_LIBS) diff --git a/src/bsp_simple.hpp b/src/bsp_simple.hpp index 1f48296..b61bcf3 100644 --- a/src/bsp_simple.hpp +++ b/src/bsp_simple.hpp @@ -154,6 +154,8 @@ namespace CosmoTool f.data = data; insert(f); } + + bool inside(const typename space_t::coord_t& p) const; }; }; diff --git a/src/bsp_simple.tcc b/src/bsp_simple.tcc index 0dc41e0..6b74db4 100644 --- a/src/bsp_simple.tcc +++ b/src/bsp_simple.tcc @@ -98,7 +98,19 @@ namespace CosmoTool *(*i) = current; allocated.push(current); - } + } + + template + bool BSP::inside(const typename space_t::coord_t& p) const + { + node_t *current = root; + + do + { + } + while(); + current + } }; diff --git a/src/fourier/base_types.hpp b/src/fourier/base_types.hpp new file mode 100644 index 0000000..9a02a7e --- /dev/null +++ b/src/fourier/base_types.hpp @@ -0,0 +1,102 @@ +#ifndef __BASE_FOURIER_TYPES_HPP +#define __BASE_FOURIER_TYPES_HPP + +#include +#include +#include + +namespace CosmoTool +{ + template + class FourierMap + { + protected: + FourierMap() {} + + public: + typedef Eigen::Matrix VecType; + typedef Eigen::Map MapType; + typedef Eigen::Map ConstMapType; + + virtual ~FourierMap() {} + + virtual const T* data() const = 0; + virtual T* data() = 0; + + virtual long size() const = 0; + + MapType eigen() + { + return MapType(data(), size()); + } + + ConstMapType eigen() const + { + return ConstMapType(data(), size()); + } + + void scale(const T& factor) + { + MapType m(data(), size()); + m *= factor; + } + + void scale(const FourierMap *map2) + { + assert(size() == map2->size()); + MapType m(data(), size()); + MapType m2(map2->data(), map2->size()); + m *= m2; + } + + void add(const T& factor) + { + eigen() += factor; + } + + void add(const FourierMap *map2) + { + assert(size() == map2->size()); + MapType m(data(), size()); + MapType m2(map2->data(), map2->size()); + + eigen() += map2->eigen(); + } + + virtual FourierMap *copy() const + { + FourierMap *m = this->mimick(); + + m->eigen() = this->eigen(); + return m; + } + + virtual FourierMap *mimick() const = 0; + }; + + template + class FourierTransform + { + protected: + FourierTransform() {} + public: + virtual ~FourierTransform() { } + + virtual const FourierMap >& fourierSpace() const = 0; + virtual FourierMap >& fourierSpace() = 0; + + virtual const FourierMap& realSpace() const = 0; + virtual FourierMap& realSpace() = 0; + + virtual FourierTransform *mimick() const = 0; + + virtual void analysis() = 0; + virtual void synthesis() = 0; + virtual void analysis_conjugate() = 0; + virtual void synthesis_conjugate() = 0; + }; + + +}; + +#endif diff --git a/src/fourier/euclidian.hpp b/src/fourier/euclidian.hpp new file mode 100644 index 0000000..0f40e1a --- /dev/null +++ b/src/fourier/euclidian.hpp @@ -0,0 +1,200 @@ +#ifndef __COSMOTOOL_FOURIER_EUCLIDIAN_HPP +#define __COSMOTOOL_FOURIER_EUCLIDIAN_HPP + +#include +#include +#include "base_types.hpp" +#include "fft/fftw_calls.hpp" + +namespace CosmoTool +{ + + template + class EuclidianFourierMap: public FourierMap + { + private: + boost::shared_ptr m_data; + std::vector m_dims; + long m_size; + public: + EuclidianFourierMap(boost::shared_ptr indata, std::vector indims) + { + m_data = indata; + m_dims = indims; + m_size = 1; + for (int i = 0; i < m_dims.size(); i++) + m_size *= m_dims[i]; + } + + virtual ~EuclidianFourierMap() + { + } + + virtual const T *data() const { return m_data.get(); } + virtual T *data() { return m_data.get(); } + virtual long size() const { return m_size; } + + virtual FourierMap *copy() const + { + FourierMap *m = this->mimick(); + m->eigen() = this->eigen(); + return m; + } + + virtual FourierMap *mimick() const + { + return new EuclidianFourierMap( + boost::shared_ptr((T *)fftw_malloc(sizeof(T)*m_size), + std::ptr_fun(fftw_free)), + m_dims); + } + }; + + + template + class EuclidianFourierTransform: public FourierTransform + { + private: + typedef FFTW_Calls calls; + EuclidianFourierMap *realMap; + EuclidianFourierMap > *fourierMap; + typename calls::plan_type m_analysis, m_synthesis; + double volume; + long N; + std::vector m_dims; + std::vector m_L; + public: + EuclidianFourierTransform(const std::vector& dims, const std::vector& L) + { + assert(L.size() == dims.size()); + + m_dims = dims; + m_L = L; + + N = 1; + volume = 1; + for (int i = 0; i < dims.size(); i++) + { + N *= dims[i]; + volume *= L[i]; + } + + realMap = new EuclidianFourierMap( + boost::shared_ptr(calls::alloc_real(N), + std::ptr_fun(calls::free)), + dims); + fourierMap = new EuclidianFourierMap >( + boost::shared_ptr >((std::complex*)calls::alloc_complex(N), + std::ptr_fun(calls::free)), + dims); + m_analysis = calls::plan_dft_r2c(dims.size(), &dims[0], + realMap->data(), (typename calls::complex_type *)fourierMap->data(), + FFTW_MEASURE); + m_synthesis = calls::plan_dft_c2r(dims.size(), &dims[0], + (typename calls::complex_type *)fourierMap->data(), realMap->data(), + FFTW_MEASURE); + } + + virtual ~EuclidianFourierTransform() + { + delete realMap; + delete fourierMap; + calls::destroy_plan(m_synthesis); + calls::destroy_plan(m_analysis); + } + + void synthesis() + { + calls::execute(m_synthesis); + realMap->scale(1/volume); + } + + void analysis() + { + calls::execute(m_analysis); + fourierMap->scale(volume/N); + } + + void synthesis_conjugate() + { + calls::execute(m_analysis); + fourierMap->scale(1/volume); + } + + void analysis_conjugate() + { + calls::execute(m_synthesis); + realMap->scale(volume/N); + } + + const FourierMap >& fourierSpace() const + { + return *fourierMap; + } + + FourierMap >& fourierSpace() + { + return *fourierMap; + } + + const FourierMap& realSpace() const + { + return *realMap; + } + + FourierMap& realSpace() + { + return *realMap; + } + + FourierTransform *mimick() const + { + return new EuclidianFourierTransform(m_dims, m_L); + } + }; + + template + class EuclidianFourierTransform_2d: public EuclidianFourierTransform + { + private: + template + static std::vector make_2d_vector(T2 a, T2 b) + { + T2 arr[2] = { a, b}; + return std::vector(&arr[0], &arr[2]); + } + public: + EuclidianFourierTransform_2d(int Nx, int Ny, double Lx, double Ly) + : EuclidianFourierTransform(make_2d_vector(Nx, Ny), make_2d_vector(Lx, Ly)) + { + } + + virtual ~EuclidianFourierTransform_2d() {} + + }; + + template + class EuclidianFourierTransform_3d: public EuclidianFourierTransform + { + private: + template + static std::vector make_3d_vector(T2 a, T2 b, T2 c) + { + T2 arr[2] = { a, b, c}; + return std::vector(&arr[0], &arr[3]); + } + + public: + EuclidianFourierTransform_3d(int Nx, int Ny, int Nz, double Lx, double Ly, double Lz) + : EuclidianFourierTransform(make_3d_vector(Nx, Ny, Nz), make_3d_vector(Lx, Ly, Lz)) + { + } + + virtual ~EuclidianFourierTransform_3d() {} + }; + + + +}; + +#endif diff --git a/src/fourier/fft/fftw_calls.hpp b/src/fourier/fft/fftw_calls.hpp new file mode 100644 index 0000000..0106055 --- /dev/null +++ b/src/fourier/fft/fftw_calls.hpp @@ -0,0 +1,75 @@ +#ifndef __FFTW_UNIFIED_CALLS_HPP +#define __FFTW_UNIFIED_CALLS_HPP + +#include + +namespace CosmoTool +{ + +static inline void init_fftw_wisdom() +{ + fftw_import_system_wisdom(); + fftw_import_wisdom_from_filename("fft_wisdom"); +} + +static inline void save_fftw_wisdom() +{ + fftw_export_wisdom_to_filename("fft_wisdom"); +} + +template class FFTW_Calls {}; + + +#define FFTW_CALLS_BASE(rtype, prefix) \ + template<> \ +class FFTW_Calls { \ +public: \ + typedef rtype real_type; \ + typedef prefix ## _complex complex_type; \ + typedef prefix ## _plan plan_type; \ + \ + static complex_type *alloc_complex(int N) { return prefix ## _alloc_complex(N); } \ + static real_type *alloc_real(int N) { return prefix ## _alloc_real(N); } \ + static void free(void *p) { fftw_free(p); } \ +\ + static void execute(plan_type p) { prefix ## _execute(p); } \ + static plan_type plan_dft_r2c_2d(int Nx, int Ny, \ + real_type *in, complex_type *out, \ + unsigned flags) \ + { \ + return prefix ## _plan_dft_r2c_2d(Nx, Ny, in, out, \ + flags); \ + } \ + static plan_type plan_dft_c2r_2d(int Nx, int Ny, \ + complex_type *in, real_type *out, \ + unsigned flags) \ + { \ + return prefix ## _plan_dft_c2r_2d(Nx, Ny, in, out, \ + flags); \ + } \ + static plan_type plan_dft_r2c_3d(int Nx, int Ny, int Nz, \ + real_type *in, complex_type *out, \ + unsigned flags) \ + { \ + return prefix ## _plan_dft_r2c_3d(Nx, Ny, Nz, in, out, flags); \ + } \ + static plan_type plan_dft_r2c(int rank, const int *n, real_type *in, \ + complex_type *out, unsigned flags) \ + { \ + return prefix ## _plan_dft_r2c(rank, n, in, out, flags); \ + } \ + static plan_type plan_dft_c2r(int rank, const int *n, complex_type *in, \ + real_type *out, unsigned flags) \ + { \ + return prefix ## _plan_dft_c2r(rank, n, in, out, flags); \ + } \ + static void destroy_plan(plan_type plan) { prefix ## _destroy_plan(plan); } \ +} + + +FFTW_CALLS_BASE(double, fftw); +FFTW_CALLS_BASE(float, fftwf); + +}; + +#endif diff --git a/src/fourier/healpix.hpp b/src/fourier/healpix.hpp new file mode 100644 index 0000000..1759a78 --- /dev/null +++ b/src/fourier/healpix.hpp @@ -0,0 +1,135 @@ +#ifndef __COSMOTOOL_FOURIER_HEALPIX_HPP +#define __COSMOTOOL_FOURIER_HEALPIX_HPP + +#include +#include +#include +#include +#include + +namespace CosmoTool +{ + + template + class HealpixFourierMap: public FourierMap, public Healpix_Base + { + private: + T *m_data; + Eigen::aligned_allocator alloc; + public: + HealpixFourierMap(long nSide) + : Healpix_Base(RING, nSide, SET_NSIDE) + { + m_data = alloc.allocate(Npix); + } + + virtual ~HealpixFourierMap() + { + alloc.deallocate(m_data); + } + + virtual const T* data() const { return m_data; } + virtual T *data() { return m_data; } + virtual long size() const { return Npix(); } + + virtual FourierMap *mimick() const + { + return new HealpixFourierMap(Nside()); + } + }; + + + template + class HealpixFourierALM: public FourierMap >, public Alm_Base + { + private: + std::complex *alms; + long size; + Eigen::aligned_allocator > alloc; + public: + HealpixFourierALM(long Lmax, long Mmax) + : Alm_Base(Lmax, Mmax) + { + size = Num_Alms(Lmax, Mmax); + alms = alloc.allocate(size); + } + + virtual ~HealpixFourierALM() + { + alloc.deallocate(alms); + } + + virtual const T* data() const { return alms; } + virtual T * data() { return alms;} + virtual long size() const { return size; } + + virtual FourierMap *mimick() const + { + return new HealpixFourierALM(Lmax(), Mmax()); + } + }; + + template + class HealpixFourierTransform: public FourierTransform + { + private: + HealpixFourierMap realMap; + HealpixFourierALM fourierMap; + psht_joblist jobs; + public: + HealpixFourierTransform(long nSide, long Lmax, long Mmax) + : realMap(nSide), fourierMap(Lmax, Mmax) + { + jobs.set_Healpix_geometry(nSide); + jobs.set_triangular_alm_info(Lmax, Mmax); + } + + virtual ~HealpixFourierTransform() {} + + virtual const FourierMap >& fourierSpace() const { return fourierMap; } + + virtual FourierMap >& fourierSpace() { return fourierMap; } + + virtual const FourierMap& realSpace() const { return realMap; } + + virtual FourierMap& realSpace() { return realMap; } + + virtual FourierTransform *mimick() const + { + return new HealpixFourierTransform(realMap.Nside(), fourierMap.Lmax(), fourierMap.Mmax()); + } + + virtual void analysis() + { + jobs.add_map2alm(realMap.data(), + reinterpret_cast *>(fourierMap.data()), + false); + jobs.execute(); + jobs.clear_jobs(); + } + + virtual void synthesis() + { + jobs.add_alm2map(reinterpret_cast *>(fourierMap.data()), + realMap.data(), + false); + jobs.execute(); + jobs.clear_jobs(); + } + + virtual void analysis_conjugate() + { + synthesis(); + realMap.scale(4*M_PI/realMap.Npix()); + } + + virtual void synthesis_conjugate() + { + analysis(); + fourierMap.scale(realMap.Npix()/(4*M_PI)); + } + + }; +}; + +#endif diff --git a/src/yorick.cpp b/src/yorick_nc3.cpp similarity index 98% rename from src/yorick.cpp rename to src/yorick_nc3.cpp index ac8556a..d760009 100644 --- a/src/yorick.cpp +++ b/src/yorick_nc3.cpp @@ -1,5 +1,11 @@ +#include "ctool_netcdf_ver.hpp" #include "config.hpp" +#ifdef NETCDFCPP4 +#include +using namespace netCDF +#else #include +#endif #include #include "yorick.hpp" #include diff --git a/src/yorick_nc4.cpp b/src/yorick_nc4.cpp new file mode 100644 index 0000000..8bdeda0 --- /dev/null +++ b/src/yorick_nc4.cpp @@ -0,0 +1,237 @@ +#include "ctool_netcdf_ver.hpp" +#include "config.hpp" +#include +using namespace netCDF; +#include +#include "yorick.hpp" +#include + +using namespace CosmoTool; +using namespace std; + +class NetCDF_handle +{ +public: + NcFile *outFile; + NcVar curVar; + vector curPos; + vector counts; + vector dimList; + uint32_t rank; + + NetCDF_handle(NcFile *f, NcVar v, vector& dimList, uint32_t rank); + virtual ~NetCDF_handle(); +}; + +NetCDF_handle::NetCDF_handle(NcFile *f, NcVar v, vector& dimList, uint32_t rank) +{ + this->outFile = f; + this->curVar = v; + this->dimList = dimList; + this->rank = rank; + this->counts.resize(rank); + this->curPos.resize(rank); + + for (long i = 0; i < rank; i++) + this->curPos[i] = 0; + + for (long i = 0; i < rank; i++) + this->counts[i] = 1; +} + +NetCDF_handle::~NetCDF_handle() +{ + delete outFile; +} + +template +class InputGenCDF: public NetCDF_handle, public ProgressiveInputImpl +{ +public: + InputGenCDF(NcFile *f, NcVar v, vector& dimList, uint32_t rank) + : NetCDF_handle(f,v,dimList,rank) + {} + virtual ~InputGenCDF() {} + + virtual T read() + { + T a; + + curVar.getVar(curPos, counts, &a); + + curPos[rank-1]++; + for (long i = rank-1; i >= 1; i--) + { + if (curPos[i] == dimList[i].getSize()) + { + curPos[i-1]++; + curPos[i] = 0; + } + } + return a; + } + + virtual void seek(uint32_t *pos) + { + for (long i = rank-1; i >= 0; i--) + curPos[i] = pos[rank-1-i]; + } +}; + +template +class OutputGenCDF: public NetCDF_handle, public ProgressiveOutputImpl +{ +public: + OutputGenCDF(NcFile *f, NcVar v, vector& dimList, uint32_t rank) + : NetCDF_handle(f,v,dimList,rank) + {} + virtual ~OutputGenCDF() {} + + virtual void put(T a) + { + curVar.putVar(curPos, counts, &a); + + curPos[rank-1]++; + for (long i = rank-1; i >= 1; i--) + { + if (curPos[i] == dimList[i].getSize()) + { + curPos[i-1]++; + curPos[i] = 0; + } + } + } +}; + +template NcType& get_NetCDF_type(); + +#define IMPL_TYPE(T,ncT) \ +template<> \ +NcType& get_NetCDF_type() \ +{ \ + return ncT; \ +} + +IMPL_TYPE(int,ncInt); +IMPL_TYPE(unsigned int,ncInt); +IMPL_TYPE(double,ncDouble); +IMPL_TYPE(float,ncFloat); + +namespace CosmoTool { + template + ProgressiveOutput + ProgressiveOutput::saveArrayProgressive(const std::string& fname, uint32_t *dimList, + uint32_t rank) + { + NcFile *f = new NcFile(fname, NcFile::replace); + + vector dimArray; + for (uint32_t i = 0; i < rank; i++) + { + char dimName[255]; + + sprintf(dimName, "dim%d", i); + dimArray.push_back(f->addDim(dimName, dimList[rank-1-i])); + } + + NcVar v = f->addVar("array", get_NetCDF_type(), dimArray); + + vector ldimList; + + for (uint32_t i = 0; i < rank; i++) + ldimList.push_back(dimArray[rank-1-i]); + + OutputGenCDF *impl = new OutputGenCDF(f, v, ldimList, rank); + return ProgressiveOutput(impl); + } + + template + ProgressiveInput + ProgressiveInput::loadArrayProgressive(const std::string& fname, uint32_t *&dimList, + uint32_t& rank) + { + NcFile *f = new NcFile(fname, NcFile::read); + + NcVar v = f->getVar("array"); + + rank = v.getDimCount(); + vector vdimlist = v.getDims(); + dimList = new uint32_t[rank]; + for (uint32_t i = 0; i < rank; i++) + { + dimList[rank-i-1] = vdimlist[i].getSize(); + } + InputGenCDF *impl = new InputGenCDF(f, v, vdimlist, rank); + + return ProgressiveInput(impl); + } + + template + void saveArray(const std::string& fname, + T *array, uint32_t *dimList, uint32_t rank) + { + NcFile f(fname.c_str(), NcFile::replace); + + vector dimArray; + for (uint32_t i = 0; i < rank; i++) + { + char dimName[255]; + + sprintf(dimName, "dim%d", i); + dimArray.push_back(f.addDim(dimName, dimList[i])); + } + + NcVar v = f.addVar("array", get_NetCDF_type(), dimArray); + + v.putVar(array); + } + + template + void loadArray(const std::string& fname, + T*&array, uint32_t *&dimList, uint32_t& rank) + throw (NoSuchFileException) + { + NcFile f(fname.c_str(), NcFile::read); + + //if (!f.is_valid()) + // throw NoSuchFileException(fname); + + NcVar v = f.getVar("array"); + vector dims = v.getDims(); + rank = v.getDimCount(); + uint32_t fullSize = 1; + dimList = new uint32_t[rank]; + for (int i = 0; i < rank; i++) + { + dimList[i] = dims[i].getSize(); + fullSize *= dimList[i]; + } + if (fullSize != 0) { + array = new T[fullSize]; + v.getVar(array); + } + } + + template class ProgressiveInput; + template class ProgressiveInput; + template class ProgressiveInput; + + template class ProgressiveOutput; + template class ProgressiveOutput; + template class ProgressiveOutput; + + template void loadArray(const std::string& fname, + int*& array, uint32_t *&dimList, uint32_t& rank); + template void loadArray(const std::string& fname, + float*& array, uint32_t *&dimList, uint32_t& rank); + template void loadArray(const std::string& fname, + double*& array, uint32_t *&dimList, uint32_t& rank); + + template void saveArray(const std::string& fname, + int *array, uint32_t *dimList, uint32_t rank); + template void saveArray(const std::string& fname, + float *array, uint32_t *dimList, uint32_t rank); + template void saveArray(const std::string& fname, + double *array, uint32_t *dimList, uint32_t rank); + +}