O P A R - Open Architecture Particle in Cell Simulation - Version 3.0
Plasma simulations with dust particles
 All Classes Files Functions Variables Friends Macros Groups Pages
numeric.h
Go to the documentation of this file.
1 
5 #ifndef NUMERIC_H
6 #define NUMERIC_H
7 #include "dimensionality.h"
8 #include <fstream>
9 #include <cmath>
10 #include <cassert>
11 #include <valarray>
12 #include <iostream>
13 //---------------------------------------------------------------------------------------------------------------------
14 
20 inline double frand() {return rand()/double(RAND_MAX);}
21 inline double srand() { // Give a random number of 1 or -1
22  double dr;
23  double fr = frand();
24  if (fr < 0.5) dr = -1.0; else dr = 1.0;
25  return dr;
26 }
27 template<typename T>
28 inline T sqr(T val) {
29  return val*val;
30 }
31 template<typename T>
32 inline T max(T a, T b) {
33  return a>b?a:b;
34 }
35 
44 //---------------------------------------------------------------------------------------------------------------------
45 #ifndef ONE_DIMENSIONAL
46 template<class T>
47 class grid {
48  protected:
50  T *G;
53  int gsize;
54  public:
56  grid() : G(0), size(Position(0)), gsize(0) { }
58  grid(GridPosition size_) : G(0), size(size_), gsize((size_+UnitGrid).volume()) {newData();}
59  // Copy constructor
60  grid(const grid &agrid) : G(0), size(agrid.size), gsize(agrid.gsize) {
61  newData();
62  for (int i=0; i<gsize; ++i) G[i] = agrid.G[i];
63  }
64  ~grid() {
65  static int ic = 0;
66  static int im = 3;
67  ic += 1;
68  if (ic==im) {
69  //std::cout << "Hier kommt jetzt der Destructor! " << ic << std::endl;
70  im += 1;
71  if (G) delete[] G;
72  //std::cout << "Fertig!" << std::endl;
73  }
74  }
76  const GridPosition& Size () const {return size;}
77 
81  void Resize (const GridPosition &asize) {
82  size = asize;
83  gsize = (size+UnitGrid).volume();
84  newData();
85  }
86 
91  const grid& operator=(const std::valarray<T> arr) {
92  assert (arr.size()==G.size());
93  for (int i=0; i<gsize; ++i) G[i] = arr[i];
94  return *this;
95  }
96  const grid& operator=(const T val) {
97  for (int i=0; i<gsize; ++i) G[i] = val;
98  return *this;
99  }
100 
106  const grid& operator+=(const std::valarray<T> arr) {
107  assert (arr.size()==G.size());
108  for (int i=0; i<gsize; ++i) G[i] += arr[i];
109  return *this;
110  }
111  const grid& operator+=(const grid& arr) {
112  assert (arr.size==size);
113  for (int i=0; i<gsize; ++i) G[i] += arr.G[i];
114  return *this;
115  }
116  const grid& operator-=(const std::valarray<T> arr) {
117  assert (arr.size()==G.size());
118  for (int i=0; i<gsize; ++i) G[i] -= arr[i];
119  return *this;
120  }
121  const grid& operator-=(const grid& arr) {
122  assert (arr.size==size);
123  for (int i=0; i<gsize; ++i) G[i] -= arr.G[i];
124  return *this;
125  }
126  const grid& operator*=(const T val) {
127  for (int i = 0; i < gsize; ++i) G[i] *= val;
128  return *this;
129  }
130  const grid& operator/=(const T val) {
131  for (int i=0; i<gsize; ++i) G[i] /= val;
132  return *this;
133  }
134  //operator std::valarray<T>& () { // Get a reference of the valarray (dirty!)
135  // return G;
136  //}
137  T& operator[] (const GridPosition &i) {
138  int pos = i.arraypos(size);
139  //if ((pos >= gsize) || (pos < 0)) {
140  // std::cerr << i << " Index out of bounds (1)" << std::endl;
141  // exit(-1);
142  //}
143  return G[pos];
144  }
145  // Returns reference/value at grid position
146  T operator[] (const GridPosition &i) const {
147  int pos = i.arraypos(size);
148  //if ((pos>=gsize) || (pos<0)) {
149  // std::cerr << i << " Index out of bounds (2)" << std::endl;
150  // exit(-1);
151  //}
152  return G[pos];
153  }
154  // The linearly interpolated value at a position between the grid points
155  T operator() (const Position &X) const {
156  GridPosition p = GridPosition(X);
157  p.limitto(size - 1);
158  GridPosition pp = p + 1;
159  Position a = Position(pp) - X;
160  Position b = X - Position(p);
161  return WeightedSum(*this,p,pp,a,b);
162  }
163  // Returns the derivative. Assumes that type T can be cast to a double
164  grid<Position> derive(Position ddx);
165  // Sets the values in the grid with the use of a function that takes no arguments, eg frand()
166  void apply(T fkt());
167  private:
168  void newData() {
169  if (G) delete[] G;
170  G = new T[gsize];
171  }
172 };
173 template<class T>
174 void grid<T>::apply(T fkt()) {
175  for (int i = 0; i < gsize; i++) {
176  T tmp = fkt();
177  G[i] = tmp;
178  }
179 }
180 #endif
181 //---------------------------------------------------------------------------------------------------------------------
182 #ifdef ONE_DIMENSIONAL
183 template<class T>
184 class grid {
185  protected:
187  std::valarray<T> G;
190  public:
192  grid() : G(), size(Position(0)) { }
194  grid(GridPosition size_) : G(0.0, size_.volume()), size(size_) { }
196  grid(const grid &agrid) : G(agrid.G), size(agrid.size) { }
197  ~grid() { }
199  const GridPosition& Size () const {return size;}
200 
204  void Resize (const GridPosition &asize) {
205  size = asize;
206  G.resize((size+UnitGrid).volume());
207  }
208 
213  const grid& operator=(const std::valarray<T> arr) {
214  assert (arr.size()==G.size());
215  G = arr;
216  return *this;
217  }
218  const grid& operator=(const T val) {
219  G = val;
220  return *this;
221  }
222 
224  const grid& operator+=(const std::valarray<T> arr) {
225  assert (arr.size()==G.size());
226  G += arr;
227  return *this;
228  }
229  const grid& operator-=(const std::valarray<T> arr) {
230  assert (arr.size()==G.size());
231  G -= arr;
232  return *this;
233  }
234  const grid& operator*=(const T val) {
235  G *= val;
236  return *this;
237  }
238  const grid& operator/=(const T val) {
239  G /= val;
240  return *this;
241  }
242 
248 
249  operator std::valarray<T>& () { // Get a reference of the valarray (dirty!)
250  return G;
251  }
252 
254  T& operator[] (const GridPosition &i) {
255  int pos = i.arraypos(size);
256  return G[i.arraypos(pos)];
257  }
258  // Returns reference/value at grid position
259  T operator[] (const GridPosition &i) const {
260  int pos = i.arraypos(size);
261  return G[i.arraypos(pos)];
262  }
264 
265  // The linearly interpolated value at a position between the grid
266  T operator() (const Position &X) const {
267  GridPosition p = GridPosition(X);
268  p.limitto(size - 1);
269  GridPosition pp = p + 1;
270  Position a = Position(pp) - X;
271  Position b = X - Position(p);
272  return WeightedSum(*this,p,pp,a,b);
273  }
274  // Returns the derivative. Assumes that type T can be cast to a double
275  grid<Position> derive(Position ddx);
276  // Sets the values in the grid with the use of a function that takes no arguments, eg frand()
277  void apply(T fkt());
278 };
279 template<class T>
280 void grid<T>::apply(T fkt()) {
281  for (int i=0; i<G.size(); i++) {
282  T tmp = fkt();
283  G[i] = tmp;
284  }
285 }
286 template<class T>
288  int i;
289  grid<Position> D;
290  GridPosition NG = Size();
291  D.Resize(NG);
292  ddx *= 2.0;
293  grid<T> &G = *this;
294  // Derivative in the volume
295  #pragma omp parallel for private(i) default(shared)
296  for (i=NG[0]-2; i>0; i--) D[i] = (G[i-1] - G[i+1]) / ddx[0];
297  // Derivative at the boundaries
298  D[0] = 2.0 * (G[0] - G[1]) / ddx[0]; // First cell
299  D[NG[0]-1] = 2.0 * (G[NG[0]-2] - G[NG[0]-1]) / ddx[0]; // Last cell
300  return D;
301 }
302 
314 void TriMatrixSolver(std::valarray<double> &a, std::valarray<double> &b, std::valarray<double> &c, std::valarray<double> &r, std::valarray<double> &u, int nt);
315 template<class T>
316 T WeightedSum(const grid<T> &g, GridPosition p1, GridPosition p2, const Position& wa, const Position& wb) {
317  return (g[p1]*wa.P[0] + g[p2]*wb.P[0]);
318 }
319 #endif
320 //---------------------------------------------------------------------------------------------------------------------
321 #ifdef TWO_DIMENSIONAL
322 template<class T>
323 T WeightedSum(const grid<T> &g,GridPosition p1, GridPosition p2, const Position& wa, const Position& wb) {
324  T sum = g[p1]*wa.P[0]*wa.P[1] + g[p2]*wb.P[0]*wb.P[1];
325  ++p1.P[0];
326  --p2.P[0];
327  return (sum + g[p1]*wb.P[0]*wa.P[1] + g[p2]*wa.P[0]*wb.P[1]);
328 }
329 #endif
330 //---------------------------------------------------------------------------------------------------------------------
331 #ifdef THREE_DIMENSIONAL
332 template<class T>
333 T WeightedSum(const grid<T> &g,GridPosition p1, GridPosition p2,const Position& wa, const Position& wb) {
334  T sum = g[p1]*wa.P[0]*wa.P[1]*wa.P[2] + g[p2]*wb.P[0]*wb.P[1]*wb.P[2];
335  ++p1.P[0];
336  --p2.P[0];
337  sum += g[p1]*wb.P[0]*wa.P[1]*wa.P[2] + g[p2]*wa.P[0]*wb.P[1]*wb.P[2];
338  ++p1.P[1];
339  --p2.P[1];
340  sum += g[p1]*wb.P[0]*wb.P[1]*wa.P[2] + g[p2]*wa.P[0]*wa.P[1]*wb.P[2];
341  --p1.P[0];
342  ++p2.P[0];
343  return sum + g[p1]*wa.P[0]*wb.P[1]*wa.P[2] + g[p2]*wb.P[0]*wa.P[1]*wb.P[2];
344 }
345 #endif
346 //---------------------------------------------------------------------------------------------------------------------
347 #endif