PFASST++
simple_physics_solver.cpp
Go to the documentation of this file.
2 
3 #include <cassert>
4 #include <iostream>
5 #include <cmath>
6 using namespace std;
7 
8 #define UNUSED(expr) (void)(expr)
9 
10 
12 {
13  SimplePhysicsSolverConfig::SimplePhysicsSolverConfig(const double omega_e, const double omega_b,
14  const double epsilon, const double sigma)
15  : omega_e(omega_e)
16  , omega_b(omega_b)
17  , epsilon(epsilon)
18  , sigma(sigma)
19  , sigma2(sigma * sigma)
20  {
21  this->external_e_field_matrix[0][0] = double(1.0);
22  this->external_e_field_matrix[0][1] = double(0.0);
23  this->external_e_field_matrix[0][2] = double(0.0);
24  this->external_e_field_matrix[1][0] = double(0.0);
25  this->external_e_field_matrix[1][1] = double(1.0);
26  this->external_e_field_matrix[1][2] = double(0.0);
27  this->external_e_field_matrix[2][0] = double(0.0);
28  this->external_e_field_matrix[2][1] = double(0.0);
29  this->external_e_field_matrix[2][2] = double(-2.0);
30 
31  this->b_field_matrix[0][0] = double(0.0);
32  this->b_field_matrix[0][1] = double(1.0);
33  this->b_field_matrix[0][2] = double(0.0);
34  this->b_field_matrix[1][0] = double(-1.0);
35  this->b_field_matrix[1][1] = double(0.0);
36  this->b_field_matrix[1][2] = double(0.0);
37  this->b_field_matrix[2][0] = double(0.0);
38  this->b_field_matrix[2][1] = double(0.0);
39  this->b_field_matrix[2][2] = double(0.0);
40  }
41 
43  {}
44 
45 
46  void evaluate_external_e_field(const double* positions, const double* charges, const double* masses,
47  const size_t num_particles, const double t,
48  const SimplePhysicsSolverConfig* config,
49  double* forces)
50  {
51  UNUSED(t);
52 // cout << "SimplePhysicsSolver::evaluate_external_e_field(t=" << t << ")" << endl;
53  double pre_factor = (- config->epsilon) * (config->omega_e * config->omega_e);
54  double factor = double(0.0);
55  for (size_t i = 0; i < num_particles; ++i) {
56 // cout << " particle " << i << endl;
57  factor = pre_factor / (charges[i] / masses[i]);
58 // cout << " position: ";
59 // internal::print_vec(positions + (i * DIM));
60 // cout << endl << " factor: " << factor << endl;
61  internal::scale_mat_mul_vec(config->external_e_field_matrix, positions + (i * DIM), factor, forces + (i * DIM));
62 // cout << " force: ";
63 // internal::print_vec(forces + (i * DIM));
64 // cout << endl;
65  }
66 // cout << "DONE SimplePhysicsSolver::evaluate_external_e_field(t=" << t << ")" << endl;
67  }
68 
69  void evaluate_internal_e_field(const double* positions, const double* charges, const double* masses,
70  const size_t num_particles, const double t,
71  const SimplePhysicsSolverConfig* config,
72  double* exyz, double* phis)
73  {
74  UNUSED(masses); UNUSED(t);
75 // cout << "SimplePhysicsSolver::evaluate_internal_e_field(t=" << t << ")" << endl;
76  double r = double(0.0),
77  r3 = double(0.0),
78  dist2 = double(0.0);
79  double* dist = new double[DIM];
80 
81  // computing forces on particle i
82  for (size_t i = 0; i < num_particles; ++i) {
83 // cout << " particle " << i << endl;
84 
85  // null result values
86  phis[i] = double(0.0);
87  for (size_t d = 0; d < DIM; ++d) { exyz[i * DIM + d] = double(0.0); }
88 
89  // effects of particle j on particle i
90  for (size_t j = 0; j < num_particles; ++j) {
91 // cout << " particle " << j << endl;
92  if (j == i) {
93 // cout << " skipping" << endl;
94  continue;
95  }
96  dist2 = double(0.0);
97  for (size_t d = 0; d < DIM; ++d) {
98  dist[d] = positions[i * DIM + d] - positions[j * DIM + d];
99  dist2 += dist[d] * dist[d];
100  }
101 // cout << " dist = " << dist << endl;
102  r = sqrt(dist2 + config->sigma2);
103 // cout << " r = " << r << " (= sqrt(dist^2+" << config->sigma2 << ")" << endl;
104  phis[i] += charges[j] / r;
105 
106  r3 = r * r * r;
107  for (size_t d = 0; d < DIM; ++d) {
108  exyz[i * DIM + d] += dist[d] / r3 * charges[j];
109 // cout << " exyz[" << i * DIM + d << "] += " << positions[j * DIM + d] << " / " << r3 << " * " << charges[j] << "(q) => " << exyz[i * DIM + d] << endl;
110  }
111  }
112 
113 // cout << " exyz = ";
114 // internal::print_vec(exyz+(i*DIM));
115 // cout << endl
116 // << " phi_i = " << phis[i] << endl;
117  }
118  delete[] dist;
119 // cout << "DONE SimplePhysicsSolver::evaluate_internal_e_field(t=" << t << ")" << endl;
120  }
121 
122 
123  void evaluate_e_field(const double* positions, const double* charges, const double* masses,
124  const size_t num_particles, const double t,
125  const SimplePhysicsSolverConfig* config,
126  double* forces)
127  {
128 // cout << "SimplePhysicsSolver::evaluate_e_field(t=" << t << ")" << endl;
129  double* external = new double[num_particles * DIM];
130  double* internal = new double[num_particles * DIM];
131  double* phis = new double[num_particles];
132  evaluate_external_e_field(positions, charges, masses, num_particles, t, config, external);
133  evaluate_internal_e_field(positions, charges, masses, num_particles, t, config, internal, phis);
134 // cout << " -> e_forces = [ " << endl;
135  for (size_t i = 0; i < num_particles; ++i) {
136 // cout << " ";
137  for (size_t d = 0; d < DIM; ++d) {
138  forces[i * DIM + d] = external[i * DIM + d] + internal[i * DIM + d];
139  }
140 // internal::print_vec(forces + (i * DIM));
141 // cout << endl;
142  }
143 // cout << " ]" << endl;
144  delete[] external;
145  delete[] internal;
146  delete[] phis;
147  }
148 
149 
150  void get_b_field_vector(const SimplePhysicsSolverConfig* config, double* b_field_vector)
151  {
152  for (size_t i = 0; i < DIM; ++i) {
153  b_field_vector[i] = double(0.0);
154  }
155  b_field_vector[2] = double(1.0);
156  for (size_t i = 0; i < DIM; ++i) {
157  b_field_vector[i] *= config->omega_b;
158  }
159  }
160 
161  void evaluate_b_field(const double* velocities, const double* charges, const double* masses,
162  const size_t num_particles, const double t,
163  const SimplePhysicsSolverConfig* config, double* forces)
164  {
165  UNUSED(t);
166 // cout << "SimplePhysicsSolver::evaluate_b_field(t=" << t << ")" << endl;
167  for (size_t i = 0; i < num_particles; ++i) {
168 // cout << " particle " << i << endl;
169  internal::scale_mat_mul_vec(config->b_field_matrix, velocities + (i * DIM),
170  config->omega_b / (charges[i] / masses[i]),
171  forces + (i * DIM));
172 // cout << " force = ";
173 // internal::print_vec(forces + (i * DIM));
174 // cout << endl;
175  }
176  }
177 
178 
179  double compute_energy(const double* positions, const double* velocities,
180  const double* charges, const double* masses,
181  const size_t num_particles, const double t,
182  const SimplePhysicsSolverConfig* config)
183  {
184 // cout << "SimplePhysicsSolver::compute_energy(t=" << t << ")" << endl;
185  double e_kin = double(0.0);
186  double e_pot = double(0.0);
187 
188  double* exyz = new double[num_particles * DIM];
189  double* phis = new double[num_particles];
190  double* temp = new double[DIM];
191  double v2 = double(0.0);
192 
193  evaluate_internal_e_field(positions, charges, masses, num_particles, t, config, exyz, phis);
194 
195  for (size_t i = 0; i < num_particles; ++i) {
196 // cout << " particle " << i << endl;
197  // potential energy (induced by external electric field, position and internal electric field (i.e. phis))
198  internal::scale_mat_mul_vec(config->external_e_field_matrix, positions + (i * DIM),
199  (- config->epsilon * config->omega_e * config->omega_e / double(2.0) * (charges[i] / masses[i])),
200  temp);
201  e_pot += (charges[i] * phis[i]) - internal::scalar_prod(temp, positions + (i * DIM));
202 // cout << " e_pot += " << charges[i] << " * " << phis[i] << " - <";
203 // internal::print_vec(temp);
204 // cout << ", ";
205 // internal::print_vec(positions + (i * DIM));
206 // cout << "> (=" << internal::scalar_prod(temp, positions + (i * DIM)) << ")" << endl;
207 
208  // kinetic energy (induced by velocity)
209  v2 = internal::scalar_prod(velocities + (i * DIM), velocities + (i * DIM));
210  e_kin += masses[i] / double(2.0) * v2;
211 // cout << " e_kin += " << masses[i] << "(m) / 2.0" << " * <";
212 // internal::print_vec(velocities + (i * DIM));
213 // cout << " , ";
214 // internal::print_vec(velocities + (i * DIM));
215 // cout << "> (=" << v2 << ")" << endl;
216  }
217 
218  delete[] exyz;
219  delete[] phis;
220  delete[] temp;
221 // cout << " -> energy = " << e_kin << " + " << e_pot << endl;
222 // cout << "DONE SimplePhysicsSolver::compute_energy(t=" << t << ")" << endl;
223  return e_kin + e_pot;
224  }
225 
226  namespace internal
227  {
228  inline void cross_prod(const double first[DIM], const double second[DIM], double cross_prod[DIM])
229  {
230  cross_prod[0] = first[1] * second[2] - first[2] * second[1];
231  cross_prod[1] = first[2] * second[0] - first[0] * second[2];
232  cross_prod[2] = first[0] * second[1] - first[1] * second[0];
233  }
234 
235  inline double scalar_prod(const double first[DIM], const double second[DIM])
236  {
237  double prod = 0.0;
238  for (size_t m = 0; m < DIM; ++m) {
239  prod += first[m] * second[m];
240  }
241  return prod;
242  }
243 
244  inline void scale_mat_mul_vec(const double mat[DIM][DIM], const double vec[DIM],
245  const double factor, double prod[DIM])
246  {
247  for (size_t i = 0; i < DIM; ++i) {
248  prod[i] = double(0.0);
249  for (size_t j = 0; j < DIM; ++j) {
250  prod[i] += factor * mat[i][j] * vec[j];
251  }
252  }
253  }
254 
255  inline void print_vec(const double vec[DIM])
256  {
257  cout << "[";
258  for (size_t i = 0; i < DIM; ++i) {
259  cout << vec[i];
260  if (i < DIM - 1) {
261  cout << " , ";
262  }
263  }
264  cout << "]";
265  }
266  } // ::simple_physics_solver::internal
267 } // ::simple_physics_solver
void evaluate_external_e_field(const double *positions, const double *charges, const double *masses, const size_t num_particles, const double t, const SimplePhysicsSolverConfig *config, double *forces)
void evaluate_internal_e_field(const double *positions, const double *charges, const double *masses, const size_t num_particles, const double t, const SimplePhysicsSolverConfig *config, double *exyz, double *phis)
double scalar_prod(const double first[DIM], const double second[DIM])
STL namespace.
void cross_prod(const double first[DIM], const double second[DIM], double cross_prod[DIM])
void get_b_field_vector(const SimplePhysicsSolverConfig *config, double *b_field_vector)
void evaluate_b_field(const double *velocities, const double *charges, const double *masses, const size_t num_particles, const double t, const SimplePhysicsSolverConfig *config, double *forces)
#define DIM
#define UNUSED(expr)
void scale_mat_mul_vec(const double mat[DIM][DIM], const double vec[DIM], const double factor, double prod[DIM])
tuple t
Definition: plot.py:12
double compute_energy(const double *positions, const double *velocities, const double *charges, const double *masses, const size_t num_particles, const double t, const SimplePhysicsSolverConfig *config)
void evaluate_e_field(const double *positions, const double *charges, const double *masses, const size_t num_particles, const double t, const SimplePhysicsSolverConfig *config, double *forces)
void print_vec(const double vec[DIM])