10 #include <boost/format.hpp>
21 #define PFASST_RANDOM_SEED 42
31 template<
typename precision>
32 inline mpi::MPICommunicator& ParticleCloud<precision>::as_mpi(ICommunicator* comm)
34 auto mpi =
dynamic_cast<mpi::MPICommunicator*
>(comm);
41 template<
typename precision>
43 const precision default_charge,
const precision default_mass)
45 , _num_particles(num_particles)
46 , _positions(num_particles * dim)
47 , _velocities(num_particles * dim)
48 , _charges(num_particles, default_charge)
49 , _masses(num_particles, default_mass)
50 , _default_charge(default_charge)
51 , _default_mass(default_mass)
60 template<
typename precision>
64 template<
typename precision>
67 fill(this->_positions.begin(), this->_positions.end(), precision(0.0));
68 fill(this->_velocities.begin(), this->_velocities.end(), precision(0.0));
69 fill(this->_charges.begin(), this->_charges.end(), this->_default_charge);
70 fill(this->_masses.begin(), this->_masses.end(), this->_default_mass);
72 fill(this->recv_request.begin(), this->recv_request.end(), MPI_REQUEST_NULL);
73 fill(this->send_request.begin(), this->send_request.end(), MPI_REQUEST_NULL);
77 template<
typename precision>
88 this->_dim = other_c->dim();
89 this->_num_particles = other_c->size();
90 this->_positions = other_c->positions();
91 this->_velocities = other_c->velocities();
92 this->_charges = other_c->charges();
93 this->_masses = other_c->masses();
94 this->_default_charge = other_c->_default_charge;
95 this->_default_mass = other_c->_default_mass;
165 template<
typename precision>
168 return this->_num_particles;
171 template<
typename precision>
177 template<
typename precision>
180 return this->_positions;
183 template<
typename precision>
186 return this->_positions;
189 template<
typename precision>
192 return this->_velocities;
195 template<
typename precision>
198 return this->_velocities;
201 template<
typename precision>
204 return this->_charges;
207 template<
typename precision>
210 return this->_charges;
213 template<
typename precision>
216 return this->_masses;
219 template<
typename precision>
222 return this->_masses;
225 template<
typename precision>
228 vector<shared_ptr<Particle<precision>>> particles(this->size());
229 for (
size_t index = 0; index < this->size(); ++index) {
230 particles[index] = this->operator[](index);
235 template<
typename precision>
239 for (
size_t p = 0; p < this->size(); ++p) {
241 std::transform(center.cbegin(), center.cend(), this->positions().cbegin() + (p * this->dim()),
242 center.begin(), std::plus<precision>());
244 return center / this->size();
247 template<
typename precision>
250 shared_ptr<Particle<precision>> particle = make_shared<Particle<precision>>(this->dim());
251 copy_n(this->positions().cbegin() + (index * this->dim()), this->dim(), particle->pos().begin());
252 copy_n(this->velocities().cbegin() + (index * this->dim()), this->dim(), particle->vel().begin());
253 particle->set_charge(this->_charges[index]);
254 particle->set_mass(this->_masses[index]);
258 template<
typename precision>
261 assert(this->size() > index);
262 return this->operator[](index);
265 template<
typename precision>
268 assert(this->size() > index);
269 assert(particle->dim() == this->dim());
270 copy_n(particle->pos().cbegin(), this->dim(), this->positions().begin() + (index * this->dim()));
271 copy_n(particle->vel().cbegin(), this->dim(), this->velocities().begin() + (index * this->dim()));
272 this->_masses[index] = particle->mass();
273 this->_charges[index] = particle->charge();
276 template<
typename precision>
280 VLOG(3) <<
LOG_INDENT <<
"distributing " << this->size() <<
" particles around center " << center;
281 assert(this->size() > 0);
283 precision scale = 1000.0;
286 precision max_pos =
max(center->pos());
287 precision max_vel =
max(center->vel());
288 uniform_real_distribution<precision> dist_pos(- max_pos / scale, max_pos / scale);
289 uniform_real_distribution<precision> dist_vel(- max_vel / scale, max_vel / scale);
290 VLOG(4) <<
LOG_INDENT <<
"random displacement range for";
291 VLOG(4) <<
LOG_INDENT <<
" ... position: " << boost::format(
"[%.4f, %.4f]") % dist_pos.min() % dist_pos.max();
292 VLOG(4) <<
LOG_INDENT <<
" ... velocity: " << boost::format(
"[%.4f, %.4f]") % dist_vel.min() % dist_vel.max();
296 if (this->size() % 2 == 1) {
297 this->set_at(p, center);
298 VLOG(5) <<
LOG_INDENT <<
"setting p=1 to center";
301 for (;p < this->size(); ++p) {
304 std::transform(center->pos().cbegin(), center->pos().cend(), pos_rand.begin(),
305 [&](
const precision& c) {
return c + dist_pos(rd_gen); });
306 std::transform(center->pos().cbegin(), center->pos().cend(), vel_rand.begin(),
307 [&](
const precision& c) {
return c + dist_vel(rd_gen); });
308 std::copy(pos_rand.cbegin(), pos_rand.cend(), this->positions().begin() + (p * this->dim()));
309 std::copy(vel_rand.cbegin(), vel_rand.cend(), this->velocities().begin() + (p * this->dim()));
310 VLOG(5) <<
LOG_INDENT <<
"p=" << (p+1) <<
": " << this->at(p);
312 assert(p == this->size());
313 VLOG(3) <<
LOG_INDENT <<
"center after distribute: " << this->center_of_mass();
316 template<
typename precision>
323 template<
typename precision>
326 auto& mpi = as_mpi(comm);
327 if (mpi.size() == 1) {
return; }
328 if (mpi.rank() == 0) {
return; }
330 int err = MPI_Irecv(this->positions().
data(),
331 sizeof(precision) * this->size() * this->dim(), MPI_CHAR,
332 (mpi.rank() - 1) % mpi.size(), tag, mpi.comm, &(this->recv_request[0]));
334 err = MPI_Irecv(this->velocities().
data(),
335 sizeof(precision) * this->size() * this->dim(), MPI_CHAR,
336 (mpi.rank() - 1) % mpi.size(), tag + 1, mpi.comm, &(this->recv_request[1]));
337 if (err != MPI_SUCCESS) {
throw mpi::MPIError(); }
340 template<
typename precision>
343 auto& mpi = as_mpi(comm);
344 if (mpi.size() == 1) {
return; }
345 if (mpi.rank() == 0) {
return; }
350 err = MPI_Recv(this->positions().
data(),
351 sizeof(precision) * this->size() * this->dim(), MPI_CHAR,
352 (mpi.rank() - 1) % mpi.size(), tag, mpi.comm, &stat);
353 if (err != MPI_SUCCESS) {
throw mpi::MPIError(); }
355 err = MPI_Recv(this->velocities().
data(),
356 sizeof(precision) * this->size() * this->dim(), MPI_CHAR,
357 (mpi.rank() - 1) % mpi.size(), tag + 1, mpi.comm, &stat);
358 if (err != MPI_SUCCESS) {
throw mpi::MPIError(); }
360 for (
auto req : this->recv_request) {
361 err = MPI_Wait(&req, &stat);
362 if (err != MPI_SUCCESS) {
throw mpi::MPIError(); }
367 template<
typename precision>
370 auto& mpi = as_mpi(comm);
371 if (mpi.size() == 1) {
return; }
372 if (mpi.rank() == mpi.size() - 1) {
return; }
374 int err = MPI_SUCCESS;
376 err = MPI_Send(this->positions().
data(),
377 sizeof(precision) * this->size() * this->dim(), MPI_CHAR,
378 (mpi.rank() + 1) % mpi.size(), tag, mpi.comm);
379 if (err != MPI_SUCCESS) {
throw mpi::MPIError(); }
380 err = MPI_Send(this->velocities().
data(),
381 sizeof(precision) * this->size() * this->dim(), MPI_CHAR,
382 (mpi.rank() + 1) % mpi.size(), tag + 1, mpi.comm);
383 if (err != MPI_SUCCESS) {
throw mpi::MPIError(); }
386 for (
auto req : this->send_request) {
387 err = MPI_Wait(&req, &stat);
388 if (err != MPI_SUCCESS) {
throw mpi::MPIError(); }
391 err = MPI_Isend(this->positions().
data(),
392 sizeof(precision) * this->size() * this->dim(), MPI_CHAR,
393 (mpi.rank() + 1) % mpi.size(), tag, mpi.comm, &send_request[0]);
394 if (err != MPI_SUCCESS) {
throw mpi::MPIError(); }
395 err = MPI_Isend(this->velocities().
data(),
396 sizeof(precision) * this->size() * this->dim(), MPI_CHAR,
397 (mpi.rank() + 1) % mpi.size(), tag + 1, mpi.comm, &send_request[1]);
398 if (err != MPI_SUCCESS) {
throw mpi::MPIError(); }
402 template<
typename precision>
405 auto& mpi = as_mpi(comm);
406 int err = MPI_Bcast(this->positions().
data(),
407 sizeof(precision) * this->size() * this->dim(), MPI_CHAR,
408 comm->size() - 1, mpi.comm);
409 if (err != MPI_SUCCESS) {
throw mpi::MPIError(); }
410 err = MPI_Bcast(this->velocities().
data(),
411 sizeof(precision) * this->size() * this->dim(), MPI_CHAR,
412 comm->size() - 1, mpi.comm);
413 if (err != MPI_SUCCESS) {
throw mpi::MPIError(); }
417 template<
typename precision>
421 os <<
"ParticleCloud(n=" << this->size() <<
", d=" << this->dim() <<
", particles=" << this->particles() <<
")";
422 os.unsetf(ios_base::floatfield);
426 template<
typename precision>
429 assert(first.
dim() == second.
dim());
430 vector<precision> diff = first.
pos() - second.
pos();
434 template<
typename precision>
437 return distance(*(first.get()), *(second.get()));
440 template<
typename precision>
444 vector<precision> distances(cloud.
size());
445 for (
size_t i = 0; i < distances.size(); ++i) {
446 distances[i] =
distance(*cloud[i], reference);
451 template<
typename precision>
459 template<
typename precision>
462 os <<
"<" << addressof(sp_cloud) <<
">";
467 template<
typename precision>
468 inline MAKE_LOGGABLE(shared_ptr<
const ParticleCloud<precision>>, sp_cloud, os)
470 os <<
"<" << addressof(sp_cloud) <<
">";
476 template<
typename precision>
478 const precision default_charge,
479 const precision default_mass)
480 : _num_particles(num_particles)
482 , _default_charge(default_charge)
483 , _default_mass(default_mass)
486 template<
typename precision>
489 return this->_num_particles;
492 template<
typename precision>
498 template<
typename precision>
499 shared_ptr<encap::Encapsulation<precision>>
502 return make_shared<ParticleCloud<precision>>(this->num_particles(), this->dim(),
503 this->_default_charge, this->_default_mass);
MAKE_LOGGABLE(shared_ptr< ParticleCloud< precision >>, sp_cloud, os)
ParticleComponent< precision > center_of_mass() const
ParticleCloudFactory(const size_t num_particles, const size_t dim, const precision default_charge, const precision default_mass)
static vector< precision > distance_to_reference(const ParticleCloud< precision > &cloud, const Particle< precision > &reference)
void set_at(const size_t index, const shared_ptr< Particle< precision >> &particle)
void distribute_around_center(const shared_ptr< Particle< precision >> ¢er)
ParticleComponent< precision > & pos()
vector< precision > & masses()
virtual void broadcast(ICommunicator *comm)
Broadcasting this data structure to all processes in comm.
virtual void copy(shared_ptr< const encap::Encapsulation< precision >> other)
virtual void zero() override
Zeroes out all values of this data structure.
static precision max_abs(const vector< precision > &data)
#define VLOG_FUNC_START(scope)
static precision distance(const Particle< precision > &first, const Particle< precision > &second)
ParticleCloudComponent< precision > & positions()
ParticleCloudComponent< precision > & velocities()
virtual void recv(ICommunicator *comm, int tag, bool blocking)
Receive values to store in this data structure.
vector< precision > ParticleCloudComponent
#define LOG_INDENT
Utility macro for creating identation depending on current stack position.
vector< precision > ParticleComponent
size_t num_particles() const
vector< shared_ptr< Particle< precision > > > particles() const
shared_ptr< Particle< precision > > at(const size_t index) const
virtual void send(ICommunicator *comm, int tag, bool blocking)
Send values stored in this data structure.
virtual void log(el::base::type::ostream_t &os) const
static precision max(const vector< precision > &data)
virtual shared_ptr< encap::Encapsulation< precision > > create(const encap::EncapType)
Actual method to create Encapsulation object of specific type.
virtual precision norm0() const
Computes the \( 0 \)-norm of the data structure's values.
Abstract interface for communicators.
shared_ptr< Particle< precision > > operator[](const size_t index) const
#define PFASST_RANDOM_SEED
vector< precision > & charges()
static precision norm0(const vector< precision > &data)
virtual void post(ICommunicator *comm, int tag)