From c27efd2b833fe19087b1f69d08b304eb28fc3287 Mon Sep 17 00:00:00 2001 From: Berenger Bramas <bbramas@mpcdf.mpg.de> Date: Fri, 19 May 2017 11:47:55 +0200 Subject: [PATCH] Add a sampling method -- update to be generic against the field -- need to update NSVEparticles::do_stats --- bfps/cpp/full_code/NSVEparticles.cpp | 13 +- .../particles/abstract_particles_output.hpp | 8 +- .../particles/abstract_particles_system.hpp | 21 +++ ...cles_distr.hpp => particles_distr_mpi.hpp} | 70 ++++------ .../particles/particles_field_computer.hpp | 22 +--- .../particles_output_sampling_hdf5.hpp | 123 ++++++++++++++++++ bfps/cpp/particles/particles_sampling.hpp | 40 ++++++ bfps/cpp/particles/particles_system.hpp | 70 ++++++++-- .../particles/particles_system_builder.hpp | 27 ++-- setup.py | 6 +- 10 files changed, 308 insertions(+), 92 deletions(-) rename bfps/cpp/particles/{abstract_particles_distr.hpp => particles_distr_mpi.hpp} (93%) create mode 100644 bfps/cpp/particles/particles_output_sampling_hdf5.hpp create mode 100644 bfps/cpp/particles/particles_sampling.hpp diff --git a/bfps/cpp/full_code/NSVEparticles.cpp b/bfps/cpp/full_code/NSVEparticles.cpp index 9c0603b1..35cbf47d 100644 --- a/bfps/cpp/full_code/NSVEparticles.cpp +++ b/bfps/cpp/full_code/NSVEparticles.cpp @@ -2,7 +2,7 @@ #include <cmath> #include "NSVEparticles.hpp" #include "scope_timer.hpp" - +#include "particles/particles_sampling.hpp" template <typename rnumber> int NSVEparticles<rnumber>::initialize(void) @@ -69,9 +69,14 @@ int NSVEparticles<rnumber>::do_stats() // fluid stats go here this->NSVE<rnumber>::do_stats(); // particle sampling should go here - //if (this->iteration % this->niter_part == 0) - //{ - //} +// if (this->iteration % this->niter_part == 0) +// { +// sample_from_particles_system(*this->fs->cvelocity,// field to save TODO +// this->ps, +// 0, // hdf5 datagroup TODO +// "TODO", // dataset basename TODO +// this->particles_output_writer_mpi->getTotalNbParticles()); +// } return EXIT_SUCCESS; } diff --git a/bfps/cpp/particles/abstract_particles_output.hpp b/bfps/cpp/particles/abstract_particles_output.hpp index dfc8ec37..a6eccaea 100644 --- a/bfps/cpp/particles/abstract_particles_output.hpp +++ b/bfps/cpp/particles/abstract_particles_output.hpp @@ -45,10 +45,6 @@ protected: return mpi_com_writer; } - partsize_t getTotalNbParticles() const { - return total_nb_particles; - } - int getNbRhs() const { return nb_rhs; } @@ -126,6 +122,10 @@ public: if(current_is_involved){ AssertMpi( MPI_Comm_free(&mpi_com_writer) ); } + } + + partsize_t getTotalNbParticles() const { + return total_nb_particles; } void releaseMemory(){ diff --git a/bfps/cpp/particles/abstract_particles_system.hpp b/bfps/cpp/particles/abstract_particles_system.hpp index 33a94513..6961eabc 100644 --- a/bfps/cpp/particles/abstract_particles_system.hpp +++ b/bfps/cpp/particles/abstract_particles_system.hpp @@ -3,6 +3,12 @@ #include <memory> +//- Not generic to enable sampling begin +#include "field.hpp" +#include "kspace.hpp" +//- Not generic to enable sampling end + + template <class partsize_t, class real_number> class abstract_particles_system { public: @@ -27,6 +33,21 @@ public: virtual partsize_t getLocalNbParticles() const = 0; virtual int getNbRhs() const = 0; + + //- Not generic to enable sampling begin + virtual void sample_compute_field(const field<float, FFTW, ONE>& sample_field, + real_number sample_rhs[]) = 0; + virtual void sample_compute_field(const field<float, FFTW, THREE>& sample_field, + real_number sample_rhs[]) = 0; + virtual void sample_compute_field(const field<float, FFTW, THREExTHREE>& sample_field, + real_number sample_rhs[]) = 0; + virtual void sample_compute_field(const field<double, FFTW, ONE>& sample_field, + real_number sample_rhs[]) = 0; + virtual void sample_compute_field(const field<double, FFTW, THREE>& sample_field, + real_number sample_rhs[]) = 0; + virtual void sample_compute_field(const field<double, FFTW, THREExTHREE>& sample_field, + real_number sample_rhs[]) = 0; + //- Not generic to enable sampling end }; #endif diff --git a/bfps/cpp/particles/abstract_particles_distr.hpp b/bfps/cpp/particles/particles_distr_mpi.hpp similarity index 93% rename from bfps/cpp/particles/abstract_particles_distr.hpp rename to bfps/cpp/particles/particles_distr_mpi.hpp index b012f824..48559518 100644 --- a/bfps/cpp/particles/abstract_particles_distr.hpp +++ b/bfps/cpp/particles/particles_distr_mpi.hpp @@ -1,5 +1,5 @@ -#ifndef ABSTRACT_PARTICLES_DISTR_HPP -#define ABSTRACT_PARTICLES_DISTR_HPP +#ifndef PARTICLES_DISTR_MPI_HPP +#define PARTICLES_DISTR_MPI_HPP #include <mpi.h> @@ -14,8 +14,8 @@ #include "particles_utils.hpp" -template <class partsize_t, class real_number, int size_particle_positions, int size_particle_rhs, int size_particle_index> -class abstract_particles_distr { +template <class partsize_t, class real_number> +class particles_distr_mpi { protected: static const int MaxNbRhs = 100; @@ -92,7 +92,7 @@ protected: public: //////////////////////////////////////////////////////////////////////////// - abstract_particles_distr(MPI_Comm in_current_com, + particles_distr_mpi(MPI_Comm in_current_com, const std::pair<int,int>& in_current_partitions, const std::array<size_t,3>& in_field_grid_dim) : current_com(in_current_com), @@ -130,11 +130,14 @@ public: assert(int(field_grid_dim[IDX_Z]) == partition_interval_offset_per_proc[nb_processes_involved]); } - virtual ~abstract_particles_distr(){} + virtual ~particles_distr_mpi(){} //////////////////////////////////////////////////////////////////////////// - void compute_distr(const partsize_t current_my_nb_particles_per_partition[], + template <class computer_class, class field_class, int size_particle_positions, int size_particle_rhs> + void compute_distr(computer_class& in_computer, + field_class& in_field, + const partsize_t current_my_nb_particles_per_partition[], const real_number particles_positions[], real_number particles_current_rhs[], const int interpolation_size){ @@ -377,10 +380,10 @@ public: assert(descriptor.toCompute != nullptr); descriptor.results.reset(new real_number[NbParticlesToReceive*size_particle_rhs]); - init_result_array(descriptor.results.get(), NbParticlesToReceive); + in_computer.template init_result_array<size_particle_rhs>(descriptor.results.get(), NbParticlesToReceive); if(more_than_one_thread == false){ - apply_computation(descriptor.toCompute.get(), descriptor.results.get(), NbParticlesToReceive); + in_computer.template apply_computation<field_class, size_particle_rhs>(in_field, descriptor.toCompute.get(), descriptor.results.get(), NbParticlesToReceive); } else{ TIMEZONE_OMP_INIT_PRETASK(timeZoneTaskKey) @@ -392,8 +395,8 @@ public: #pragma omp task default(shared) firstprivate(ptr_descriptor, idxPart, sizeToDo) priority(10) \ TIMEZONE_OMP_PRAGMA_TASK_KEY(timeZoneTaskKey) { - TIMEZONE_OMP_TASK("apply_computation", timeZoneTaskKey); - apply_computation(&ptr_descriptor->toCompute[idxPart*size_particle_positions], + TIMEZONE_OMP_TASK("in_computer.apply_computation", timeZoneTaskKey); + in_computer.template apply_computation<field_class, size_particle_rhs>(in_field, &ptr_descriptor->toCompute[idxPart*size_particle_positions], &ptr_descriptor->results[idxPart*size_particle_rhs], sizeToDo); } } @@ -425,13 +428,13 @@ public: if(descriptor.isLower){ TIMEZONE("reduce"); assert(descriptor.toRecvAndMerge != nullptr); - reduce_particles_rhs(&particles_current_rhs[0], descriptor.toRecvAndMerge.get(), descriptor.nbParticlesToSend); + in_computer.template reduce_particles_rhs<size_particle_rhs>(&particles_current_rhs[0], descriptor.toRecvAndMerge.get(), descriptor.nbParticlesToSend); descriptor.toRecvAndMerge.release(); } else { TIMEZONE("reduce"); assert(descriptor.toRecvAndMerge != nullptr); - reduce_particles_rhs(&particles_current_rhs[(current_offset_particles_for_partition[current_partition_size]-descriptor.nbParticlesToSend)*size_particle_rhs], + in_computer.template reduce_particles_rhs<size_particle_rhs>(&particles_current_rhs[(current_offset_particles_for_partition[current_partition_size]-descriptor.nbParticlesToSend)*size_particle_rhs], descriptor.toRecvAndMerge.get(), descriptor.nbParticlesToSend); descriptor.toRecvAndMerge.release(); } @@ -452,8 +455,8 @@ public: // Low priority to help master thread when possible #pragma omp task default(shared) firstprivate(idxPart, sizeToDo) priority(0) TIMEZONE_OMP_PRAGMA_TASK_KEY(timeZoneTaskKey) { - TIMEZONE_OMP_TASK("apply_computation", timeZoneTaskKey); - apply_computation(&particles_positions[idxPart*size_particle_positions], + TIMEZONE_OMP_TASK("in_computer.apply_computation", timeZoneTaskKey); + in_computer.template apply_computation<field_class, size_particle_rhs>(in_field, &particles_positions[idxPart*size_particle_positions], &particles_current_rhs[idxPart*size_particle_rhs], sizeToDo); } @@ -470,13 +473,13 @@ public: if(descriptor.isLower){ TIMEZONE("reduce_later"); assert(descriptor.toRecvAndMerge != nullptr); - reduce_particles_rhs(&particles_current_rhs[0], descriptor.toRecvAndMerge.get(), descriptor.nbParticlesToSend); + in_computer.template reduce_particles_rhs<size_particle_rhs>(&particles_current_rhs[0], descriptor.toRecvAndMerge.get(), descriptor.nbParticlesToSend); descriptor.toRecvAndMerge.release(); } else { TIMEZONE("reduce_later"); assert(descriptor.toRecvAndMerge != nullptr); - reduce_particles_rhs(&particles_current_rhs[(current_offset_particles_for_partition[current_partition_size]-descriptor.nbParticlesToSend)*size_particle_rhs], + in_computer.template reduce_particles_rhs<size_particle_rhs>(&particles_current_rhs[(current_offset_particles_for_partition[current_partition_size]-descriptor.nbParticlesToSend)*size_particle_rhs], descriptor.toRecvAndMerge.get(), descriptor.nbParticlesToSend); descriptor.toRecvAndMerge.release(); } @@ -489,7 +492,7 @@ public: TIMEZONE("compute-my_compute"); // Compute my particles if(myTotalNbParticles){ - apply_computation(particles_positions, particles_current_rhs, myTotalNbParticles); + in_computer.template apply_computation<field_class, size_particle_rhs>(in_field, particles_positions, particles_current_rhs, myTotalNbParticles); } } @@ -497,20 +500,12 @@ public: assert(mpiRequests.size() == 0); } - //////////////////////////////////////////////////////////////////////////// - - virtual void init_result_array(real_number particles_current_rhs[], - const partsize_t nb_particles) const = 0; - virtual void apply_computation(const real_number particles_positions[], - real_number particles_current_rhs[], - const partsize_t nb_particles) const = 0; - virtual void reduce_particles_rhs(real_number particles_current_rhs[], - const real_number extra_particles_current_rhs[], - const partsize_t nb_particles) const = 0; //////////////////////////////////////////////////////////////////////////// - void redistribute(partsize_t current_my_nb_particles_per_partition[], + template <class computer_class, int size_particle_positions, int size_particle_rhs, int size_particle_index> + void redistribute(computer_class& in_computer, + partsize_t current_my_nb_particles_per_partition[], partsize_t* nb_particles, std::unique_ptr<real_number[]>* inout_positions_particles, std::unique_ptr<real_number[]> inout_rhs_particles[], const int in_nb_rhs, @@ -533,7 +528,7 @@ public: // Find particles outside my interval const partsize_t nbOutLower = particles_utils::partition_extra<partsize_t, size_particle_positions>(&(*inout_positions_particles)[0], current_my_nb_particles_per_partition[0], [&](const real_number val[]){ - const int partition_level = pbc_field_layer(val[IDX_Z], IDX_Z); + const int partition_level = in_computer.pbc_field_layer(val[IDX_Z], IDX_Z); assert(partition_level == current_partition_interval.first || partition_level == (current_partition_interval.first-1+int(field_grid_dim[IDX_Z]))%int(field_grid_dim[IDX_Z]) || partition_level == (current_partition_interval.first+1)%int(field_grid_dim[IDX_Z])); @@ -558,7 +553,7 @@ public: &(*inout_positions_particles)[(current_offset_particles_for_partition[current_partition_size-1]+offesetOutLow)*size_particle_positions], myTotalNbParticles - (current_offset_particles_for_partition[current_partition_size-1]+offesetOutLow), [&](const real_number val[]){ - const int partition_level = pbc_field_layer(val[IDX_Z], IDX_Z); + const int partition_level = in_computer.pbc_field_layer(val[IDX_Z], IDX_Z); assert(partition_level == (current_partition_interval.second-1) || partition_level == ((current_partition_interval.second-1)-1+int(field_grid_dim[IDX_Z]))%int(field_grid_dim[IDX_Z]) || partition_level == ((current_partition_interval.second-1)+1)%int(field_grid_dim[IDX_Z])); @@ -807,7 +802,7 @@ public: myTotalNbParticles,current_partition_size, current_my_nb_particles_per_partition, current_offset_particles_for_partition.get(), [&](const real_number& z_pos){ - const int partition_level = pbc_field_layer(z_pos, IDX_Z); + const int partition_level = in_computer.pbc_field_layer(z_pos, IDX_Z); assert(current_partition_interval.first <= partition_level && partition_level < current_partition_interval.second); return partition_level - current_partition_interval.first; }, @@ -829,7 +824,7 @@ public: assert(current_my_nb_particles_per_partition[idxPartition] == current_offset_particles_for_partition[idxPartition+1] - current_offset_particles_for_partition[idxPartition]); for(partsize_t idx = current_offset_particles_for_partition[idxPartition] ; idx < current_offset_particles_for_partition[idxPartition+1] ; ++idx){ - assert(pbc_field_layer((*inout_positions_particles)[idx*3+IDX_Z], IDX_Z)-current_partition_interval.first == idxPartition); + assert(in_computer.pbc_field_layer((*inout_positions_particles)[idx*3+IDX_Z], IDX_Z)-current_partition_interval.first == idxPartition); } } } @@ -838,15 +833,6 @@ public: assert(mpiRequests.size() == 0); } - - virtual int pbc_field_layer(const real_number& a_z_pos, const int idx_dim) const = 0; - - //////////////////////////////////////////////////////////////////////////// - - virtual void move_particles(real_number particles_positions[], - const partsize_t nb_particles, - const std::unique_ptr<real_number[]> particles_current_rhs[], - const int nb_rhs, const real_number dt) const = 0; }; #endif diff --git a/bfps/cpp/particles/particles_field_computer.hpp b/bfps/cpp/particles/particles_field_computer.hpp index 1c7c7e77..f68f2fc0 100644 --- a/bfps/cpp/particles/particles_field_computer.hpp +++ b/bfps/cpp/particles/particles_field_computer.hpp @@ -4,15 +4,13 @@ #include <array> #include <utility> -#include "abstract_particles_distr.hpp" #include "scope_timer.hpp" #include "particles_utils.hpp" template <class partsize_t, class real_number, class interpolator_class, - int interp_neighbours, - class positions_updater_class> + int interp_neighbours> class particles_field_computer { const std::array<int,3> field_grid_dim; @@ -20,8 +18,6 @@ class particles_field_computer { const interpolator_class& interpolator; - const positions_updater_class positions_updater; - const std::array<real_number,3> spatial_box_width; const std::array<real_number,3> spatial_box_offset; const std::array<real_number,3> box_step_width; @@ -33,11 +29,10 @@ public: particles_field_computer(const std::array<size_t,3>& in_field_grid_dim, const std::pair<int,int>& in_current_partitions, const interpolator_class& in_interpolator, - const field_class& in_field, const std::array<real_number,3>& in_spatial_box_width, const std::array<real_number,3>& in_spatial_box_offset, const std::array<real_number,3>& in_box_step_width) : field_grid_dim({{int(in_field_grid_dim[0]),int(in_field_grid_dim[1]),int(in_field_grid_dim[2])}}), current_partition_interval(in_current_partitions), - interpolator(in_interpolator), field(in_field), positions_updater(), + interpolator(in_interpolator), spatial_box_width(in_spatial_box_width), spatial_box_offset(in_spatial_box_offset), box_step_width(in_box_step_width){ deriv[IDX_X] = 0; deriv[IDX_Y] = 0; @@ -174,19 +169,6 @@ public: } } - //////////////////////////////////////////////////////////////////////// - /// Update position - //////////////////////////////////////////////////////////////////////// - - void move_particles(real_number particles_positions[], - const partsize_t nb_particles, - const std::unique_ptr<real_number[]> particles_current_rhs[], - const int nb_rhs, const real_number dt) const { - TIMEZONE("particles_field_computer::move_particles"); - positions_updater.move_particles(particles_positions, nb_particles, - particles_current_rhs, nb_rhs, dt); - } - //////////////////////////////////////////////////////////////////////// /// Re-distribution related //////////////////////////////////////////////////////////////////////// diff --git a/bfps/cpp/particles/particles_output_sampling_hdf5.hpp b/bfps/cpp/particles/particles_output_sampling_hdf5.hpp new file mode 100644 index 00000000..7e9a54dd --- /dev/null +++ b/bfps/cpp/particles/particles_output_sampling_hdf5.hpp @@ -0,0 +1,123 @@ +#ifndef PARTICLES_OUTPUT_SAMPLING_HDF5_HPP +#define PARTICLES_OUTPUT_SAMPLING_HDF5_HPP + +#include "abstract_particles_output.hpp" + +#include <hdf5.h> + +template <class partsize_t, + class real_number, + int size_particle_positions, + int size_particle_rhs> +class particles_output_sampling_hdf5 : public abstract_particles_output<partsize_t, + real_number, + size_particle_positions, + size_particle_rhs>{ + using Parent = abstract_particles_output<partsize_t, + real_number, + size_particle_positions, + size_particle_rhs>; + + hid_t parent_group; + const std::string dataset_name; + const bool use_collective_io; + +public: + particles_output_sampling_hdf5(MPI_Comm in_mpi_com, + const partsize_t inTotalNbParticles, + const hid_t in_parent_group, + const std::string& in_dataset_name, + const bool in_use_collective_io = false) + : Parent(in_mpi_com, inTotalNbParticles, 1), + parent_group(in_parent_group), + dataset_name(in_dataset_name), + use_collective_io(in_use_collective_io){} + + void write( + const int idx_time_step, + const real_number* /*particles_positions*/, + const std::unique_ptr<real_number[]>* particles_rhs, + const partsize_t nb_particles, + const partsize_t particles_idx_offset) final{ + assert(Parent::isInvolved()); + + TIMEZONE("particles_output_hdf5::write"); + + assert(particles_idx_offset < Parent::getTotalNbParticles() || (particles_idx_offset == Parent::getTotalNbParticles() && nb_particles == 0)); + assert(particles_idx_offset+nb_particles <= Parent::getTotalNbParticles()); + + static_assert(std::is_same<real_number, double>::value || + std::is_same<real_number, float>::value, + "real_number must be double or float"); + const hid_t type_id = (sizeof(real_number) == 8 ? H5T_NATIVE_DOUBLE : H5T_NATIVE_FLOAT); + + hid_t plist_id = H5Pcreate(H5P_DATASET_XFER); + assert(plist_id >= 0); + { + int rethdf = H5Pset_dxpl_mpio(plist_id, use_collective_io ? H5FD_MPIO_COLLECTIVE : H5FD_MPIO_INDEPENDENT); + assert(rethdf >= 0); + } + { + assert(size_particle_rhs >= 0); + const hsize_t datacount[3] = {hsize_t(Parent::getNbRhs()), + hsize_t(Parent::total_nb_particles), + hsize_t(size_particle_rhs)}; + hid_t dataspace = H5Screate_simple(3, datacount, NULL); + assert(dataspace >= 0); + + hid_t dataset_id = H5Dcreate( parent_group, + dataset_name.c_str(), + type_id, + dataspace, + H5P_DEFAULT, + H5P_DEFAULT, + H5P_DEFAULT); + assert(dataset_id >= 0); + + assert(particles_idx_offset >= 0); + const hsize_t count[3] = { + 1, + hsize_t(nb_particles), + hsize_t(size_particle_rhs)}; + const hsize_t offset[3] = { + 0, + hsize_t(particles_idx_offset), + 0}; + hid_t memspace = H5Screate_simple(3, count, NULL); + assert(memspace >= 0); + + hid_t filespace = H5Dget_space(dataset_id); + assert(filespace >= 0); + int rethdf = H5Sselect_hyperslab( + filespace, + H5S_SELECT_SET, + offset, + NULL, + count, + NULL); + assert(rethdf >= 0); + + herr_t status = H5Dwrite( + dataset_id, + type_id, + memspace, + filespace, + plist_id, + particles_rhs[0].get()); + assert(status >= 0); + rethdf = H5Sclose(filespace); + assert(rethdf >= 0); + rethdf = H5Sclose(memspace); + assert(rethdf >= 0); + rethdf = H5Dclose(dataset_id); + assert(rethdf >= 0); + } + + { + int rethdf = H5Pclose(plist_id); + assert(rethdf >= 0); + } + } +}; + +#endif diff --git a/bfps/cpp/particles/particles_sampling.hpp b/bfps/cpp/particles/particles_sampling.hpp new file mode 100644 index 00000000..cc987f69 --- /dev/null +++ b/bfps/cpp/particles/particles_sampling.hpp @@ -0,0 +1,40 @@ +#ifndef PARTICLES_SAMPLING_HPP +#define PARTICLES_SAMPLING_HPP + +#include <memory> +#include <string> + +#include "abstract_particles_system.hpp" +#include "particles_output_sampling_hdf5.hpp" + +#include "field.hpp" +#include "kspace.hpp" + + +template <class partsize_t, class particles_rnumber, class rnumber, field_backend be, field_components fc> +void sample_from_particles_system(const field<rnumber, be, fc>& in_field, // a pointer to a field<rnumber, FFTW, fc> + std::unique_ptr<abstract_particles_system<partsize_t, particles_rnumber>>& ps, // a pointer to an particles_system<double> + hid_t gid, // an hid_t identifying an HDF5 group + const std::string& fname, + const partsize_t totalNbParticles){ +// const int size_particle_rhs = ncomp(fc); +// const partsize_t nb_particles = ps->getLocalNbParticles(); +// std::unique_ptr<particles_rnumber[]> sample_rhs(new particles_rnumber[size_particle_rhs*nb_particles]); + +// ps->sample_compute_field(in_field, sample_rhs.get()); + +// const std::string datasetname = fname + std::string("/") + std::to_string(ps->step_idx); + +// particles_output_sampling_hdf5<partsize_t, particles_rnumber, 3, size_particle_rhs> outputclass(MPI_COMM_WORLD, +// totalNbParticles, +// gid, +// datasetname); +// outputclass.save(ps->getParticlesPositions(), +// &sample_rhs, +// ps->getParticlesIndexes(), +// ps->getLocalNbParticles(), +// in_field->iteration); +} + +#endif + diff --git a/bfps/cpp/particles/particles_system.hpp b/bfps/cpp/particles/particles_system.hpp index 444f0cc7..1e5ec2dd 100644 --- a/bfps/cpp/particles/particles_system.hpp +++ b/bfps/cpp/particles/particles_system.hpp @@ -4,6 +4,7 @@ #include <array> #include "abstract_particles_system.hpp" +#include "particles_distr_mpi.hpp" #include "particles_output_hdf5.hpp" #include "particles_output_mpiio.hpp" #include "particles_field_computer.hpp" @@ -12,7 +13,7 @@ #include "scope_timer.hpp" template <class partsize_t, class real_number, class field_rnumber, class field_class, class interpolator_class, int interp_neighbours, - class size_particle_rhs> + int size_particle_rhs> class particles_system : public abstract_particles_system<partsize_t, real_number> { MPI_Comm mpi_com; @@ -21,7 +22,14 @@ class particles_system : public abstract_particles_system<partsize_t, real_numbe interpolator_class interpolator; - particles_field_computer<partsize_t, real_number, interpolator_class, field_class, interp_neighbours, particles_adams_bashforth<partsize_t, real_number, 3, size_particle_rhs>, size_particle_rhs> computer; + particles_distr_mpi<partsize_t, real_number> particles_distr; + + particles_adams_bashforth<partsize_t, real_number, 3, size_particle_rhs> positions_updater; + + using computer_class = particles_field_computer<partsize_t, real_number, interpolator_class, interp_neighbours>; + computer_class computer; + + field_class default_field; std::unique_ptr<partsize_t[]> current_my_nb_particles_per_partition; std::unique_ptr<partsize_t[]> current_offset_particles_for_partition; @@ -52,8 +60,11 @@ public: current_partition_interval({in_local_field_offset[IDX_Z], in_local_field_offset[IDX_Z] + in_local_field_dims[IDX_Z]}), partition_interval_size(current_partition_interval.second - current_partition_interval.first), interpolator(), - computer(in_mpi_com, field_grid_dim, current_partition_interval, - interpolator, in_field, in_spatial_box_width, in_spatial_box_offset, in_spatial_partition_width), + particles_distr(in_mpi_com, current_partition_interval,field_grid_dim), + positions_updater(), + computer(field_grid_dim, current_partition_interval, + interpolator, in_spatial_box_width, in_spatial_box_offset, in_spatial_partition_width), + default_field(in_field), spatial_box_width(in_spatial_box_width), spatial_partition_width(in_spatial_partition_width), my_spatial_low_limit(in_my_spatial_low_limit), my_spatial_up_limit(in_my_spatial_up_limit), my_nb_particles(0), step_idx(in_current_iteration){ @@ -65,7 +76,7 @@ public: ~particles_system(){ } - void init(abstract_particles_input<partsize_t, real_number>& particles_input){ + void init(abstract_particles_input<partsize_t, real_number>& particles_input) { TIMEZONE("particles_system::init"); my_particles_positions = particles_input.getMyParticles(); @@ -110,22 +121,65 @@ public: void compute() final { TIMEZONE("particles_system::compute"); - computer.compute_distr(current_my_nb_particles_per_partition.get(), + particles_distr.template compute_distr<computer_class, field_class, 3, size_particle_rhs>( + computer, default_field, + current_my_nb_particles_per_partition.get(), my_particles_positions.get(), my_particles_rhs.front().get(), interp_neighbours); } + template <class sample_field_class, int sample_size_particle_rhs> + void sample_compute(const sample_field_class& sample_field, + real_number sample_rhs[]) { + TIMEZONE("particles_system::compute"); + particles_distr.template compute_distr<computer_class, sample_field_class, 3, sample_size_particle_rhs>( + computer, sample_field, + current_my_nb_particles_per_partition.get(), + my_particles_positions.get(), + sample_rhs, + interp_neighbours); + } + + //- Not generic to enable sampling begin + void sample_compute_field(const field<float, FFTW, ONE>& sample_field, + real_number sample_rhs[]) final { + // sample_compute<decltype(sample_field), 1>(sample_field, sample_rhs); + } + void sample_compute_field(const field<float, FFTW, THREE>& sample_field, + real_number sample_rhs[]) final { + sample_compute<decltype(sample_field), 3>(sample_field, sample_rhs); + } + void sample_compute_field(const field<float, FFTW, THREExTHREE>& sample_field, + real_number sample_rhs[]) final { + sample_compute<decltype(sample_field), 9>(sample_field, sample_rhs); + } + void sample_compute_field(const field<double, FFTW, ONE>& sample_field, + real_number sample_rhs[]) final { + sample_compute<decltype(sample_field), 1>(sample_field, sample_rhs); + } + void sample_compute_field(const field<double, FFTW, THREE>& sample_field, + real_number sample_rhs[]) final { + sample_compute<decltype(sample_field), 3>(sample_field, sample_rhs); + } + void sample_compute_field(const field<double, FFTW, THREExTHREE>& sample_field, + real_number sample_rhs[]) final { + sample_compute<decltype(sample_field), 9>(sample_field, sample_rhs); + } + //- Not generic to enable sampling end + void move(const real_number dt) final { TIMEZONE("particles_system::move"); - computer.move_particles(my_particles_positions.get(), my_nb_particles, + positions_updater.move_particles(my_particles_positions.get(), my_nb_particles, my_particles_rhs.data(), std::min(step_idx,int(my_particles_rhs.size())), dt); } void redistribute() final { TIMEZONE("particles_system::redistribute"); - computer.redistribute(current_my_nb_particles_per_partition.get(), + particles_distr.template redistribute<computer_class, 3, size_particle_rhs, 1>( + computer, + current_my_nb_particles_per_partition.get(), &my_nb_particles, &my_particles_positions, my_particles_rhs.data(), int(my_particles_rhs.size()), diff --git a/bfps/cpp/particles/particles_system_builder.hpp b/bfps/cpp/particles/particles_system_builder.hpp index a3c0d094..321f6d20 100644 --- a/bfps/cpp/particles/particles_system_builder.hpp +++ b/bfps/cpp/particles/particles_system_builder.hpp @@ -192,18 +192,21 @@ struct particles_system_build_container { const particles_rnumber my_spatial_up_limit_z = particles_rnumber(local_field_offset[IDX_Z]+local_field_dims[IDX_Z])*spatial_partition_width[IDX_Z]; // Create the particles system - particles_system<partsize_t, particles_rnumber, field_rnumber, field<field_rnumber, be, fc>, particles_generic_interp<particles_rnumber, interpolation_size,spline_mode>, interpolation_size, ncomp(fc)>>* part_sys - = new particles_system<partsize_t, particles_rnumber, field_rnumber, field<field_rnumber, be, fc>, particles_generic_interp<particles_rnumber, interpolation_size,spline_mode, interpolation_size, ncomp(fc)>>(field_grid_dim, - spatial_box_width, - spatial_box_offset, - spatial_partition_width, - my_spatial_low_limit_z, - my_spatial_up_limit_z, - local_field_dims, - local_field_offset, - (*fs_field), - mpi_comm, - in_current_iteration); + using particles_system_type = particles_system<partsize_t, particles_rnumber, field_rnumber, + field<field_rnumber, be, fc>, + particles_generic_interp<particles_rnumber, interpolation_size,spline_mode>, + interpolation_size, ncomp(fc)>; + particles_system_type* part_sys = new particles_system_type(field_grid_dim, + spatial_box_width, + spatial_box_offset, + spatial_partition_width, + my_spatial_low_limit_z, + my_spatial_up_limit_z, + local_field_dims, + local_field_offset, + (*fs_field), + mpi_comm, + in_current_iteration); // Load particles from hdf5 particles_input_hdf5<partsize_t, particles_rnumber, 3,3> generator(mpi_comm, fname_input, diff --git a/setup.py b/setup.py index 139a4411..c531263a 100644 --- a/setup.py +++ b/setup.py @@ -121,7 +121,7 @@ src_file_list = ['full_code/direct_numerical_simulation', 'scope_timer'] particle_headers = [ - 'cpp/particles/abstract_particles_distr.hpp', + 'cpp/particles/particles_distr_mpi.hpp', 'cpp/particles/abstract_particles_input.hpp', 'cpp/particles/abstract_particles_output.hpp', 'cpp/particles/abstract_particles_system.hpp', @@ -135,7 +135,9 @@ particle_headers = [ 'cpp/particles/particles_system_builder.hpp', 'cpp/particles/particles_system.hpp', 'cpp/particles/particles_utils.hpp', - 'cpp/particles/env_utils.hpp' ] + 'cpp/particles/particles_output_sampling_hdf5.hpp', + 'cpp/particles/particles_sampling.hpp', + 'cpp/particles/env_utils.hpp'] full_code_headers = ['cpp/full_code/main_code.hpp', 'cpp/full_code/codes_with_no_output.hpp', -- GitLab