OSHUN  beta
Arbitrary Order Spherical-Harmonic 1D-3P Vlasov-Fokker-Planck-Maxwell code
nmethods.cpp
Go to the documentation of this file.
1 
11 // Standard libraries
12  #include <iostream>
13  #include <vector>
14  #include <valarray>
15  #include <complex>
16  #include <algorithm>
17  #include <cstdlib>
18  #include <float.h>
19 
20  #include <math.h>
21  #include <map>
22 
23 // My libraries
24  #include "lib-array.h"
25 
26 
27 
28 //-------------------------------------------------------------------
30  valarray<complex<double> >& b,
31  valarray<complex<double> >& xk) {
32 //-------------------------------------------------------------------
33  double tol(1.0e-1); //< Tolerance for absolute error
34  int MAXiter(5); //< Maximum iteration allowed
35 
36 
37 // The Matrices all have the right dimensions
38 // -------------------------------------------------------------
39  if ( ( A.dim1() != A.dim2() ) ||
40  ( A.dim1() != b.size() ) ||
41  ( A.dim1() != xk.size() ) ) {
42  cout << "Error: The Matrices don't have the right dimensions!" << endl;
43  exit(1);
44  }
45 // Check if the matrix A is diagonally dominant
46 // -------------------------------------------------------------
47  for (int i(0); i < A.dim1(); ++i){
48  double rowi(0.0);
49  for (int j(0); j < A.dim2(); ++j){
50  rowi += A(i,j);
51  }
52  if (!(rowi < 2.0*A(i,i))) return false;
53  }
54 // -------------------------------------------------------------
55 
56 
57 // Calculate and invert the diagonal elements once and for all
58 // -------------------------------------------------------------
59  valarray<double> invDIAG(A.dim1());
60  for (int i(0); i < invDIAG.size(); ++i) invDIAG[i] = 1.0 / A(i,i);
61 
62  valarray<complex<double> > xold(xk);
63  int iteration(0); // used to count iterations
64  int conv(0); // used to test convergence
65 
66 // Start the iteration loop
67 // -------------------------------------------------------------
68  while ( (iteration++ < MAXiter) && (conv < b.size()) ) {
69 
70  xold = xk;
71  for (int i(0); i < A.dim1(); ++i){
72  complex<double> sigma(0.0); // Temporary sum
73  for (int j(0); j < i; ++j){
74  sigma += A(i,j)*xk[j];
75  }
76  for (int j(i+1); j < A.dim2(); ++j){
77  sigma += A(i,j)*xk[j];
78  }
79  xk[i] = invDIAG[i] * (b[i] - sigma);
80  }
81 
82  // Calculate Dx = x_old - x_new
83  xold -= xk;
84 
85 // If the relative error < prescribed tolerance everywhere the method has converged
86 // |Dx(i)| < t*|x(i)| + eps
87  conv = 0;
88  while ( ( conv < b.size() ) &&
89  ( abs(xold[conv]) < (tol*abs(xk[conv] + 20.0*DBL_MIN)) ) ){
90  ++conv;
91  }
92 
93  //----> Output for testing
94  //--------------------------------
95  //cout << "iteration = " << iteration << " ";
96  //for (int i(0); i < b.size(); ++i){
97  // cout << xk[i] << " ";
98  //}
99  //cout << "\n";
100  //--------------------------------
101 
102  }
103 
104  //----> Output for testing
105  //--------------------------------
106  // cout << "Iterations = " << iteration-1 <<"\n";
107  //for (int i(0); i < b.size(); ++i) {
108  // cout << "Error |Dx| = " << abs(xold[i])
109  // << ", "
110  // << "Tolerance * |x| = " << tol*abs(xk[i]) <<"\n";
111  //}
112  //--------------------------------
113 
114  return true;
115  }
116 //-------------------------------------------------------------------
117 //*******************************************************************
118 
119 //*******************************************************************
120 //-------------------------------------------------------------------
121  void TridiagonalSolve (const valarray<double>& a,
122  const valarray<double>& b,
123  valarray<double>& c,
124  valarray<complex<double> > d,
125  valarray<complex<double> >& x) {
126 //-------------------------------------------------------------------
127 // Fills solution into x. Warning: will modify c and d!
128 //-------------------------------------------------------------------
129  size_t n(x.size());
130  // Modify the coefficients.
131  c[0] /= b[0]; // Division by zero risk.
132  d[0] /= b[0]; // Division by zero would imply a singular matrix.
133  for (int i(1); i < n; ++i){
134  double id(1.0/(b[i]-c[i-1]*a[i])); // Division by zero risk.
135  c[i] *= id; // Last value calculated is redundant.
136  d[i] -= d[i-1] * a[i];
137  d[i] *= id; // d[i] = (d[i] - d[i-1] * a[i]) * id
138  }
139 
140  // Now back substitute.
141  x[n-1] = d[n-1];
142  for (int i(n-2); i > -1; --i){
143  x[i] = d[i];
144  x[i] -= c[i] * x[i+1]; // x[i] = d[i] - c[i] * x[i + 1];
145  }
146  }
147 //-------------------------------------------------------------------
148 
149 //*******************************************************************
150 //-------------------------------------------------------------------
151 void TridiagonalSolve (const valarray<double>& a,
152  const valarray<double>& b,
153  valarray<double>& c,
154  valarray<double> d,
155  valarray<double>& x) {
156 //-------------------------------------------------------------------
157 // Fills solution into x. Warning: will modify c and d!
158 //-------------------------------------------------------------------
159  size_t n(x.size());
160  // Modify the coefficients.
161  c[0] /= b[0]; // Division by zero risk.
162  d[0] /= b[0]; // Division by zero would imply a singular matrix.
163  for (int i(1); i < n; ++i){
164  double id(1.0/(b[i]-c[i-1]*a[i])); // Division by zero risk.
165  c[i] *= id; // Last value calculated is redundant.
166  d[i] -= d[i-1] * a[i];
167  d[i] *= id; // d[i] = (d[i] - d[i-1] * a[i]) * id
168  }
169 
170  // Now back substitute.
171  x[n-1] = d[n-1];
172  for (int i(n-2); i > -1; --i){
173  x[i] = d[i];
174  x[i] -= c[i] * x[i+1]; // x[i] = d[i] - c[i] * x[i + 1];
175  }
176 }
177 //-------------------------------------------------------------------
178 
179 
180 
181 //*******************************************************************
182 //-------------------------------------------------------------------
183  void TridiagonalSolve (const valarray<complex<double>>& a,
184  const valarray<complex<double>>& b,
185  valarray<complex<double>>& c,
186  valarray<complex<double>> d,
187  valarray<complex<double>>& x) {
188 //-------------------------------------------------------------------
189 // Fills solution into x. Warning: will modify c and d!
190 //-------------------------------------------------------------------
191  size_t n(x.size());
192  // Modify the coefficients.
193  c[0] /= b[0]; // Division by zero risk.
194  d[0] /= b[0]; // Division by zero would imply a singular matrix.
195  for (int i(1); i < n; ++i){
196  complex<double> id(1.0/(b[i]-c[i-1]*a[i])); // Division by zero risk.
197  c[i] *= id; // Last value calculated is redundant.
198  d[i] -= d[i-1] * a[i];
199  d[i] *= id; // d[i] = (d[i] - d[i-1] * a[i]) * id
200  }
201 
202  // Now back substitute.
203  x[n-1] = d[n-1];
204  for (int i(n-2); i > -1; --i){
205  x[i] = d[i];
206  x[i] -= c[i] * x[i+1]; // x[i] = d[i] - c[i] * x[i + 1];
207  }
208  }
209 //-------------------------------------------------------------------
210 
211 
212 //-------------------------------------------------------------------
213 //*******************************************************************
214 
215 //-------------------------------------------------------------------
217  valarray<double> & d,
218  valarray<double> & xk) {
219 //-------------------------------------------------------------------
220 // Fills solution into xk. The other matrices are not modified
221 // The function returns "false" if the matrix A is not diagonally
222 // dominant
223 //-------------------------------------------------------------------
224 
225 // The Matrices all have the right dimensions
226 // -------------------------------------------------------------
227  if ( ( A.dim1() != A.dim2() ) ||
228  ( A.dim1() != d.size() ) ||
229  ( A.dim1() != xk.size() ) ) {
230  cout << "Error: The Matrices don't have the right dimensions!" << endl;
231  exit(1);
232  }
233 // -------------------------------------------------------------
234 
235  valarray<double> a(d.size()), b(d.size()), c(d.size());
236 
237  for (int i(0); i < A.dim1()-1; ++i){
238  a[i+1] = A(i+1,i);
239  }
240  for (int i(0); i < A.dim1(); ++i){
241  b[i] = A(i,i);
242  }
243  for (int i(0); i < A.dim1()-1; ++i){
244  c[i] = A(i,i+1);
245  }
246 
247 // valarray< double > dcopy(d);
248  TridiagonalSolve(a,b,c,d,xk);
249 
250  return true;
251 }
252 
253 //-------------------------------------------------------------------
255  valarray<complex<double> >& d,
256  valarray<complex<double> >& xk) {
257 //-------------------------------------------------------------------
258 // Fills solution into xk. The other matrices are not modified
259 // The function returns "false" if the matrix A is not diagonally
260 // dominant
261 //-------------------------------------------------------------------
262 
263 // The Matrices all have the right dimensions
264 // -------------------------------------------------------------
265  if ( ( A.dim1() != A.dim2() ) ||
266  ( A.dim1() != d.size() ) ||
267  ( A.dim1() != xk.size() ) ) {
268  cout << "Error: The Matrices don't have the right dimensions!" << endl;
269  exit(1);
270  }
271 // -------------------------------------------------------------
272 
273  valarray<double> a(d.size()), b(d.size()), c(d.size());
274 
275  for (int i(0); i < A.dim1()-1; ++i){
276  a[i+1] = A(i+1,i);
277  }
278  for (int i(0); i < A.dim1(); ++i){
279  b[i] = A(i,i);
280  }
281  for (int i(0); i < A.dim1()-1; ++i){
282  c[i] = A(i,i+1);
283  }
284 
285 // valarray< double > dcopy(d);
286  TridiagonalSolve(a,b,c,d,xk);
287 
288  return true;
289 }
290 
291 //-------------------------------------------------------------------
292 //*******************************************************************
293 //-------------------------------------------------------------------
294  bool Thomas_Tridiagonal(Array2D<complex<double>>& A,
295  valarray<complex<double> >& d,
296  valarray<complex<double> >& xk) {
297 //-------------------------------------------------------------------
298 // Fills solution into xk. The other matrices are not modified
299 // The function returns "false" if the matrix A is not diagonally
300 // dominant
301 //-------------------------------------------------------------------
302 
303 // The Matrices all have the right dimensions
304 // -------------------------------------------------------------
305  if ( ( A.dim1() != A.dim2() ) ||
306  ( A.dim1() != d.size() ) ||
307  ( A.dim1() != xk.size() ) ) {
308  cout << "Error: The Matrices don't have the right dimensions!" << endl;
309  exit(1);
310  }
311 // -------------------------------------------------------------
312 
313  valarray<complex<double>> a(d.size()), b(d.size()), c(d.size());
314 
315  for (int i(0); i < A.dim1()-1; ++i){
316  a[i+1] = A(i+1,i);
317  }
318  for (int i(0); i < A.dim1(); ++i){
319  b[i] = A(i,i);
320  }
321  for (int i(0); i < A.dim1()-1; ++i){
322  c[i] = A(i,i+1);
323  }
324 
325 // valarray< double > dcopy(d);
326  TridiagonalSolve(a,b,c,d,xk);
327 
328  return true;
329  }
330 
331 //-------------------------------------------------------------------
332 //*******************************************************************
333 //
334 //*******************************************************************
335 //-------------------------------------------------------------------
336  complex <double> Det33(/*const valarray<double>& D, */
337  Array2D<complex <double>>& A) { // Determinant for a 3*3 system
338 //-------------------------------------------------------------------
339  return A(0,0) * ( A(1,1)*A(2,2) - A(2,1)*A(1,2) ) -
340  A(1,0) * ( A(0,1)*A(2,2) - A(2,1)*A(0,2) ) +
341  A(2,0) * ( A(0,1)*A(1,2) - A(1,1)*A(0,2) );
342  }
343 //-------------------------------------------------------------------
344 
345 //-------------------------------------------------------------------
346  complex <double> Detx33(valarray<complex <double>>& D,
347  Array2D<complex <double>>& A) { // Determinant x for a 3*3 system
348 //-------------------------------------------------------------------
349  return D[0] * ( A(1,1)*A(2,2) - A(2,1)*A(1,2) ) -
350  D[1] * ( A(0,1)*A(2,2) - A(2,1)*A(0,2) ) +
351  D[2] * ( A(0,1)*A(1,2) - A(1,1)*A(0,2) );
352  }
353 //-------------------------------------------------------------------
354 
355 //-------------------------------------------------------------------
356  complex <double> Dety33(valarray<complex <double>>& D,
357  Array2D<complex <double>>& A) { // Determinant y for a 3*3 system
358 //-------------------------------------------------------------------
359  return A(0,0) * ( D[1]*A(2,2) - D[2]*A(1,2) ) -
360  A(1,0) * ( D[0]*A(2,2) - D[2]*A(0,2) ) +
361  A(2,0) * ( D[0]*A(1,2) - D[1]*A(0,2) );
362  }
363 //-------------------------------------------------------------------
364 
365 //-------------------------------------------------------------------
366  complex <double> Detz33(valarray<complex <double>>& D,
367  Array2D<complex <double>>& A) { // Determinant z for a 3*3 system
368 //-------------------------------------------------------------------
369  return A(0,0) * ( A(1,1)*D[2] - A(2,1)*D[1] ) -
370  A(1,0) * ( A(0,1)*D[2] - A(2,1)*D[0] ) +
371  A(2,0) * ( A(0,1)*D[1] - A(1,1)*D[0] );
372  }
373 //-------------------------------------------------------------------
374 
375 // Convert data structure to float structure
376 //
377 // @param[in] vDouble The v double
378 //
379 // @return float structure
380 //
381 valarray<float> vfloat(const valarray<double>& vDouble) {
382  valarray<float> vf(vDouble.size());
383  for (size_t i(0); i < vf.size(); ++i) {
384  vf[i] = static_cast<float>(vDouble[i]);
385  }
386  return vf;
387 }
388 
389 
397 vector<float> vfloat(const vector<double> vDouble) {
398  vector<float> vf;
399  for (size_t i(0); i < vDouble.size(); ++i) {
400  vf.push_back(static_cast<float>(vDouble[i]));
401  }
402  return vf;
403 }
404 vector<float> vfloat(const vector<complex<double> > vDouble) {
405  vector<float> vf;
406  for (size_t i(0); i < vDouble.size(); ++i) {
407  vf.push_back(static_cast<float>(vDouble[i].real()));
408  }
409  return vf;
410 }
411 
412 vector<float> vfloat_complex(const vector<complex<double> > vDouble){
413  vector<float> vf;
414  for (size_t i(0); i < vDouble.size(); ++i) {
415  vf.push_back(static_cast<float>(vDouble[i].imag()));
416  }
417  return vf;
418 }
419 //--------------------------------------------------------------
420 
421 valarray<double> df_4thorder(const valarray<double>& f) {
422  valarray<double> df(f.size());
423 
424  df[0] = f[1]-f[0];
425  df[1] = 1.0/12.0*(f[4]-6.0*f[3]+18.0*f[2]-10.0*f[1]-3.0*f[0]);
426 
427  for (size_t i(2); i < df.size()-2; ++i) {
428  df[i] = 1.0/12.0*(-f[i+2]+8.0*f[i+1]-8.0*f[i-1]+f[i-2]);
429  }
430 
431  df[df.size()-2] = 1.0/12.0*(3.0*f[df.size()-1]+10.0*f[df.size()-2]-18.0*f[df.size()-3]+6.0*f[df.size()-4]-f[df.size()-5]);
432  df[df.size()-1] = f[df.size()-1]-f[df.size()-2];
433 
434  return df;
435 }
436 
437 valarray<double> df_4thorder(valarray<double>& f) {
438  valarray<double> df(f.size());
439 
440  df[0] = f[1]-f[0];
441  df[1] = 1.0/12.0*(f[4]-6.0*f[3]+18.0*f[2]-10.0*f[1]-3.0*f[0]);
442 
443  for (size_t i(2); i < df.size()-2; ++i) {
444  df[i] = 1.0/12.0*(-f[i+2]+8.0*f[i+1]-8.0*f[i-1]+f[i-2]);
445  }
446 
447  df[df.size()-2] = 1.0/12.0*(3.0*f[df.size()-1]+10.0*f[df.size()-2]-18.0*f[df.size()-3]+6.0*f[df.size()-4]-f[df.size()-5]);
448  df[df.size()-1] = f[df.size()-1]-f[df.size()-2];
449 
450  return df;
451 }
452 
453 valarray<complex<double> > df_4thorder(const valarray<complex<double> >& f) {
454  valarray<complex<double> > df(f.size());
455 
456  df[0] = f[1]-f[0];
457  df[1] = 1.0/12.0*(f[4]-6.0*f[3]+18.0*f[2]-10.0*f[1]-3.0*f[0]);
458 
459  for (size_t i(2); i < df.size()-2; ++i) {
460  df[i] = 1.0/12.0*(-f[i+2]+8.0*f[i+1]-8.0*f[i-1]+f[i-2]);
461  }
462 
463  df[df.size()-2] = 1.0/12.0*(3.0*f[df.size()-1]+10.0*f[df.size()-2]-18.0*f[df.size()-3]+6.0*f[df.size()-4]-f[df.size()-5]);
464  df[df.size()-1] = f[df.size()-1]-f[df.size()-2];
465 
466  return df;
467 }
468 
469  Array2D<complex<double> > df1_4thorder(Array2D<complex<double> >& f) {
470  Array2D<complex<double> > df(f.dim1(),f.dim2());
471 
472  for (long i2(0); i2<f.dim1();++i2){
473 
474  df(0,i2) = f(1,i2)-f(0,i2);
475  df(1,i2) = 1.0/12.0*(f(4,i2)-6.0*f(3,i2)+18.0*f(2,i2)-10.0*f(1,i2)-3.0*f(0,i2));
476 
477  for (long i1(2); i1<f.dim1()-2;++i1){
478  df(i1,i2) = 1.0/12.0*(-f(i1+2,i2)+8.0*f(i1+1,i2)-8.0*f(i1-1,i2)+f(i1-2,i2));
479  }
480 
481  df(f.dim1()-2,i2) = 1.0/12.0*(3.0*f(f.dim2()-1,i2)+10.0*f(f.dim2()-2,i2)-18.0*f(f.dim2()-3,i2)+6.0*f(f.dim2()-4,i2)-f(f.dim2()-5,i2));
482  df(f.dim1()-1,i2) = f(f.dim2()-1,i2)-f(f.dim2()-2,i2);
483 
484  }
485 
486  return df;
487 }
488 
489  Array2D<complex<double> > df2_4thorder(Array2D<complex<double> >& f) {
490  Array2D<complex<double> > df(f.dim1(),f.dim2());
491 
492  for (long i1(0); i1<f.dim1();++i1){
493 
494  df(i1,0) = f(i1,1)-f(i1,0);
495  df(i1,1) = 1.0/12.0*(f(i1,4)-6.0*f(i1,3)+18.0*f(i1,2)-10.0*f(i1,1)-3.0*f(i1,0));
496 
497  for (long i2(2); i2<f.dim2()-2;++i2){
498  df(i1,i2) = 1.0/12.0*(-f(i1,i2+2)+8.0*f(i1,i2+1)-8.0*f(i1,i2-1)+f(i1,i2-2));
499  }
500 
501  df(i1,f.dim2()-2) = 1.0/12.0*(3.0*f(i1,f.dim2()-1)+10.0*f(i1,f.dim2()-2)-18.0*f(i1,f.dim2()-3)+6.0*f(i1,f.dim2()-4)-f(i1,f.dim2()-5));
502  df(i1,f.dim2()-1) = f(i1,f.dim2()-1)-f(i1,f.dim2()-2);
503 
504  }
505 
506  return df;
507 }
508 
bool Thomas_Tridiagonal(Array2D< double > &A, valarray< double > &d, valarray< double > &xk)
The tridiagonal solver for implicit collisions.
Definition: nmethods.cpp:216
vector< float > vfloat_complex(const vector< complex< double > > vDouble)
Definition: nmethods.cpp:412
valarray< double > df_4thorder(const valarray< double > &f)
Definition: nmethods.cpp:421
Underlying data structures.
Array2D< complex< double > > df1_4thorder(Array2D< complex< double > > &f)
Definition: nmethods.cpp:469
valarray< float > vfloat(const valarray< double > &vDouble)
Definition: nmethods.cpp:381
complex< double > Detx33(valarray< complex< double >> &D, Array2D< complex< double >> &A)
Definition: nmethods.cpp:346
complex< double > Detz33(valarray< complex< double >> &D, Array2D< complex< double >> &A)
Definition: nmethods.cpp:366
size_t dim1() const
Definition: lib-array.h:289
size_t dim2() const
Definition: lib-array.h:290
void TridiagonalSolve(const valarray< double > &a, const valarray< double > &b, valarray< double > &c, valarray< complex< double > > d, valarray< complex< double > > &x)
Set up tridiagonal solver.
Definition: nmethods.cpp:121
complex< double > Det33(Array2D< complex< double >> &A)
Definition: nmethods.cpp:336
Array2D< complex< double > > df2_4thorder(Array2D< complex< double > > &f)
Definition: nmethods.cpp:489
complex< double > Dety33(valarray< complex< double >> &D, Array2D< complex< double >> &A)
Definition: nmethods.cpp:356
bool Gauss_Seidel(Array2D< double > &A, valarray< complex< double > > &b, valarray< complex< double > > &xk)
Performs Gauss-Seidel method on Ax = b.
Definition: nmethods.cpp:29