Skip to content

Commit 4d280a0

Browse files
committed
examples: boris: linearized particle cloud components
Previously, the positions and velocities of a particle cloud were a 2D nested array with particle index as first and axis index as second index. This would cause some significant overhead and complexity when it comes to parallelization and communication. Now, the positions and velocities are linear vectors with the coordinates of the particles: x1, y1, z1, x2, y2, z2, x3, y3, z3, ..., xn, yn, zn u1, v1, w1, u2, v2, w2, u3, v3, w3, ..., un, vn, wn While I've been at it, some for loops have been replaced by iterator-based STL functions.
1 parent 4bb9e5b commit 4d280a0

File tree

9 files changed

+392
-575
lines changed

9 files changed

+392
-575
lines changed

examples/boris/bindings/wrapper_simple_physics_solver.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ namespace pfasst
3636

3737
protected:
3838
virtual size_t vector_to_array(const vector<scalar>& vec, scalar* arr);
39-
virtual size_t vector2d_to_array(const vector<vector<scalar>>& vec, scalar* arr);
39+
virtual size_t vector2d_to_array(const vector<scalar>& vec, scalar* arr);
4040

4141
virtual size_t pack_positions(const particle_cloud_type& particles, scalar* packed) override;
4242

examples/boris/bindings/wrapper_simple_physics_solver_impl.hpp

Lines changed: 7 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -27,12 +27,12 @@ namespace pfasst
2727

2828
template<typename scalar, typename time>
2929
size_t
30-
WrapperSimplePhysicsSolver<scalar, time>::vector2d_to_array(const vector<vector<scalar>>& vec,
31-
scalar* arr)
30+
WrapperSimplePhysicsSolver<scalar, time>::vector2d_to_array(const vector<scalar>& vec, scalar* arr)
3231
{
33-
for (size_t p = 0; p < vec.size(); ++p) {
32+
const size_t npart = vec.size() / DIM;
33+
for (size_t p = 0; p < npart; ++p) {
3434
for (size_t d = 0; d < DIM; ++d) {
35-
arr[p * DIM + d] = vec[p][d];
35+
arr[p * DIM + d] = vec[p * DIM + d];
3636
}
3737
}
3838
return vec.size() * DIM;
@@ -95,11 +95,7 @@ namespace pfasst
9595
WrapperSimplePhysicsSolver<scalar, time>::unpack_2d(const scalar* packed,
9696
const size_t num_particles)
9797
{
98-
ParticleCloudComponent<scalar> out(num_particles);
99-
for (size_t p = 0; p < num_particles; ++p) {
100-
out[p] = this->unpack_1d(packed + (p * DIM), DIM);
101-
}
102-
return out;
98+
return this->unpack_1d(packed, num_particles * DIM);
10399
}
104100

105101

@@ -198,7 +194,8 @@ namespace pfasst
198194
{
199195
auto b_vecs = cloud_component_factory<scalar>(particles->size(), particles->dim());
200196
for (size_t p = 0; p < particles->size(); ++p) {
201-
b_vecs[p] = this->get_b_field_vector() / particles->charges()[p] / particles->masses()[p];
197+
auto bvec = this->get_b_field_vector() / particles->charges()[p] / particles->masses()[p];
198+
std::copy(bvec.cbegin(), bvec.cend(), b_vecs.begin() + (p * DIM));
202199
}
203200
return b_vecs;
204201
}

examples/boris/boris_sweeper_impl.hpp

Lines changed: 43 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,9 @@ namespace pfasst
133133
scalar max_residual = scalar(0.0);
134134

135135
for (size_t m = 1; m < this->residuals.size(); ++m) {
136-
max_residual = std::max(max_residual, this->residuals[m]->norm0());
136+
auto residual_m = dynamic_pointer_cast<encap_type>(this->residuals[m]);
137+
assert(residual_m);
138+
max_residual = std::max(max_residual, residual_m->norm0());
137139
}
138140

139141
BCVLOG(8) << "=> max residual: " << max_residual;
@@ -164,8 +166,8 @@ namespace pfasst
164166
for (size_t p = 0; p < cloud->size(); ++p) {
165167
BCVLOG(9) << "writing cloud particle " << p << " to file";
166168
this->data_stream_fmt % (iter+1) % sweep % p
167-
% cloud->positions()[p][0] % cloud->positions()[p][1] % cloud->positions()[p][2]
168-
% cloud->velocities()[p][0] % cloud->velocities()[p][1] % cloud->velocities()[p][2]
169+
% cloud->positions()[p * cloud->dim()] % cloud->positions()[p * cloud->dim() + 1] % cloud->positions()[p * cloud->dim() + 2]
170+
% cloud->velocities()[p * cloud->dim()] % cloud->velocities()[p * cloud->dim() + 1] % cloud->velocities()[p * cloud->dim() + 2]
169171
% energy % drift % residual;
170172
this->data_stream << this->data_stream_fmt << endl;
171173
}
@@ -214,11 +216,11 @@ namespace pfasst
214216
this->log_indent->increment(5);
215217
// - delta_nodes_{m} / 2 * f_{m+1}^{k}
216218
auto t1 = this->build_rhs(m+1, true);
217-
c_k_term -= (0.5 * t1 * ds);
219+
c_k_term -= t1 * 0.5 * ds;
218220
BCVLOG(5) << "-= 0.5 * " << t1 << " * " << ds << " => " << c_k_term;
219221
// - delta_nodes_{m} / 2 * f_{m}^{k}
220222
auto t2 = this->build_rhs(m, true);
221-
c_k_term -= (0.5 * t2 * ds);
223+
c_k_term -= t2 * 0.5 * ds;
222224
BCVLOG(5) << "-= 0.5 * " << t2 << " * " << ds << " => " << c_k_term;
223225
// + s_integral[m]
224226
c_k_term += this->s_integrals[m+1];
@@ -342,19 +344,19 @@ namespace pfasst
342344
typedef complex<scalar> C;
343345
C i(0.0, 1.0);
344346
auto initial = this->particles[0];
345-
scalar x0 = initial->positions()[0][0],
346-
y0 = initial->positions()[0][1],
347-
z0 = initial->positions()[0][2],
348-
u0 = initial->velocities()[0][0],
349-
v0 = initial->velocities()[0][1],
350-
w0 = initial->velocities()[0][2],
347+
scalar x0 = initial->positions()[0],
348+
y0 = initial->positions()[1],
349+
z0 = initial->positions()[2],
350+
u0 = initial->velocities()[0],
351+
v0 = initial->velocities()[1],
352+
w0 = initial->velocities()[2],
351353
omega_e = this->impl_solver->omega_e(),
352354
omega_b = this->impl_solver->omega_b(),
353355
epsilon = this->impl_solver->epsilon();
354356
time dt = this->get_controller()->get_time_step();
355357

356358
C omega_tilde = sqrt(-2.0 * epsilon) * omega_e;
357-
q.positions()[0][2] = (z0 * cos(omega_tilde * (scalar)(dt))
359+
q.positions()[2] = (z0 * cos(omega_tilde * (scalar)(dt))
358360
+ w0 / omega_tilde * sin(omega_tilde * (scalar)(dt))).real();
359361

360362
C sqrt_in_omega = sqrt(pow(omega_b, 2) + 4.0 * epsilon * pow(omega_e, 2));
@@ -369,14 +371,14 @@ namespace pfasst
369371

370372
C x_y_move = (r_plus + i * i_plus) * exp(- i * omega_plus * (scalar)(dt))
371373
+ (r_minus + i * i_minus) * exp(- i * omega_minus * (scalar)(dt));
372-
q.positions()[0][0] = x_y_move.real();
373-
q.positions()[0][1] = x_y_move.imag();
374+
q.positions()[0] = x_y_move.real();
375+
q.positions()[1] = x_y_move.imag();
374376

375-
q.velocities()[0][2] = (- z0 * omega_tilde * sin(omega_tilde * (scalar)(dt)) + w0 * cos(omega_tilde * (scalar)(dt))).real();
377+
q.velocities()[2] = (- z0 * omega_tilde * sin(omega_tilde * (scalar)(dt)) + w0 * cos(omega_tilde * (scalar)(dt))).real();
376378
C u_v_move = (- i * omega_plus * (r_plus + i * i_plus)) * exp(-i * omega_plus * (scalar)(dt))
377379
- (i * omega_minus * (r_minus + i * i_minus)) * exp(-i * omega_minus * (scalar)(dt));
378-
q.velocities()[0][0] = u_v_move.real();
379-
q.velocities()[0][1] = u_v_move.imag();
380+
q.velocities()[0] = u_v_move.real();
381+
q.velocities()[1] = u_v_move.imag();
380382

381383
this->exact_cache = make_shared<encap_type>(q);
382384
this->exact_updated = true;
@@ -409,12 +411,12 @@ namespace pfasst
409411
shared_ptr<encap_type> ex = dynamic_pointer_cast<encap_type>(this->get_factory()->create(pfasst::encap::solution));
410412
this->exact(ex, t);
411413

412-
e_tuple.p_err.x = ex->positions()[0][0] - end->positions()[0][0];
413-
e_tuple.p_err.y = ex->positions()[0][1] - end->positions()[0][1];
414-
e_tuple.p_err.z = ex->positions()[0][2] - end->positions()[0][2];
415-
e_tuple.p_err.u = ex->velocities()[0][0] - end->velocities()[0][0];
416-
e_tuple.p_err.v = ex->velocities()[0][1] - end->velocities()[0][1];
417-
e_tuple.p_err.w = ex->velocities()[0][2] - end->velocities()[0][2];
414+
e_tuple.p_err.x = ex->positions()[0] - end->positions()[0];
415+
e_tuple.p_err.y = ex->positions()[1] - end->positions()[1];
416+
e_tuple.p_err.z = ex->positions()[2] - end->positions()[2];
417+
e_tuple.p_err.u = ex->velocities()[0] - end->velocities()[0];
418+
e_tuple.p_err.v = ex->velocities()[1] - end->velocities()[1];
419+
e_tuple.p_err.w = ex->velocities()[2] - end->velocities()[2];
418420

419421
BCVLOG(9) << "absolute error at end point: " << e_tuple.p_err;
420422
}
@@ -555,8 +557,8 @@ namespace pfasst
555557
zero(dst_q[m]);
556558
zero(dst_qq[m]);
557559
for (size_t n = 0; n < nnodes; ++n) {
558-
*(dst_q[m].get()) += dt * this->q_mat(m, n) * rhs[n];
559-
*(dst_qq[m].get()) += dt * dt * this->qq_mat(m, n) * rhs[n];
560+
*(dst_q[m].get()) += rhs[n] * dt * this->q_mat(m, n);
561+
*(dst_qq[m].get()) += rhs[n] * dt * dt * this->qq_mat(m, n);
560562
}
561563
BCVLOG(6) << "integral(Q)[" << m << "]: " << *(dst_q[m].get());
562564
BCVLOG(6) << "integral(QQ)[" << m << "]: " << *(dst_qq[m].get());
@@ -583,8 +585,8 @@ namespace pfasst
583585
zero(dst_cast[m]->positions());
584586
zero(dst_cast[m]->velocities());
585587
for (size_t j = 0; j < nnodes; ++j) {
586-
dst_cast[m]->positions() += this->q_mat(m, j) * dt * this->particles[j]->velocities();
587-
dst_cast[m]->velocities() += this->q_mat(m, j) * dt * this->build_rhs(j);
588+
dst_cast[m]->positions() += this->particles[j]->velocities() * this->q_mat(m, j) * dt;
589+
dst_cast[m]->velocities() += this->build_rhs(j) * this->q_mat(m, j) * dt;
588590
}
589591
dst_cast[m]->positions() += this->start_particles->positions() - this->particles[m]->positions();
590592
dst_cast[m]->velocities() += this->start_particles->velocities() - this->particles[m]->velocities();
@@ -685,15 +687,15 @@ namespace pfasst
685687

686688
// compute integrals
687689
BCVLOG(1) << "computing integrals";
688-
zero(this->s_integrals);
689-
zero(this->ss_integrals);
690690
if (this->get_quadrature()->left_is_node()) {
691691
// starting at m=1 as m=0 will only add zeros
692692
for (size_t m = 1; m < nnodes; m++) {
693+
zero(this->s_integrals[m]);
694+
zero(this->ss_integrals[m]);
693695
for (size_t l = 0; l < nnodes; l++) {
694696
auto rhs = this->build_rhs(l);
695-
this->s_integrals[m] += dt * this->s_mat(m, l) * rhs;
696-
this->ss_integrals[m] += dt * dt * this->ss_mat(m, l) * rhs;
697+
this->s_integrals[m] += rhs * dt * this->s_mat(m, l);
698+
this->ss_integrals[m] += rhs * dt * dt * this->ss_mat(m, l);
697699
}
698700
}
699701
if (this->tau_q_corrections.size() > 0 && this->tau_qq_corrections.size()) {
@@ -847,10 +849,12 @@ namespace pfasst
847849
{
848850
BCVLOG(3) << "solving with Boris' method";
849851
this->log_indent->increment(3);
852+
const size_t npart = this->start_particles->size();
850853
UNUSED(t_next);
854+
851855
velocity_type c_k_term_half = c_k_term / scalar(2.0);
852856
BCVLOG(5) << "c_k_term/2: " << c_k_term_half;
853-
AttributeValues<scalar> beta = cmp_wise_div(this->particles[m]->charges(), this->particles[m]->masses()) / scalar(2.0) * ds;
857+
vector<scalar> beta = cmp_wise_div(this->particles[m]->charges(), this->particles[m]->masses()) / scalar(2.0) * ds;
854858
BCVLOG(5) << "beta: " << beta;
855859
acceleration_type e_forces_mean = (this->forces[m] + this->forces[m+1]) / scalar(2.0);
856860
BCVLOG(5) << "e_mean: " << e_forces_mean << " (<=" << this->forces[m] << " +" << this->forces[m+1] << " / 2)";
@@ -863,20 +867,17 @@ namespace pfasst
863867
BCVLOG(3) << "v-: " << v_minus;
864868

865869
// Boris' kick
866-
velocity_type boris_t(beta.size());
867-
auto b_field_vector = this->impl_solver->get_b_field_vector();
868-
for (size_t p = 0; p < beta.size(); ++p) {
869-
boris_t[p] = b_field_vector * beta[p];
870-
}
870+
vector<scalar> b_field_vector = this->impl_solver->get_b_field_vector();
871+
velocity_type boris_t = kronecker(beta, b_field_vector);
871872
velocity_type v_prime = v_minus + cross_prod(v_minus, boris_t);
872873
BCVLOG(3) << "v': " << v_prime;
873874

874875
// final Boris' drift
875-
vector<scalar> boris_t_sqr(boris_t.size());
876-
for (size_t p = 0; p < boris_t.size(); ++p) {
877-
boris_t_sqr[p] = pow(norm0(boris_t[p]), 2);
878-
}
879-
velocity_type boris_s = (scalar(2.0) * boris_t) / (scalar(1.0) + boris_t_sqr);
876+
vector<scalar> boris_t_sqr = norm_sq_npart(boris_t, npart); // particle-wise scalar product of boris_t
877+
// for (size_t p = 0; p < boris_t.size(); ++p) {
878+
// boris_t_sqr[p] = pow(norm0(boris_t[p]), 2);
879+
// }
880+
velocity_type boris_s = (boris_t * scalar(2.0)) / (boris_t_sqr + scalar(1.0));
880881
velocity_type v_plus = v_minus + cross_prod(v_prime, boris_s);
881882
BCVLOG(3) << "v+: " << v_plus;
882883

examples/boris/particle.hpp

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ namespace pfasst
4141
Particle(const size_t dim, const precision charge, const precision mass);
4242
virtual ~Particle();
4343

44-
size_t dim() const;
44+
inline size_t dim() const;
4545
ParticleComponent<precision>& pos();
4646
const ParticleComponent<precision>& pos() const;
4747
ParticleComponent<precision>& vel();
@@ -50,8 +50,6 @@ namespace pfasst
5050
const precision mass() const;
5151
const precision alpha() const;
5252

53-
// void set_pos(const ParticleComponent<precision>& pos);
54-
// void set_vel(const ParticleComponent<precision>& vel);
5553
void set_charge(const precision& charge);
5654
void set_mass(const precision& mass);
5755

examples/boris/particle_cloud.hpp

Lines changed: 16 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,7 @@ namespace pfasst
1818
namespace boris
1919
{
2020
template<typename precision>
21-
using ParticleCloudComponent = vector<vector<precision>>;
22-
23-
template<typename precision>
24-
using AttributeValues = ParticleComponent<precision>;
21+
using ParticleCloudComponent = vector<precision>;
2522

2623

2724
template<typename precision>
@@ -34,8 +31,8 @@ namespace pfasst
3431
size_t _num_particles;
3532
ParticleCloudComponent<precision> _positions;
3633
ParticleCloudComponent<precision> _velocities;
37-
AttributeValues<precision> _charges;
38-
AttributeValues<precision> _masses;
34+
vector<precision> _charges;
35+
vector<precision> _masses;
3936

4037
precision _default_charge;
4138
precision _default_mass;
@@ -49,33 +46,31 @@ namespace pfasst
4946

5047
virtual void zero() override;
5148
virtual void copy(shared_ptr<const encap::Encapsulation<precision>> other);
52-
// virtual void copy(shared_ptr<const ParticleCloud<precision>> other);
5349

54-
void extend(const size_t new_size);
55-
void erase(const size_t index);
56-
void push_back(const shared_ptr<Particle<precision>>& particle);
57-
void insert(const size_t pos, const shared_ptr<Particle<precision>>& paticle);
58-
59-
size_t size() const;
60-
size_t dim() const;
61-
ParticleCloudComponent<precision>& positions();
50+
inline size_t size() const;
51+
inline size_t dim() const;
52+
ParticleCloudComponent<precision>& positions();
6253
const ParticleCloudComponent<precision>& positions() const;
63-
ParticleCloudComponent<precision>& velocities();
54+
ParticleCloudComponent<precision>& velocities();
6455
const ParticleCloudComponent<precision>& velocities() const;
65-
vector<precision>& charges();
56+
vector<precision>& charges();
6657
const vector<precision>& charges() const;
67-
vector<precision>& masses();
58+
vector<precision>& masses();
6859
const vector<precision>& masses() const;
6960

7061
ParticleComponent<precision> center_of_mass() const;
62+
// !! EXPENSIVE !!
7163
shared_ptr<Particle<precision>> operator[](const size_t index) const;
64+
// !! EXPENSIVE !!
7265
shared_ptr<Particle<precision>> at(const size_t index) const;
7366
void set_at(const size_t index, const shared_ptr<Particle<precision>>& particle);
74-
// !! EXPENSIVE !!
67+
68+
// !! VERY !! EXPENSIVE !! (i.e. never use for production code)
7569
vector<shared_ptr<Particle<precision>>> particles() const;
7670

7771
void distribute_around_center(const shared_ptr<Particle<precision>>& center);
7872

73+
// TODO: unify behaviour with particle_util::norm0 (e.g. norm_max vs. norm0 (==sqrt(^2))
7974
virtual precision norm0() const;
8075

8176
virtual void log(el::base::type::ostream_t& os) const;
@@ -116,8 +111,8 @@ namespace pfasst
116111
public:
117112
ParticleCloudFactory(const size_t num_particles, const size_t dim, const precision default_charge,
118113
const precision default_mass);
119-
size_t num_particles() const;
120-
size_t dim() const;
114+
inline size_t num_particles() const;
115+
inline size_t dim() const;
121116
virtual shared_ptr<encap::Encapsulation<precision>> create(const encap::EncapType);
122117
};
123118
} // ::pfasst::examples::boris

0 commit comments

Comments
 (0)