Garfield++ v1r0
A toolkit for the detailed simulation of particle detectors based on ionisation measurement in gases and semiconductors
Loading...
Searching...
No Matches
Medium.cc
Go to the documentation of this file.
1#include <iostream>
2#include <iomanip>
3#include <cmath>
4
5#include "Medium.hh"
8#include "Random.hh"
9#include "Numerics.hh"
10
11namespace Garfield {
12
13int Medium::m_idCounter = -1;
14
16 : m_className("Medium"),
17 m_id(++m_idCounter),
18 m_name(""),
19 m_temperature(293.15),
20 m_pressure(760.),
21 m_epsilon(1.),
22 m_nComponents(1),
23 m_z(1.),
24 m_a(0.),
25 m_density(0.),
26 m_driftable(false),
27 m_microscopic(false),
28 m_ionisable(false),
29 m_w(0.),
30 m_fano(0.),
31 m_isChanged(true),
32 m_debug(false),
33 m_map2d(false) {
34
35 // Initialise the transport tables.
36 m_nEfields = 0;
37 m_nBfields = 1;
38 m_nAngles = 1;
39
40 eFields.clear();
41 bFields.clear();
42 bFields.assign(1, 0.);
43 bAngles.clear();
44 bAngles.assign(1, 0.);
45
53 tabElectronDiffLong.clear();
57 tabElectronTownsend.clear();
61 tabElectronDiffTens.clear();
62
63 m_hasHoleVelocityE = false;
64 tabHoleVelocityE.clear();
65 m_hasHoleVelocityB = false;
66 tabHoleVelocityB.clear();
68 tabHoleVelocityExB.clear();
69 m_hasHoleDiffLong = false;
70 tabHoleDiffLong.clear();
71 m_hasHoleDiffTrans = false;
72 tabHoleDiffTrans.clear();
73 m_hasHoleTownsend = false;
74 tabHoleTownsend.clear();
75 m_hasHoleAttachment = false;
76 tabHoleAttachment.clear();
77 m_hasHoleDiffTens = false;
78 tabHoleDiffTens.clear();
79
80 m_hasIonMobility = false;
81 tabIonMobility.clear();
82 m_hasIonDiffLong = false;
83 tabIonDiffLong.clear();
84 m_hasIonDiffTrans = false;
85 tabIonDiffTrans.clear();
87 tabIonDissociation.clear();
88
101
102 m_intpVelocity = 2;
103 m_intpDiffusion = 2;
104 m_intpTownsend = 2;
106 m_intpMobility = 2;
108
112
113 // Set the default grid.
114 SetFieldGrid(100., 100000., 20, true, 0., 0., 1, 0., 0., 1);
115}
116
117void Medium::SetTemperature(const double& t) {
118
119 if (t <= 0.) {
120 std::cerr << m_className << "::SetTemperature:\n";
121 std::cerr << " Temperature [K] must be greater than zero.\n";
122 return;
123 }
124 m_temperature = t;
125 m_isChanged = true;
126}
127
128void Medium::SetPressure(const double& p) {
129
130 if (p <= 0.) {
131 std::cerr << m_className << "::SetPressure:\n";
132 std::cerr << " Pressure [Torr] must be greater than zero.\n";
133 return;
134 }
135 m_pressure = p;
136 m_isChanged = true;
137}
138
139void Medium::SetDielectricConstant(const double& eps) {
140
141 if (eps < 1.) {
142 std::cerr << m_className << "::SetDielectricConstant:\n";
143 std::cerr << " Dielectric constant must be >= 1.\n";
144 return;
145 }
146 m_epsilon = eps;
147 m_isChanged = true;
148}
149
151
152 return m_density * AtomicMassUnit * m_a;
153}
154
155void Medium::GetComponent(const unsigned int& i,
156 std::string& label, double& f) {
157
158 if (i >= m_nComponents) {
159 std::cerr << m_className << "::GetComponent:\n";
160 std::cerr << " Index out of range.\n";
161 }
162
163 label = m_name;
164 f = 1.;
165}
166
167void Medium::SetAtomicNumber(const double& z) {
168
169 if (z < 1.) {
170 std::cerr << m_className << "::SetAtomicNumber:\n";
171 std::cerr << " Atomic number must be >= 1.\n";
172 return;
173 }
174 m_z = z;
175 m_isChanged = true;
176}
177
178void Medium::SetAtomicWeight(const double& a) {
179
180 if (a <= 0.) {
181 std::cerr << m_className << "::SetAtomicWeight:\n";
182 std::cerr << " Atomic weight must be greater than zero.\n";
183 return;
184 }
185 m_a = a;
186 m_isChanged = true;
187}
188
189void Medium::SetNumberDensity(const double& n) {
190
191 if (n <= 0.) {
192 std::cerr << m_className << "::SetNumberDensity:\n";
193 std::cerr << " Density [cm-3] must be greater than zero.\n";
194 return;
195 }
196 m_density = n;
197 m_isChanged = true;
198}
199
200void Medium::SetMassDensity(const double& rho) {
201
202 if (rho <= 0.) {
203 std::cerr << m_className << "::SetMassDensity:\n";
204 std::cerr << " Density [g/cm3] must be greater than zero.\n";
205 return;
206 }
207
208 if (m_a <= 0.) {
209 std::cerr << m_className << "::SetMassDensity:\n";
210 std::cerr << " Atomic weight is not defined.\n";
211 return;
212 }
213 m_density = rho / (AtomicMassUnit * m_a);
214 m_isChanged = true;
215}
216
217bool Medium::ElectronVelocity(const double ex, const double ey, const double ez,
218 const double bx, const double by, const double bz,
219 double& vx, double& vy, double& vz) {
220
221 vx = vy = vz = 0.;
222 // Make sure there is at least a table of velocities along E.
223 if (!m_hasElectronVelocityE) return false;
224
225 // Compute the magnitude of the electric field.
226 const double e = sqrt(ex * ex + ey * ey + ez * ez);
227 const double e0 = ScaleElectricField(e);
228 if (e < Small || e0 < Small) return false;
229
230 // Compute the magnitude of the magnetic field.
231 const double b = sqrt(bx * bx + by * by + bz * bz);
232
233 // Compute the angle between B field and E field.
234 double ebang = 0.;
235 if (e * b > 0.) {
236 const double eb = fabs(ex * bx + ey * by + ez * bz);
237 if (eb > 0.2 * e * b) {
238 ebang = asin(std::min(
239 1., sqrt(pow(ex * by - ey * bx, 2) + pow(ex * bz - ez * bx, 2) +
240 pow(ez * by - ey * bz, 2)) /
241 (e * b)));
242 } else {
243 ebang = acos(std::min(1., eb / (e * b)));
244 }
245 } else {
246 ebang = bAngles[0];
247 }
248
249 if (b < Small) {
250 // No magnetic field.
251
252 // Calculate the velocity along E.
253 double ve = 0.;
254 if (m_map2d) {
256 m_nAngles, m_nBfields, m_nEfields, ebang, b, e0, ve,
258 std::cerr << m_className << "::ElectronVelocity:\n";
259 std::cerr << " Interpolation of velocity along E failed.\n";
260 return false;
261 }
262 } else {
265 }
266 const double q = -1.;
267 const double mu = q * ve / e;
268 vx = mu * ex;
269 vy = mu * ey;
270 vz = mu * ez;
271
273 // Magnetic field, velocities along ExB and Bt available
274
275 // Compute unit vectors along E, E x B and Bt.
276 double ue[3] = {ex / e, ey / e, ez / e};
277 double uexb[3] = {ey * bz - ez * by, ez * bx - ex * bz, ex * by - ey * bx};
278 const double exb =
279 sqrt(uexb[0] * uexb[0] + uexb[1] * uexb[1] + uexb[2] * uexb[2]);
280 if (exb > 0.) {
281 uexb[0] /= exb;
282 uexb[1] /= exb;
283 uexb[2] /= exb;
284 } else {
285 uexb[0] = ue[0];
286 uexb[1] = ue[1];
287 uexb[2] = ue[2];
288 }
289
290 double ubt[3] = {uexb[1] * ez - uexb[2] * ey, uexb[2] * ex - uexb[0] * ez,
291 uexb[0] * ey - uexb[1] * ex};
292 const double bt = sqrt(ubt[0] * ubt[0] + ubt[1] * ubt[1] + ubt[2] * ubt[2]);
293
294 if (bt > 0.) {
295 ubt[0] /= bt;
296 ubt[1] /= bt;
297 ubt[2] /= bt;
298 } else {
299 ubt[0] = ue[0];
300 ubt[1] = ue[1];
301 ubt[2] = ue[2];
302 }
303
304 if (m_debug) {
305 std::cout << std::setprecision(5);
306 std::cout << m_className << "::ElectronVelocity:\n";
307 std::cout << " unit vector along E: (" << ue[0] << ", " << ue[1]
308 << ", " << ue[2] << ")\n";
309 std::cout << " unit vector along E x B: (" << uexb[0] << ", "
310 << uexb[1] << ", " << uexb[2] << ")\n";
311 std::cout << " unit vector along Bt: (" << ubt[0] << ", " << ubt[1]
312 << ", " << ubt[2] << ")\n";
313 }
314
315 // Calculate the velocities in all directions.
316 double ve = 0., vbt = 0., vexb = 0.;
317 if (m_map2d) {
319 m_nAngles, m_nBfields, m_nEfields, ebang, b, e0, ve,
321 std::cerr << m_className << "::ElectronVelocity:\n";
322 std::cerr << " Interpolation of velocity along E failed.\n";
323 return false;
324 }
326 m_nAngles, m_nBfields, m_nEfields, ebang, b, e0, vexb,
328 std::cerr << m_className << "::ElectronVelocity:\n";
329 std::cerr << " Interpolation of velocity along ExB failed.\n";
330 return false;
331 }
333 m_nAngles, m_nBfields, m_nEfields, ebang, b, e0, vbt,
335 std::cerr << m_className << "::ElectronVelocity:\n";
336 std::cerr << " Interpolation of velocity along Bt failed.\n";
337 return false;
338 }
339 } else {
349 }
350 const double q = -1.;
351 if (ex * bx + ey * by + ez * bz > 0.) vbt = fabs(vbt);
352 else vbt = -fabs(vbt);
353 vx = q * (ve * ue[0] + q * q * vbt * ubt[0] + q * vexb * uexb[0]);
354 vy = q * (ve * ue[1] + q * q * vbt * ubt[1] + q * vexb * uexb[1]);
355 vz = q * (ve * ue[2] + q * q * vbt * ubt[2] + q * vexb * uexb[2]);
356
357 } else {
358 // Magnetic field, velocities along ExB, Bt not available
359
360 // Calculate the velocity along E.
361 double ve = 0.;
362 if (m_map2d) {
364 m_nAngles, m_nBfields, m_nEfields, ebang, b, e0, ve,
366 std::cerr << m_className << "::ElectronVelocity:\n";
367 std::cerr << " Interpolation of velocity along E failed.\n";
368 return false;
369 }
370 } else {
374 }
375
376 const double q = -1.;
377 const double mu = q * ve / e;
378 const double eb = bx * ex + by * ey + bz * ez;
379 const double nom = 1. + pow(mu * b, 2);
380 vx = mu * (ex + mu * (ey * bz - ez * by) + mu * mu * bx * eb) / nom;
381 vy = mu * (ey + mu * (ez * bx - ex * bz) + mu * mu * by * eb) / nom;
382 vz = mu * (ez + mu * (ex * by - ey * bx) + mu * mu * bz * eb) / nom;
383 }
384
385 return true;
386}
387
388bool Medium::ElectronDiffusion(const double ex, const double ey,
389 const double ez, const double bx,
390 const double by, const double bz, double& dl,
391 double& dt) {
392
393 dl = dt = 0.;
394 // Compute the magnitude of the electric field.
395 const double e = sqrt(ex * ex + ey * ey + ez * ez);
396 const double e0 = ScaleElectricField(e);
397 if (e < Small || e0 < Small) return true;
398
399 if (m_map2d) {
400 // Compute the magnitude of the magnetic field.
401 const double b = sqrt(bx * bx + by * by + bz * bz);
402 // Compute the angle between B field and E field.
403 double ebang = 0.;
404 if (e * b > 0.) {
405 const double eb = fabs(ex * bx + ey * by + ez * bz);
406 if (eb > 0.2 * e * b) {
407 ebang = asin(std::min(
408 1., sqrt(pow(ex * by - ey * bx, 2) + pow(ex * bz - ez * bx, 2) +
409 pow(ez * by - ey * bz, 2)) /
410 (e * b)));
411 } else {
412 ebang = acos(std::min(1., eb / (e * b)));
413 }
414 } else {
415 ebang = bAngles[0];
416 }
417
418 // Interpolate.
421 m_nAngles, m_nBfields, m_nEfields, ebang, b, e0, dl,
423 dl = 0.;
424 }
425 }
428 m_nAngles, m_nBfields, m_nEfields, ebang, b, e0, dt,
430 dt = 0.;
431 }
432 }
433 } else {
438 }
443 }
444 }
445
446 // If no data available, calculate
447 // the diffusion coefficients using the Einstein relation
449 const double d = sqrt(2. * BoltzmannConstant * m_temperature / e);
450 if (!m_hasElectronDiffLong) dl = d;
451 if (!m_hasElectronDiffTrans) dt = d;
452 }
453 // Verify values and apply scaling.
454 if (dl < 0.) dl = 0.;
455 if (dt < 0.) dt = 0.;
456 dl = ScaleDiffusion(dl);
457 dt = ScaleDiffusion(dt);
458
459 return true;
460}
461
462bool Medium::ElectronDiffusion(const double ex, const double ey,
463 const double ez, const double bx,
464 const double by, const double bz,
465 double cov[3][3]) {
466
467 // Initialise the tensor.
468 cov[0][0] = cov[0][1] = cov[0][2] = 0.;
469 cov[1][0] = cov[1][1] = cov[1][2] = 0.;
470 cov[2][0] = cov[2][1] = cov[2][2] = 0.;
471
472 if (!m_hasElectronDiffTens) return false;
473
474 // Compute the magnitude of the electric field.
475 const double e = sqrt(ex * ex + ey * ey + ez * ez);
476 const double e0 = ScaleElectricField(e);
477 if (e < Small || e0 < Small) return true;
478
479 if (m_map2d) {
480 // Compute the magnitude of the magnetic field.
481 const double b = sqrt(bx * bx + by * by + bz * bz);
482
483 // Compute the angle between B field and E field.
484 double ebang = 0.;
485 if (e * b > 0.) {
486 const double eb = fabs(ex * bx + ey * by + ez * bz);
487 if (eb > 0.2 * e * b) {
488 ebang = asin(std::min(
489 1., sqrt(pow(ex * by - ey * bx, 2) + pow(ex * bz - ez * bx, 2) +
490 pow(ez * by - ey * bz, 2)) /
491 (e * b)));
492 } else {
493 ebang = acos(std::min(1., eb / (e * b)));
494 }
495 } else {
496 ebang = bAngles[0];
497 }
498 // Interpolate.
499 double diff = 0.;
500 for (int l = 0; l < 6; ++l) {
502 m_nAngles, m_nBfields, m_nEfields, ebang, b, e0, diff,
504 diff = 0.;
505 }
506 // Apply scaling.
507 diff = ScaleDiffusionTensor(diff);
508 if (l < 3) {
509 cov[l][l] = diff;
510 } else if (l == 3) {
511 cov[0][1] = cov[1][0] = diff;
512 } else if (l == 4) {
513 cov[0][2] = cov[2][0] = diff;
514 } else if (l == 5) {
515 cov[1][2] = cov[2][1] = diff;
516 }
517 }
518 } else {
519 // Interpolate.
520 for (int l = 0; l < 6; ++l) {
521 double diff =
525 // Apply scaling.
526 diff = ScaleDiffusionTensor(diff);
527 if (l < 3) {
528 cov[l][l] = diff;
529 } else if (l == 3) {
530 cov[0][1] = cov[1][0] = diff;
531 } else if (l == 4) {
532 cov[0][2] = cov[2][0] = diff;
533 } else if (l == 5) {
534 cov[1][2] = cov[2][1] = diff;
535 }
536 }
537 }
538
539 return true;
540}
541
542bool Medium::ElectronTownsend(const double ex, const double ey, const double ez,
543 const double bx, const double by, const double bz,
544 double& alpha) {
545
546 alpha = 0.;
547 if (!m_hasElectronTownsend) return false;
548 // Compute the magnitude of the electric field.
549 const double e = sqrt(ex * ex + ey * ey + ez * ez);
550 const double e0 = ScaleElectricField(e);
551 if (e < Small || e0 < Small) return true;
552
553 if (m_map2d) {
554 // Compute the magnitude of the magnetic field.
555 const double b = sqrt(bx * bx + by * by + bz * bz);
556
557 // Compute the angle between B field and E field.
558 double ebang = 0.;
559 if (e * b > 0.) {
560 const double eb = fabs(ex * bx + ey * by + ez * bz);
561 if (eb > 0.2 * e * b) {
562 ebang = asin(std::min(
563 1., sqrt(pow(ex * by - ey * bx, 2) + pow(ex * bz - ez * bx, 2) +
564 pow(ez * by - ey * bz, 2)) /
565 (e * b)));
566 } else {
567 ebang = acos(std::min(1., eb / (e * b)));
568 }
569 } else {
570 ebang = bAngles[0];
571 }
572 // Interpolate.
573 if (e0 < eFields[thrElectronTownsend]) {
575 m_nAngles, m_nBfields, m_nEfields, ebang, b, e0, alpha,
576 1)) {
577 alpha = -30.;
578 }
579 } else {
581 m_nAngles, m_nBfields, m_nEfields, ebang, b, e0, alpha,
583 alpha = -30.;
584 }
585 }
586 } else {
587 // Interpolate.
588 if (e0 < eFields[thrElectronTownsend]) {
589 alpha = Interpolate1D(e0, tabElectronTownsend[0][0], eFields, 1,
591 } else {
592 alpha = Interpolate1D(e0, tabElectronTownsend[0][0], eFields,
595 }
596 }
597
598 if (alpha < -20.) {
599 alpha = 0.;
600 } else {
601 alpha = exp(alpha);
602 }
603
604 // Apply scaling.
605 alpha = ScaleTownsend(alpha);
606 return true;
607}
608
609bool Medium::ElectronAttachment(const double ex, const double ey,
610 const double ez, const double bx,
611 const double by, const double bz, double& eta) {
612
613 eta = 0.;
614 if (!m_hasElectronAttachment) return false;
615 // Compute the magnitude of the electric field.
616 const double e = sqrt(ex * ex + ey * ey + ez * ez);
617 const double e0 = ScaleElectricField(e);
618 if (e < Small || e0 < Small) return true;
619
620 if (m_map2d) {
621 // Compute the magnitude of the magnetic field.
622 const double b = sqrt(bx * bx + by * by + bz * bz);
623
624 // Compute the angle between B field and E field.
625 double ebang = 0.;
626 if (e * b > 0.) {
627 const double eb = fabs(ex * bx + ey * by + ez * bz);
628 if (eb > 0.2 * e * b) {
629 ebang = asin(std::min(
630 1., sqrt(pow(ex * by - ey * bx, 2) + pow(ex * bz - ez * bx, 2) +
631 pow(ez * by - ey * bz, 2)) /
632 (e * b)));
633 } else {
634 ebang = acos(std::min(1., eb / (e * b)));
635 }
636 } else {
637 ebang = bAngles[0];
638 }
639 // Interpolate.
640 if (e0 < eFields[thrElectronAttachment]) {
642 m_nAngles, m_nBfields, m_nEfields, ebang, b, e0, eta,
643 1)) {
644 eta = -30.;
645 }
646 } else {
648 m_nAngles, m_nBfields, m_nEfields, ebang, b, e0, eta,
650 eta = -30.;
651 }
652 }
653 } else {
654 // Interpolate.
655 if (e0 < eFields[thrElectronAttachment]) {
656 eta = Interpolate1D(e0, tabElectronAttachment[0][0], eFields, 1,
658 } else {
659 eta =
663 }
664 }
665
666 if (eta < -20.) {
667 eta = 0.;
668 } else {
669 eta = exp(eta);
670 }
671
672 // Apply scaling.
673 eta = ScaleAttachment(eta);
674 return true;
675}
676
677double Medium::GetElectronEnergy(const double px, const double py,
678 const double pz, double& vx, double& vy,
679 double& vz, const int band) {
680
681 if (band > 0) {
682 std::cerr << m_className << "::GetElectronEnergy:\n";
683 std::cerr << " Unknown band index.\n";
684 }
685
686 vx = SpeedOfLight * px / ElectronMass;
687 vy = SpeedOfLight * py / ElectronMass;
688 vz = SpeedOfLight * pz / ElectronMass;
689
690 return 0.5 * (px * px + py * py + pz * pz) / ElectronMass;
691}
692
693void Medium::GetElectronMomentum(const double e, double& px, double& py,
694 double& pz, int& band) {
695
696 const double p = sqrt(2. * ElectronMass * e) / SpeedOfLight;
697 const double ctheta = 1. - 2. * RndmUniform();
698 const double stheta = sqrt(1. - ctheta * ctheta);
699 const double phi = TwoPi * RndmUniform();
700
701 px = p * stheta * cos(phi);
702 py = p * stheta * sin(phi);
703 pz = p * ctheta;
704
705 band = -1;
706}
707
708double Medium::GetElectronNullCollisionRate(const int /*band*/) {
709
710 if (m_debug) {
711 std::cerr << m_className << "::GetElectronNullCollisionRate:\n";
712 std::cerr << " Function is not implemented.\n";
713 }
714 return 0.;
715}
716
717double Medium::GetElectronCollisionRate(const double /*e*/,
718 const int /*band*/) {
719
720 if (m_debug) {
721 std::cerr << m_className << "::GetElectronCollisionRate:\n";
722 std::cerr << " Function is not implemented.\n";
723 }
724 return 0.;
725}
726
727bool Medium::GetElectronCollision(const double e, int& type, int& level,
728 double& e1, double& dx, double& dy,
729 double& dz, int& nion, int& ndxc, int& band) {
730
731 type = level = -1;
732 e1 = e;
733 nion = ndxc = band = 0;
734 const double ctheta = 1. - 2 * RndmUniform();
735 const double stheta = sqrt(1. - ctheta * ctheta);
736 const double phi = TwoPi * RndmUniform();
737 dx = cos(phi) * stheta;
738 dy = sin(phi) * stheta;
739 dz = ctheta;
740
741 if (m_debug) {
742 std::cerr << m_className << "::GetElectronCollision:\n";
743 std::cerr << " Function is not implemented.\n";
744 }
745 return false;
746}
747
748bool Medium::GetIonisationProduct(const int i, int& type, double& energy) {
749
750 if (m_debug) {
751 std::cerr << m_className << "::GetIonisationProduct:\n";
752 std::cerr << " Ionisation product " << i << " requested.\n";
753 std::cerr << " Not supported. Program bug!\n";
754 }
755 type = 0;
756 energy = 0.;
757 return false;
758}
759
760bool Medium::GetDeexcitationProduct(const int i, double& t, double& s,
761 int& type, double& energy) {
762
763 if (m_debug) {
764 std::cerr << m_className << "::GetDeexcitationProduct:\n";
765 std::cerr << " Deexcitation product " << i << " requested.\n";
766 std::cerr << " Not supported. Program bug!\n";
767 }
768 t = s = energy = 0.;
769 type = 0;
770 return false;
771}
772
773bool Medium::HoleVelocity(const double ex, const double ey, const double ez,
774 const double bx, const double by, const double bz,
775 double& vx, double& vy, double& vz) {
776
777 vx = vy = vz = 0.;
778 // Make sure there is at least a table of velocities along E.
779 if (!m_hasHoleVelocityE) return false;
780
781 // Compute the magnitude of the electric field.
782 const double e = sqrt(ex * ex + ey * ey + ez * ez);
783 const double e0 = ScaleElectricField(e);
784 if (e < Small || e0 < Small) return true;
785
786 // Compute the magnitude of the magnetic field.
787 const double b = sqrt(bx * bx + by * by + bz * bz);
788
789 // Compute the angle between B field and E field.
790 double ebang = 0.;
791 if (e * b > 0.) {
792 const double eb = fabs(ex * bx + ey * by + ez * bz);
793 if (eb > 0.2 * e * b) {
794 ebang = asin(std::min(
795 1., sqrt(pow(ex * by - ey * bx, 2) + pow(ex * bz - ez * bx, 2) +
796 pow(ez * by - ey * bz, 2)) /
797 (e * b)));
798 } else {
799 ebang = acos(std::min(1., eb / (e * b)));
800 }
801 } else {
802 ebang = bAngles[0];
803 }
804
805 if (b < Small) {
806 // No magnetic field.
807 // Calculate the velocity along E.
808 double ve = 0.;
809 if (m_map2d) {
811 m_nAngles, m_nBfields, m_nEfields, ebang, b, e0, ve,
813 std::cerr << m_className << "::HoleVelocity:\n";
814 std::cerr << " Interpolation of velocity along E failed.\n";
815 return false;
816 }
817 } else {
820 }
821 const double q = 1.;
822 const double mu = q * ve / e;
823 vx = mu * ex;
824 vy = mu * ey;
825 vz = mu * ez;
826
828 // Magnetic field, velocities along ExB and Bt available
829
830 // Compute unit vectors along E, E x B and Bt.
831 double ue[3] = {ex / e, ey / e, ez / e};
832 double uexb[3] = {ey * bz - ez * by, ez * bx - ex * bz, ex * by - ey * bx};
833 const double exb =
834 sqrt(uexb[0] * uexb[0] + uexb[1] * uexb[1] + uexb[2] * uexb[2]);
835 if (exb > 0.) {
836 uexb[0] /= exb;
837 uexb[1] /= exb;
838 uexb[2] /= exb;
839 } else {
840 uexb[0] = ue[0];
841 uexb[1] = ue[1];
842 uexb[2] = ue[2];
843 }
844
845 double ubt[3] = {uexb[1] * ez - uexb[2] * ey, uexb[2] * ex - uexb[0] * ez,
846 uexb[0] * ey - uexb[1] * ex};
847 const double bt = sqrt(ubt[0] * ubt[0] + ubt[1] * ubt[1] + ubt[2] * ubt[2]);
848
849 if (bt > 0.) {
850 ubt[0] /= bt;
851 ubt[1] /= bt;
852 ubt[2] /= bt;
853 } else {
854 ubt[0] = ue[0];
855 ubt[1] = ue[1];
856 ubt[2] = ue[2];
857 }
858
859 // Calculate the velocities in all directions.
860 double ve = 0., vbt = 0., vexb = 0.;
861 if (m_map2d) {
863 m_nAngles, m_nBfields, m_nEfields, ebang, b, e0, ve,
865 std::cerr << m_className << "::HoleVelocity:\n";
866 std::cerr << " Interpolation of velocity along E failed.\n";
867 return false;
868 }
870 m_nAngles, m_nBfields, m_nEfields, ebang, b, e0, vexb,
872 std::cerr << m_className << "::HoleVelocity:\n";
873 std::cerr << " Interpolation of velocity along ExB failed.\n";
874 return false;
875 }
877 m_nAngles, m_nBfields, m_nEfields, ebang, b, e0, vbt,
879 std::cerr << m_className << "::HoleVelocity:\n";
880 std::cerr << " Interpolation of velocity along Bt failed.\n";
881 return false;
882 }
883 } else {
890 }
891 const double q = 1.;
892 if (ex * bx + ey * by + ez * bz > 0.) vbt = fabs(vbt);
893 else vbt = -fabs(vbt);
894 vx = q * (ve * ue[0] + q * q * vbt * ubt[0] + q * vexb * uexb[0]);
895 vy = q * (ve * ue[1] + q * q * vbt * ubt[1] + q * vexb * uexb[1]);
896 vz = q * (ve * ue[2] + q * q * vbt * ubt[2] + q * vexb * uexb[2]);
897
898 } else {
899 // Magnetic field, velocities along ExB, Bt not available
900
901 // Calculate the velocity along E.
902 double ve = 0.;
903 if (m_map2d) {
905 m_nAngles, m_nBfields, m_nEfields, ebang, b, e0, ve,
907 std::cerr << m_className << "::HoleVelocity:\n";
908 std::cerr << " Interpolation of velocity along E failed.\n";
909 return false;
910 }
911 } else {
914 }
915
916 const double q = 1.;
917 const double mu = q * ve / e;
918 const double eb = bx * ex + by * ey + bz * ez;
919 const double nom = 1. + pow(mu * b, 2);
920 vx = mu * (ex + mu * (ey * bz - ez * by) + mu * mu * bx * eb) / nom;
921 vy = mu * (ey + mu * (ez * bx - ex * bz) + mu * mu * by * eb) / nom;
922 vz = mu * (ez + mu * (ex * by - ey * bx) + mu * mu * bz * eb) / nom;
923 }
924
925 return true;
926}
927
928bool Medium::HoleDiffusion(const double ex, const double ey, const double ez,
929 const double bx, const double by, const double bz,
930 double& dl, double& dt) {
931
932 dl = dt = 0.;
933 // Compute the magnitude of the electric field.
934 const double e = sqrt(ex * ex + ey * ey + ez * ez);
935 const double e0 = ScaleElectricField(e);
936 if (e < Small || e0 < Small) return true;
937
938 if (m_map2d) {
939 // Compute the magnitude of the magnetic field.
940 const double b = sqrt(bx * bx + by * by + bz * bz);
941 // Compute the angle between B field and E field.
942 double ebang = 0.;
943 if (e * b > 0.) {
944 const double eb = fabs(ex * bx + ey * by + ez * bz);
945 if (eb > 0.2 * e * b) {
946 ebang = asin(std::min(
947 1., sqrt(pow(ex * by - ey * bx, 2) + pow(ex * bz - ez * bx, 2) +
948 pow(ez * by - ey * bz, 2)) /
949 (e * b)));
950 } else {
951 ebang = acos(std::min(1., eb / (e * b)));
952 }
953 } else {
954 ebang = bAngles[0];
955 }
956
957 // Interpolate.
958 if (m_hasHoleDiffLong) {
960 m_nBfields, m_nEfields, ebang, b, e0, dl,
962 dl = 0.;
963 }
964 }
965 if (m_hasHoleDiffTrans) {
967 m_nAngles, m_nBfields, m_nEfields, ebang, b, e0, dt,
969 dt = 0.;
970 }
971 }
972 } else {
973 if (m_hasHoleDiffLong) {
976 }
977 if (m_hasHoleDiffTrans) {
980 }
981 }
982
983 // If no data available, calculate
984 // the diffusion coefficients using the Einstein relation
985 if (!m_hasHoleDiffLong) {
986 dl = sqrt(2. * BoltzmannConstant * m_temperature / e);
987 }
988 if (!m_hasHoleDiffTrans) {
989 dt = sqrt(2. * BoltzmannConstant * m_temperature / e);
990 }
991
992 // Verify values and apply scaling.
993 if (dl < 0.) dl = 0.;
994 if (dt < 0.) dt = 0.;
995 dl = ScaleDiffusion(dl);
996 dt = ScaleDiffusion(dt);
997
998 return true;
999}
1000
1001bool Medium::HoleDiffusion(const double ex, const double ey, const double ez,
1002 const double bx, const double by, const double bz,
1003 double cov[3][3]) {
1004
1005 // Initialise the tensor.
1006 cov[0][0] = cov[0][1] = cov[0][2] = 0.;
1007 cov[1][0] = cov[1][1] = cov[1][2] = 0.;
1008 cov[2][0] = cov[2][1] = cov[2][2] = 0.;
1009
1010 if (!m_hasHoleDiffTens) return false;
1011
1012 // Compute the magnitude of the electric field.
1013 const double e = sqrt(ex * ex + ey * ey + ez * ez);
1014 const double e0 = ScaleElectricField(e);
1015 if (e < Small || e0 < Small) return true;
1016
1017 if (m_map2d) {
1018 // Compute the magnitude of the magnetic field.
1019 const double b = sqrt(bx * bx + by * by + bz * bz);
1020
1021 // Compute the angle between B field and E field.
1022 double ebang = 0.;
1023 if (e * b > 0.) {
1024 const double eb = fabs(ex * bx + ey * by + ez * bz);
1025 if (eb > 0.2 * e * b) {
1026 ebang = asin(std::min(
1027 1., sqrt(pow(ex * by - ey * bx, 2) + pow(ex * bz - ez * bx, 2) +
1028 pow(ez * by - ey * bz, 2)) /
1029 (e * b)));
1030 } else {
1031 ebang = acos(std::min(1., eb / (e * b)));
1032 }
1033 } else {
1034 ebang = bAngles[0];
1035 }
1036 // Interpolate.
1037 double diff = 0.;
1038 for (int l = 0; l < 6; ++l) {
1040 m_nAngles, m_nBfields, m_nEfields, ebang, b, e0, diff,
1041 m_intpDiffusion)) {
1042 diff = 0.;
1043 }
1044 // Apply scaling.
1045 diff = ScaleDiffusionTensor(diff);
1046 if (l < 3) {
1047 cov[l][l] = diff;
1048 } else if (l == 3) {
1049 cov[0][1] = cov[1][0] = diff;
1050 } else if (l == 4) {
1051 cov[0][2] = cov[2][0] = diff;
1052 } else if (l == 5) {
1053 cov[1][2] = cov[2][1] = diff;
1054 }
1055 }
1056 } else {
1057 // Interpolate.
1058 for (int l = 0; l < 6; ++l) {
1059 double diff =
1062 // Apply scaling.
1063 diff = ScaleDiffusionTensor(diff);
1064 if (l < 3) {
1065 cov[l][l] = diff;
1066 } else if (l == 3) {
1067 cov[0][1] = cov[1][0] = diff;
1068 } else if (l == 4) {
1069 cov[0][2] = cov[2][0] = diff;
1070 } else if (l == 5) {
1071 cov[1][2] = cov[2][1] = diff;
1072 }
1073 }
1074 }
1075
1076 return true;
1077}
1078
1079bool Medium::HoleTownsend(const double ex, const double ey, const double ez,
1080 const double bx, const double by, const double bz,
1081 double& alpha) {
1082
1083 alpha = 0.;
1084 if (!m_hasHoleTownsend) return false;
1085 // Compute the magnitude of the electric field.
1086 const double e = sqrt(ex * ex + ey * ey + ez * ez);
1087 const double e0 = ScaleElectricField(e);
1088 if (e < Small || e0 < Small) return true;
1089
1090 if (m_map2d) {
1091 // Compute the magnitude of the magnetic field.
1092 const double b = sqrt(bx * bx + by * by + bz * bz);
1093
1094 // Compute the angle between B field and E field.
1095 double ebang = 0.;
1096 if (e * b > 0.) {
1097 const double eb = fabs(ex * bx + ey * by + ez * bz);
1098 if (eb > 0.2 * e * b) {
1099 ebang = asin(std::min(
1100 1., sqrt(pow(ex * by - ey * bx, 2) + pow(ex * bz - ez * bx, 2) +
1101 pow(ez * by - ey * bz, 2)) /
1102 (e * b)));
1103 } else {
1104 ebang = acos(std::min(1., eb / (e * b)));
1105 }
1106 } else {
1107 ebang = bAngles[0];
1108 }
1109 // Interpolate.
1110 if (e0 < eFields[thrHoleTownsend]) {
1112 m_nBfields, m_nEfields, ebang, b, e0, alpha, 1)) {
1113 alpha = -30.;
1114 }
1115 } else {
1117 m_nBfields, m_nEfields, ebang, b, e0, alpha,
1118 m_intpTownsend)) {
1119 alpha = -30.;
1120 }
1121 }
1122 } else {
1123 // Interpolate.
1124 if (e0 < eFields[thrHoleTownsend]) {
1125 alpha = Interpolate1D(e0, tabHoleTownsend[0][0], eFields, 1,
1127 } else {
1130 }
1131 }
1132
1133 if (alpha < -20.) {
1134 alpha = 0.;
1135 } else {
1136 alpha = exp(alpha);
1137 }
1138
1139 // Apply scaling.
1140 alpha = ScaleTownsend(alpha);
1141 return true;
1142}
1143
1144bool Medium::HoleAttachment(const double ex, const double ey, const double ez,
1145 const double bx, const double by, const double bz,
1146 double& eta) {
1147
1148 eta = 0.;
1149 if (!m_hasHoleAttachment) return false;
1150 // Compute the magnitude of the electric field.
1151 const double e = sqrt(ex * ex + ey * ey + ez * ez);
1152 const double e0 = ScaleElectricField(e);
1153 if (e < Small || e0 < Small) return true;
1154
1155 if (m_map2d) {
1156 // Compute the magnitude of the magnetic field.
1157 const double b = sqrt(bx * bx + by * by + bz * bz);
1158
1159 // Compute the angle between B field and E field.
1160 double ebang = 0.;
1161 if (e * b > 0.) {
1162 const double eb = fabs(ex * bx + ey * by + ez * bz);
1163 if (eb > 0.2 * e * b) {
1164 ebang = asin(std::min(
1165 1., sqrt(pow(ex * by - ey * bx, 2) + pow(ex * bz - ez * bx, 2) +
1166 pow(ez * by - ey * bz, 2)) /
1167 (e * b)));
1168 } else {
1169 ebang = acos(std::min(1., eb / (e * b)));
1170 }
1171 } else {
1172 ebang = bAngles[0];
1173 }
1174 // Interpolate.
1175 if (e0 < eFields[thrHoleAttachment]) {
1177 m_nAngles, m_nBfields, m_nEfields, ebang, b, e0, eta,
1178 1)) {
1179 eta = -30.;
1180 }
1181 } else {
1183 m_nAngles, m_nBfields, m_nEfields, ebang, b, e0, eta,
1185 eta = -30.;
1186 }
1187 }
1188 } else {
1189 // Interpolate.
1190 if (e0 < eFields[thrHoleAttachment]) {
1191 eta = Interpolate1D(e0, tabHoleAttachment[0][0], eFields, 1,
1193 } else {
1194 eta = Interpolate1D(e0, tabHoleAttachment[0][0], eFields,
1197 }
1198 }
1199
1200 if (eta < -20.) {
1201 eta = 0.;
1202 } else {
1203 eta = exp(eta);
1204 }
1205
1206 // Apply scaling.
1207 eta = ScaleAttachment(eta);
1208 return true;
1209}
1210
1211bool Medium::IonVelocity(const double ex, const double ey, const double ez,
1212 const double bx, const double by, const double bz,
1213 double& vx, double& vy, double& vz) {
1214
1215 vx = vy = vz = 0.;
1216 if (!m_hasIonMobility) return false;
1217 // Compute the magnitude of the electric field.
1218 const double e = sqrt(ex * ex + ey * ey + ez * ez);
1219 const double e0 = ScaleElectricField(e);
1220 if (e < Small || e0 < Small) return true;
1221 // Compute the magnitude of the electric field.
1222 const double b = sqrt(bx * bx + by * by + bz * bz);
1223
1224 double mu = 0.;
1225 if (m_map2d) {
1226 // Compute the angle between B field and E field.
1227 double ebang = 0.;
1228 if (e * b > 0.) {
1229 const double eb = fabs(ex * bx + ey * by + ez * bz);
1230 if (eb > 0.2 * e * b) {
1231 ebang = asin(std::min(
1232 1., sqrt(pow(ex * by - ey * bx, 2) + pow(ex * bz - ez * bx, 2) +
1233 pow(ez * by - ey * bz, 2)) /
1234 (e * b)));
1235 } else {
1236 ebang = acos(std::min(1., eb / (e * b)));
1237 }
1238 } else {
1239 ebang = bAngles[0];
1240 }
1242 m_nBfields, m_nEfields, ebang, b, e0, mu,
1243 m_intpMobility)) {
1244 mu = 0.;
1245 }
1246 } else {
1249 }
1250
1251 const double q = 1.;
1252 mu *= q;
1253 if (b < Small) {
1254 vx = mu * ex;
1255 vy = mu * ey;
1256 vz = mu * ez;
1257 } else {
1258 const double eb = bx * ex + by * ey + bz * ez;
1259 const double nom = 1. + pow(mu * b, 2);
1260 vx = mu * (ex + mu * (ey * bz - ez * by) + mu * mu * bx * eb) / nom;
1261 vy = mu * (ey + mu * (ez * bx - ex * bz) + mu * mu * by * eb) / nom;
1262 vz = mu * (ez + mu * (ex * by - ey * bx) + mu * mu * bz * eb) / nom;
1263 }
1264
1265 return true;
1266}
1267
1268bool Medium::IonDiffusion(const double ex, const double ey, const double ez,
1269 const double bx, const double by, const double bz,
1270 double& dl, double& dt) {
1271
1272 dl = dt = 0.;
1273 // Compute the magnitude of the electric field.
1274 const double e = sqrt(ex * ex + ey * ey + ez * ez);
1275 const double e0 = ScaleElectricField(e);
1276 if (e < Small || e0 < Small) return true;
1277
1278 if (m_map2d) {
1279 // Compute the magnitude of the magnetic field.
1280 const double b = sqrt(bx * bx + by * by + bz * bz);
1281 // Compute the angle between B field and E field.
1282 double ebang = 0.;
1283 if (e * b > 0.) {
1284 const double eb = fabs(ex * bx + ey * by + ez * bz);
1285 if (eb > 0.2 * e * b) {
1286 ebang = asin(std::min(
1287 1., sqrt(pow(ex * by - ey * bx, 2) + pow(ex * bz - ez * bx, 2) +
1288 pow(ez * by - ey * bz, 2)) /
1289 (e * b)));
1290 } else {
1291 ebang = acos(std::min(1., eb / (e * b)));
1292 }
1293 } else {
1294 ebang = bAngles[0];
1295 }
1296
1297 // Interpolate.
1298 if (m_hasIonDiffLong) {
1300 m_nBfields, m_nEfields, ebang, b, e0, dl,
1301 m_intpDiffusion)) {
1302 dl = 0.;
1303 }
1304 }
1305 if (m_hasIonDiffTrans) {
1307 m_nBfields, m_nEfields, ebang, b, e0, dt,
1308 m_intpDiffusion)) {
1309 dt = 0.;
1310 }
1311 }
1312 } else {
1313 if (m_hasIonDiffLong) {
1316 }
1317 if (m_hasIonDiffTrans) {
1320 }
1321 }
1322
1323 // If no data available, calculate
1324 // the diffusion coefficients using the Einstein relation
1325 if (!m_hasIonDiffLong) {
1326 dl = sqrt(2. * BoltzmannConstant * m_temperature / e);
1327 }
1328 if (!m_hasIonDiffTrans) {
1329 dt = sqrt(2. * BoltzmannConstant * m_temperature / e);
1330 }
1331
1332 return true;
1333}
1334
1335bool Medium::IonDissociation(const double ex, const double ey, const double ez,
1336 const double bx, const double by, const double bz,
1337 double& diss) {
1338
1339 diss = 0.;
1340 if (!m_hasIonDissociation) return false;
1341 // Compute the magnitude of the electric field.
1342 const double e = sqrt(ex * ex + ey * ey + ez * ez);
1343 const double e0 = ScaleElectricField(e);
1344 if (e < Small || e0 < Small) return true;
1345
1346 if (m_map2d) {
1347 // Compute the magnitude of the magnetic field.
1348 const double b = sqrt(bx * bx + by * by + bz * bz);
1349
1350 // Compute the angle between B field and E field.
1351 double ebang = 0.;
1352 if (e * b > 0.) {
1353 const double eb = fabs(ex * bx + ey * by + ez * bz);
1354 if (eb > 0.2 * e * b) {
1355 ebang = asin(std::min(
1356 1., sqrt(pow(ex * by - ey * bx, 2) + pow(ex * bz - ez * bx, 2) +
1357 pow(ez * by - ey * bz, 2)) /
1358 (e * b)));
1359 } else {
1360 ebang = acos(std::min(1., eb / (e * b)));
1361 }
1362 } else {
1363 ebang = bAngles[0];
1364 }
1365 // Interpolate.
1366 if (e0 < eFields[thrIonDissociation]) {
1368 m_nAngles, m_nBfields, m_nEfields, ebang, b, e0, diss,
1369 1)) {
1370 diss = -30.;
1371 }
1372 } else {
1374 m_nAngles, m_nBfields, m_nEfields, ebang, b, e0, diss,
1376 diss = -30.;
1377 }
1378 }
1379 } else {
1380 // Interpolate.
1381 if (e0 < eFields[thrIonDissociation]) {
1382 diss = Interpolate1D(e0, tabIonDissociation[0][0], eFields, 1,
1384 } else {
1385 diss = Interpolate1D(e0, tabHoleTownsend[0][0], eFields,
1388 }
1389 }
1390
1391 if (diss < -20.) {
1392 diss = 0.;
1393 } else {
1394 diss = exp(diss);
1395 }
1396
1397 // Apply scaling.
1398 diss = ScaleDissociation(diss);
1399 return true;
1400}
1401
1402bool Medium::GetOpticalDataRange(double& emin, double& emax,
1403 const unsigned int& i) {
1404
1405 if (i >= m_nComponents) {
1406 std::cerr << m_className << "::GetOpticalDataRange:\n";
1407 std::cerr << " Component " << i << " does not exist.\n";
1408 return false;
1409 }
1410
1411 if (m_debug) {
1412 std::cerr << m_className << "::GetOpticalDataRange:\n";
1413 std::cerr << " Function is not implemented.\n";
1414 }
1415 emin = emax = 0.;
1416 return false;
1417}
1418
1419bool Medium::GetDielectricFunction(const double& e, double& eps1, double& eps2,
1420 const unsigned int& i) {
1421
1422 if (i >= m_nComponents) {
1423 std::cerr << m_className << "::GetDielectricFunction:\n";
1424 std::cerr << " Component " << i << " does not exist.\n";
1425 return false;
1426 }
1427
1428 if (e < 0.) {
1429 std::cerr << m_className << "::GetDielectricFunction:\n";
1430 std::cerr << " Energy must be > 0.\n";
1431 return false;
1432 }
1433
1434 if (m_debug) {
1435 std::cerr << m_className << "::GetDielectricFunction:\n";
1436 std::cerr << " Function is not implemented.\n";
1437 }
1438 eps1 = 1.;
1439 eps2 = 0.;
1440 return false;
1441}
1442
1443bool Medium::GetPhotoAbsorptionCrossSection(const double& e, double& sigma,
1444 const unsigned int& i) {
1445
1446 if (i >= m_nComponents) {
1447 std::cerr << m_className << "::GetPhotoAbsorptionCrossSection:\n";
1448 std::cerr << " Component " << i << " does not exist.\n";
1449 return false;
1450 }
1451
1452 if (e < 0.) {
1453 std::cerr << m_className << "::GetPhotoAbsorptionCrossSection:\n";
1454 std::cerr << " Energy must be > 0.\n";
1455 return false;
1456 }
1457
1458 if (m_debug) {
1459 std::cerr << m_className << "::GetPhotoAbsorptionCrossSection:\n";
1460 std::cerr << " Function is not implemented.\n";
1461 }
1462 sigma = 0.;
1463 return false;
1464}
1465
1466double Medium::GetPhotonCollisionRate(const double& e) {
1467
1468 double sigma = 0.;
1469 if (!GetPhotoAbsorptionCrossSection(e, sigma)) return 0.;
1470
1471 return sigma * m_density * SpeedOfLight;
1472}
1473
1474bool Medium::GetPhotonCollision(const double e, int& type, int& level,
1475 double& e1, double& ctheta, int& nsec,
1476 double& esec) {
1477
1478 type = level = -1;
1479 e1 = e;
1480 ctheta = 1.;
1481 nsec = 0;
1482 esec = 0.;
1483 return false;
1484}
1485
1487
1488 tabElectronVelocityE.clear();
1489 tabElectronVelocityB.clear();
1490 tabElectronVelocityExB.clear();
1491 m_hasElectronVelocityE = false;
1492 m_hasElectronVelocityB = false;
1494}
1495
1497
1498 tabElectronDiffLong.clear();
1499 tabElectronDiffTrans.clear();
1500 tabElectronDiffTens.clear();
1501 m_hasElectronDiffLong = false;
1502 m_hasElectronDiffTrans = false;
1503 m_hasElectronDiffTens = false;
1504}
1505
1507
1508 tabElectronTownsend.clear();
1509 m_hasElectronTownsend = false;
1510}
1511
1513
1514 tabElectronAttachment.clear();
1516}
1517
1519
1520 tabHoleVelocityE.clear();
1521 tabHoleVelocityB.clear();
1522 tabHoleVelocityExB.clear();
1523 m_hasHoleVelocityE = false;
1524 m_hasHoleVelocityB = false;
1525 m_hasHoleVelocityExB = false;
1526}
1527
1529
1530 tabHoleDiffLong.clear();
1531 tabHoleDiffTrans.clear();
1532 tabHoleDiffTens.clear();
1533 m_hasHoleDiffLong = false;
1534 m_hasHoleDiffTrans = false;
1535 m_hasHoleDiffTens = false;
1536}
1537
1539
1540 tabHoleTownsend.clear();
1541 m_hasHoleTownsend = false;
1542}
1543
1545
1546 tabHoleAttachment.clear();
1547 m_hasHoleAttachment = false;
1548}
1549
1551
1552 tabIonMobility.clear();
1553 m_hasIonMobility = false;
1554}
1555
1557
1558 tabIonDiffLong.clear();
1559 tabIonDiffTrans.clear();
1560 m_hasIonDiffLong = false;
1561 m_hasIonDiffTrans = false;
1562}
1563
1565
1566 tabIonDissociation.clear();
1567 m_hasIonDissociation = false;
1568}
1569
1570void Medium::SetFieldGrid(double emin, double emax, int ne, bool logE,
1571 double bmin, double bmax, int nb, double amin,
1572 double amax, int na) {
1573
1574 // Check if the requested E-field range makes sense.
1575 if (ne <= 0) {
1576 std::cerr << m_className << "::SetFieldGrid:\n";
1577 std::cerr << " Number of E-fields must be > 0.\n";
1578 return;
1579 }
1580
1581 if (emin < 0. || emax < 0.) {
1582 std::cerr << m_className << "::SetFieldGrid:\n";
1583 std::cerr << " Electric fields must be positive.\n";
1584 return;
1585 }
1586
1587 if (emax < emin) {
1588 std::cerr << m_className << "::SetFieldGrid:\n";
1589 std::cerr << " Swapping min./max. E-field.\n";
1590 const double etemp = emin;
1591 emin = emax;
1592 emax = etemp;
1593 }
1594
1595 double estep = 0.;
1596 if (logE) {
1597 // Logarithmic scale
1598 if (emin < Small) {
1599 std::cerr << m_className << "::SetFieldGrid:\n";
1600 std::cerr << " Min. E-field must be non-zero for log. scale.\n";
1601 return;
1602 }
1603 if (ne == 1) {
1604 std::cerr << m_className << "::SetFieldGrid:\n";
1605 std::cerr << " Number of E-fields must be > 1 for log. scale.\n";
1606 return;
1607 }
1608 estep = pow(emax / emin, 1. / (ne - 1.));
1609 } else {
1610 // Linear scale
1611 if (ne > 1) estep = (emax - emin) / (ne - 1.);
1612 }
1613
1614 // Check if the requested B-field range makes sense.
1615 if (nb <= 0) {
1616 std::cerr << m_className << "::SetFieldGrid:\n";
1617 std::cerr << " Number of B-fields must be > 0.\n";
1618 return;
1619 }
1620 if (bmax < 0. || bmin < 0.) {
1621 std::cerr << m_className << "::SetFieldGrid:\n";
1622 std::cerr << " Magnetic fields must be positive.\n";
1623 return;
1624 }
1625 if (bmax < bmin) {
1626 std::cerr << m_className << "::SetFieldGrid:\n";
1627 std::cerr << " Swapping min./max. B-field.\n";
1628 const double btemp = bmin;
1629 bmin = bmax;
1630 bmax = btemp;
1631 }
1632
1633 double bstep = 0.;
1634 if (nb > 1) bstep = (bmax - bmin) / (nb - 1.);
1635
1636 // Check if the requested angular range makes sense.
1637 if (na <= 0) {
1638 std::cerr << m_className << "::SetFieldGrid:\n";
1639 std::cerr << " Number of angles must be > 0.\n";
1640 return;
1641 }
1642 if (amax < 0. || amin < 0.) {
1643 std::cerr << m_className << "::SetFieldGrid:\n";
1644 std::cerr << " Angles must be positive.\n";
1645 return;
1646 }
1647 if (amax < amin) {
1648 std::cerr << m_className << "::SetFieldGrid:\n";
1649 std::cerr << " Swapping min./max. angle.\n";
1650 const double atemp = amin;
1651 amin = amax;
1652 amax = atemp;
1653 }
1654 double astep = 0.;
1655 if (na > 1) astep = (amax - amin) / (na - 1.);
1656
1657 // Setup the field grids.
1658 std::vector<double> eFieldsNew;
1659 std::vector<double> bFieldsNew;
1660 std::vector<double> bAnglesNew;
1661 eFieldsNew.resize(ne);
1662 bFieldsNew.resize(nb);
1663 bAnglesNew.resize(na);
1664
1665 for (int i = 0; i < ne; ++i) {
1666 if (logE) {
1667 eFieldsNew[i] = emin * pow(estep, i);
1668 } else {
1669 eFieldsNew[i] = emin + i * estep;
1670 }
1671 }
1672 for (int i = 0; i < nb; ++i) {
1673 bFieldsNew[i] = bmin + i * bstep;
1674 }
1675 if (na == 1 && nb == 1 && fabs(bmin) < 1.e-4) {
1676 bAnglesNew[0] = HalfPi;
1677 } else {
1678 for (int i = 0; i < na; ++i) {
1679 bAnglesNew[i] = amin + i * astep;
1680 }
1681 }
1682 SetFieldGrid(eFieldsNew, bFieldsNew, bAnglesNew);
1683}
1684
1685void Medium::SetFieldGrid(const std::vector<double>& efields,
1686 const std::vector<double>& bfields,
1687 const std::vector<double>& angles) {
1688
1689 if (efields.empty()) {
1690 std::cerr << m_className << "::SetFieldGrid:\n";
1691 std::cerr << " Number of E-fields must be > 0.\n";
1692 return;
1693 }
1694 if (bfields.empty()) {
1695 std::cerr << m_className << "::SetFieldGrid:\n";
1696 std::cerr << " Number of B-fields must be > 0.\n";
1697 return;
1698 }
1699 if (angles.empty()) {
1700 std::cerr << m_className << "::SetFieldGrid:\n";
1701 std::cerr << " Number of angles must be > 0.\n";
1702 return;
1703 }
1704
1705 // Make sure the values are not negative.
1706 if (efields[0] < 0.) {
1707 std::cerr << m_className << "::SetFieldGrid:\n";
1708 std::cerr << " E-fields must be >= 0.\n";
1709 }
1710 if (bfields[0] < 0.) {
1711 std::cerr << m_className << "::SetFieldGrid:\n";
1712 std::cerr << " B-fields must be >= 0.\n";
1713 }
1714 if (angles[0] < 0.) {
1715 std::cerr << m_className << "::SetFieldGrid:\n";
1716 std::cerr << " Angles must be >= 0.\n";
1717 }
1718
1719 const unsigned int nEfieldsNew = efields.size();
1720 const unsigned int nBfieldsNew = bfields.size();
1721 const unsigned int nAnglesNew = angles.size();
1722 // Make sure the values are in strictly monotonic, ascending order.
1723 if (nEfieldsNew > 1) {
1724 for (unsigned int i = 1; i < nEfieldsNew; ++i) {
1725 if (efields[i] <= efields[i - 1]) {
1726 std::cerr << m_className << "::SetFieldGrid:\n";
1727 std::cerr << " E-fields are not in ascending order.\n";
1728 return;
1729 }
1730 }
1731 }
1732 if (nBfieldsNew > 1) {
1733 for (unsigned int i = 1; i < nBfieldsNew; ++i) {
1734 if (bfields[i] <= bfields[i - 1]) {
1735 std::cerr << m_className << "::SetFieldGrid:\n";
1736 std::cerr << " B-fields are not in ascending order.\n";
1737 return;
1738 }
1739 }
1740 }
1741 if (nAnglesNew > 1) {
1742 for (unsigned int i = 1; i < nAnglesNew; ++i) {
1743 if (angles[i] <= angles[i - 1]) {
1744 std::cerr << m_className << "::SetFieldGrid:\n";
1745 std::cerr << " Angles are not in ascending order.\n";
1746 return;
1747 }
1748 }
1749 }
1750
1751 if (m_debug) {
1752 std::cout << m_className << "::SetFieldGrid:\n";
1753 std::cout << " E-fields:\n";
1754 for (unsigned int i = 0; i < nEfieldsNew; ++i) {
1755 std::cout << " " << efields[i] << "\n";
1756 }
1757 std::cout << " B-fields:\n";
1758 for (unsigned int i = 0; i < nBfieldsNew; ++i) {
1759 std::cout << " " << bfields[i] << "\n";
1760 }
1761 std::cout << " Angles:\n";
1762 for (unsigned int i = 0; i < nAnglesNew; ++i) {
1763 std::cout << " " << angles[i] << "\n";
1764 }
1765 }
1766
1767 // Clone the existing tables.
1768 // Electrons
1770 CloneTable(tabElectronVelocityE, efields, bfields, angles, m_intpVelocity,
1772 "electron velocity along E");
1773 }
1775 CloneTable(tabElectronVelocityB, efields, bfields, angles, m_intpVelocity,
1777 "electron velocity along Bt");
1778 }
1780 CloneTable(tabElectronVelocityExB, efields, bfields, angles, m_intpVelocity,
1782 "electron velocity along ExB");
1783 }
1785 CloneTable(tabElectronDiffLong, efields, bfields, angles, m_intpDiffusion,
1787 "electron longitudinal diffusion");
1788 }
1790 CloneTable(tabElectronDiffTrans, efields, bfields, angles, m_intpDiffusion,
1792 "electron transverse diffusion");
1793 }
1795 CloneTable(tabElectronTownsend, efields, bfields, angles, m_intpTownsend,
1797 "electron Townsend coefficient");
1798 }
1800 CloneTable(tabElectronAttachment, efields, bfields, angles, m_intpAttachment,
1802 "electron attachment coefficient");
1803 }
1805 CloneTensor(tabElectronDiffTens, 6, efields, bfields, angles, m_intpDiffusion,
1807 "electron diffusion tensor");
1808 }
1809
1810 // Holes
1811 if (m_hasHoleVelocityE) {
1812 CloneTable(tabHoleVelocityE, efields, bfields, angles, m_intpVelocity,
1814 "hole velocity along E");
1815 }
1816 if (m_hasHoleVelocityB) {
1817 CloneTable(tabHoleVelocityB, efields, bfields, angles, m_intpVelocity,
1819 "hole velocity along Bt");
1820 }
1822 CloneTable(tabHoleVelocityExB, efields, bfields, angles, m_intpVelocity,
1824 "hole velocity along ExB");
1825 }
1826 if (m_hasHoleDiffLong) {
1827 CloneTable(tabHoleDiffLong, efields, bfields, angles, m_intpDiffusion,
1829 "hole longitudinal diffusion");
1830 }
1831 if (m_hasHoleDiffTrans) {
1832 CloneTable(tabHoleDiffTrans, efields, bfields, angles, m_intpDiffusion,
1834 "hole transverse diffusion");
1835 }
1836 if (m_hasHoleTownsend) {
1837 CloneTable(tabHoleTownsend, efields, bfields, angles, m_intpTownsend,
1839 "hole Townsend coefficient");
1840 }
1841 if (m_hasHoleAttachment) {
1842 CloneTable(tabHoleAttachment, efields, bfields, angles, m_intpAttachment,
1844 "hole attachment coefficient");
1845 }
1846 if (m_hasHoleDiffTens) {
1847 CloneTensor(tabHoleDiffTens, 6, efields, bfields, angles, m_intpDiffusion,
1849 "hole diffusion tensor");
1850 }
1851
1852 // Ions
1853 if (m_hasIonMobility) {
1854 CloneTable(tabIonMobility, efields, bfields, angles, m_intpMobility,
1856 "ion mobility");
1857 }
1858 if (m_hasIonDiffLong) {
1859 CloneTable(tabIonDiffLong, efields, bfields, angles, m_intpDiffusion,
1861 "ion longitudinal diffusion");
1862 }
1863 if (m_hasIonDiffTrans) {
1864 CloneTable(tabIonDiffTrans, efields, bfields, angles, m_intpDiffusion,
1866 "ion transverse diffusion");
1867 }
1869 CloneTable(tabIonDissociation, efields, bfields, angles, m_intpDissociation,
1871 "ion dissociation");
1872 }
1873
1874 m_nEfields = nEfieldsNew;
1875 m_nBfields = nBfieldsNew;
1876 m_nAngles = nAnglesNew;
1877 if (m_nBfields > 1 || m_nAngles > 1) m_map2d = true;
1878 eFields.resize(m_nEfields);
1879 bFields.resize(m_nBfields);
1880 bAngles.resize(m_nAngles);
1881 eFields = efields;
1882 bFields = bfields;
1883 bAngles = angles;
1884}
1885
1886void Medium::GetFieldGrid(std::vector<double>& efields,
1887 std::vector<double>& bfields,
1888 std::vector<double>& angles) {
1889
1890 efields = eFields;
1891 bfields = bFields;
1892 angles = bAngles;
1893}
1894
1895bool Medium::GetElectronVelocityE(const unsigned int& ie,
1896 const unsigned int& ib,
1897 const unsigned int& ia, double& v) {
1898
1899 if (ie >= m_nEfields || ib >= m_nBfields || ia >= m_nAngles) {
1900 std::cerr << m_className << "::GetElectronVelocityE:\n";
1901 std::cerr << " Index (" << ie << ", " << ib << ", " << ia
1902 << ") out of range.\n";
1903 v = 0.;
1904 return false;
1905 }
1907 if (m_debug) {
1908 std::cerr << m_className << "::GetElectronVelocityE:\n";
1909 std::cerr << " Data not available.\n";
1910 }
1911 v = 0.;
1912 return false;
1913 }
1914
1915 v = tabElectronVelocityE[ia][ib][ie];
1916 return true;
1917}
1918
1919bool Medium::GetElectronVelocityExB(const unsigned int& ie,
1920 const unsigned int& ib,
1921 const unsigned int& ia, double& v) {
1922
1923 if (ie >= m_nEfields || ib >= m_nBfields || ia >= m_nAngles) {
1924 std::cerr << m_className << "::GetElectronVelocityExB:\n";
1925 std::cerr << " Index (" << ie << ", " << ib << ", " << ia
1926 << ") out of range.\n";
1927 v = 0.;
1928 return false;
1929 }
1931 if (m_debug) {
1932 std::cerr << m_className << "::GetElectronVelocityExB:\n";
1933 std::cerr << " Data not available.\n";
1934 }
1935 v = 0.;
1936 return false;
1937 }
1938
1939 v = tabElectronVelocityExB[ia][ib][ie];
1940 return true;
1941}
1942
1943bool Medium::GetElectronVelocityB(const unsigned int& ie,
1944 const unsigned int& ib,
1945 const unsigned int& ia, double& v) {
1946
1947 if (ie >= m_nEfields || ib >= m_nBfields || ia >= m_nAngles) {
1948 std::cerr << m_className << "::GetElectronVelocityB:\n";
1949 std::cerr << " Index (" << ie << ", " << ib << ", " << ia
1950 << ") out of range.\n";
1951 v = 0.;
1952 return false;
1953 }
1955 if (m_debug) {
1956 std::cerr << m_className << "::GetElectronVelocityB:\n";
1957 std::cerr << " Data not available.\n";
1958 }
1959 v = 0.;
1960 return false;
1961 }
1962
1963 v = tabElectronVelocityB[ia][ib][ie];
1964 return true;
1965}
1966
1967bool Medium::GetElectronLongitudinalDiffusion(const unsigned int& ie,
1968 const unsigned int& ib,
1969 const unsigned int& ia,
1970 double& dl) {
1971
1972 if (ie >= m_nEfields || ib >= m_nBfields || ia >= m_nAngles) {
1973 std::cerr << m_className << "::GetElectronLongitudinalDiffusion:\n";
1974 std::cerr << " Index (" << ie << ", " << ib << ", " << ia
1975 << ") out of range.\n";
1976 dl = 0.;
1977 return false;
1978 }
1979 if (!m_hasElectronDiffLong) {
1980 if (m_debug) {
1981 std::cerr << m_className << "::GetElectronLongitudinalDiffusion:\n";
1982 std::cerr << " Data not available.\n";
1983 }
1984 dl = 0.;
1985 return false;
1986 }
1987
1988 dl = tabElectronDiffLong[ia][ib][ie];
1989 return true;
1990}
1991
1992bool Medium::GetElectronTransverseDiffusion(const unsigned int& ie,
1993 const unsigned int& ib,
1994 const unsigned int& ia,
1995 double& dt) {
1996
1997 if (ie >= m_nEfields || ib >= m_nBfields || ia >= m_nAngles) {
1998 std::cerr << m_className << "::GetElectronTransverseDiffusion:\n";
1999 std::cerr << " Index (" << ie << ", " << ib << ", " << ia
2000 << ") out of range.\n";
2001 dt = 0.;
2002 return false;
2003 }
2005 if (m_debug) {
2006 std::cerr << m_className << "::GetElectronTransverseDiffusion:\n";
2007 std::cerr << " Data not available.\n";
2008 }
2009 dt = 0.;
2010 return false;
2011 }
2012
2013 dt = tabElectronDiffTrans[ia][ib][ie];
2014 return true;
2015}
2016
2017bool Medium::GetElectronTownsend(const unsigned int& ie,
2018 const unsigned int& ib,
2019 const unsigned int& ia, double& alpha) {
2020
2021 if (ie >= m_nEfields || ib >= m_nBfields || ia >= m_nAngles) {
2022 std::cerr << m_className << "::GetElectronTownsend:\n";
2023 std::cerr << " Index (" << ie << ", " << ib << ", " << ia
2024 << ") out of range.\n";
2025 alpha = 0.;
2026 return false;
2027 }
2028 if (!m_hasElectronTownsend) {
2029 if (m_debug) {
2030 std::cerr << m_className << "::GetElectronTownsend:\n";
2031 std::cerr << " Data not available.\n";
2032 }
2033 alpha = 0.;
2034 return false;
2035 }
2036
2037 alpha = tabElectronTownsend[ia][ib][ie];
2038 return true;
2039}
2040
2041bool Medium::GetElectronAttachment(const unsigned int& ie,
2042 const unsigned int& ib,
2043 const unsigned int& ia, double& eta) {
2044
2045 if (ie >= m_nEfields || ib >= m_nBfields || ia >= m_nAngles) {
2046 std::cerr << m_className << "::GetElectronAttachment:\n";
2047 std::cerr << " Index (" << ie << ", " << ib << ", " << ia
2048 << ") out of range.\n";
2049 eta = 0.;
2050 return false;
2051 }
2053 if (m_debug) {
2054 std::cerr << m_className << "::GetElectronAttachment:\n";
2055 std::cerr << " Data not available.\n";
2056 }
2057 eta = 0.;
2058 return false;
2059 }
2060
2061 eta = tabElectronAttachment[ia][ib][ie];
2062 return true;
2063}
2064
2065bool Medium::GetHoleVelocityE(const unsigned int& ie,
2066 const unsigned int& ib,
2067 const unsigned int& ia, double& v) {
2068
2069 if (ie >= m_nEfields || ib >= m_nBfields || ia >= m_nAngles) {
2070 std::cerr << m_className << "::GetHoleVelocityE:\n";
2071 std::cerr << " Index (" << ie << ", " << ib << ", " << ia
2072 << ") out of range.\n";
2073 v = 0.;
2074 return false;
2075 }
2076 if (!m_hasHoleVelocityE) {
2077 if (m_debug) {
2078 std::cerr << m_className << "::GetHoleVelocityE:\n";
2079 std::cerr << " Data not available.\n";
2080 }
2081 v = 0.;
2082 return false;
2083 }
2084
2085 v = tabHoleVelocityE[ia][ib][ie];
2086 return true;
2087}
2088
2089bool Medium::GetHoleVelocityExB(const unsigned int& ie,
2090 const unsigned int& ib,
2091 const unsigned int& ia, double& v) {
2092
2093 if (ie >= m_nEfields || ib >= m_nBfields || ia >= m_nAngles) {
2094 std::cerr << m_className << "::GetHoleVelocityExB:\n";
2095 std::cerr << " Index (" << ie << ", " << ib << ", " << ia
2096 << ") out of range.\n";
2097 v = 0.;
2098 return false;
2099 }
2100 if (!m_hasHoleVelocityExB) {
2101 if (m_debug) {
2102 std::cerr << m_className << "::GetHoleVelocityExB:\n";
2103 std::cerr << " Data not available.\n";
2104 }
2105 v = 0.;
2106 return false;
2107 }
2108
2109 v = tabHoleVelocityExB[ia][ib][ie];
2110 return true;
2111}
2112
2113bool Medium::GetHoleVelocityB(const unsigned int& ie,
2114 const unsigned int& ib,
2115 const unsigned int& ia, double& v) {
2116
2117 if (ie >= m_nEfields || ib >= m_nBfields || ia >= m_nAngles) {
2118 std::cerr << m_className << "::GetHoleVelocityB:\n";
2119 std::cerr << " Index (" << ie << ", " << ib << ", " << ia
2120 << ") out of range.\n";
2121 v = 0.;
2122 return false;
2123 }
2124 if (!m_hasHoleVelocityB) {
2125 if (m_debug) {
2126 std::cerr << m_className << "::GetHoleVelocityB:\n";
2127 std::cerr << " Data not available.\n";
2128 }
2129 v = 0.;
2130 return false;
2131 }
2132
2133 v = tabHoleVelocityB[ia][ib][ie];
2134 return true;
2135}
2136
2137bool Medium::GetHoleLongitudinalDiffusion(const unsigned int& ie,
2138 const unsigned int& ib,
2139 const unsigned int& ia, double& dl) {
2140
2141 if (ie >= m_nEfields || ib >= m_nBfields || ia >= m_nAngles) {
2142 std::cerr << m_className << "::GetHoleLongitudinalDiffusion:\n";
2143 std::cerr << " Index (" << ie << ", " << ib << ", " << ia
2144 << ") out of range.\n";
2145 dl = 0.;
2146 return false;
2147 }
2148 if (!m_hasHoleDiffLong) {
2149 if (m_debug) {
2150 std::cerr << m_className << "::GetHoleLongitudinalDiffusion:\n";
2151 std::cerr << " Data not available.\n";
2152 }
2153 dl = 0.;
2154 return false;
2155 }
2156
2157 dl = tabHoleDiffLong[ia][ib][ie];
2158 return true;
2159}
2160
2161bool Medium::GetHoleTransverseDiffusion(const unsigned int& ie,
2162 const unsigned int& ib,
2163 const unsigned int& ia, double& dt) {
2164
2165 if (ie >= m_nEfields || ib >= m_nBfields || ia >= m_nAngles) {
2166 std::cerr << m_className << "::GetHoleTransverseDiffusion:\n";
2167 std::cerr << " Index (" << ie << ", " << ib << ", " << ia
2168 << ") out of range.\n";
2169 dt = 0.;
2170 return false;
2171 }
2172 if (!m_hasHoleDiffTrans) {
2173 if (m_debug) {
2174 std::cerr << m_className << "::GetHoleTransverseDiffusion:\n";
2175 std::cerr << " Data not available.\n";
2176 }
2177 dt = 0.;
2178 return false;
2179 }
2180
2181 dt = tabHoleDiffTrans[ia][ib][ie];
2182 return true;
2183}
2184
2185bool Medium::GetHoleTownsend(const unsigned int& ie,
2186 const unsigned int& ib,
2187 const unsigned int& ia, double& alpha) {
2188
2189 if (ie >= m_nEfields || ib >= m_nBfields || ia >= m_nAngles) {
2190 std::cerr << m_className << "::GetHoleTownsend:\n";
2191 std::cerr << " Index (" << ie << ", " << ib << ", " << ia
2192 << ") out of range.\n";
2193 alpha = 0.;
2194 return false;
2195 }
2196 if (!m_hasHoleTownsend) {
2197 if (m_debug) {
2198 std::cerr << m_className << "::GetHoleTownsend:\n";
2199 std::cerr << " Data not available.\n";
2200 }
2201 alpha = 0.;
2202 return false;
2203 }
2204
2205 alpha = tabHoleTownsend[ia][ib][ie];
2206 return true;
2207}
2208
2209bool Medium::GetHoleAttachment(const unsigned int& ie,
2210 const unsigned int& ib,
2211 const unsigned int& ia, double& eta) {
2212
2213 if (ie >= m_nEfields || ib >= m_nBfields || ia >= m_nAngles) {
2214 std::cerr << m_className << "::GetHoleAttachment:\n";
2215 std::cerr << " Index (" << ie << ", " << ib << ", " << ia
2216 << ") out of range.\n";
2217 eta = 0.;
2218 return false;
2219 }
2220 if (!m_hasHoleAttachment) {
2221 if (m_debug) {
2222 std::cerr << m_className << "::GetHoleAttachment:\n";
2223 std::cerr << " Data not available.\n";
2224 }
2225 eta = 0.;
2226 return false;
2227 }
2228
2229 eta = tabHoleAttachment[ia][ib][ie];
2230 return true;
2231}
2232
2233bool Medium::GetIonMobility(const unsigned int& ie, const unsigned int& ib,
2234 const unsigned int& ia, double& mu) {
2235
2236 if (ie >= m_nEfields || ib >= m_nBfields || ia >= m_nAngles) {
2237 std::cerr << m_className << "::GetIonMobility:\n";
2238 std::cerr << " Index (" << ie << ", " << ib << ", " << ia
2239 << ") out of range.\n";
2240 mu = 0.;
2241 return false;
2242 }
2243 if (!m_hasIonMobility) {
2244 if (m_debug) {
2245 std::cerr << m_className << "::GetIonMobility:\n";
2246 std::cerr << " Data not available.\n";
2247 }
2248 mu = 0.;
2249 return false;
2250 }
2251
2252 mu = tabIonMobility[ia][ib][ie];
2253 return true;
2254}
2255
2256bool Medium::GetIonLongitudinalDiffusion(const unsigned int& ie,
2257 const unsigned int& ib,
2258 const unsigned int& ia, double& dl) {
2259
2260 if (ie >= m_nEfields || ib >= m_nBfields || ia >= m_nAngles) {
2261 std::cerr << m_className << "::GetIonLongitudinalDiffusion:\n";
2262 std::cerr << " Index (" << ie << ", " << ib << ", " << ia
2263 << ") out of range.\n";
2264 dl = 0.;
2265 return false;
2266 }
2267 if (!m_hasIonDiffLong) {
2268 if (m_debug) {
2269 std::cerr << m_className << "::GetIonLongitudinalDiffusion:\n";
2270 std::cerr << " Data not available.\n";
2271 }
2272 dl = 0.;
2273 return false;
2274 }
2275
2276 dl = tabIonDiffLong[ia][ib][ie];
2277 return true;
2278}
2279
2280bool Medium::GetIonTransverseDiffusion(const unsigned int& ie,
2281 const unsigned int& ib,
2282 const unsigned int& ia, double& dt) {
2283
2284 if (ie >= m_nEfields || ib >= m_nBfields || ia >= m_nAngles) {
2285 std::cerr << m_className << "::GetIonTransverseDiffusion:\n";
2286 std::cerr << " Index (" << ie << ", " << ib << ", " << ia
2287 << ") out of range.\n";
2288 dt = 0.;
2289 return false;
2290 }
2291 if (!m_hasIonDiffTrans) {
2292 if (m_debug) {
2293 std::cerr << m_className << "::GetIonTransverseDiffusion:\n";
2294 std::cerr << " Data not available.\n";
2295 }
2296 dt = 0.;
2297 return false;
2298 }
2299
2300 dt = tabIonDiffTrans[ia][ib][ie];
2301 return true;
2302}
2303
2304bool Medium::GetIonDissociation(const unsigned int& ie,
2305 const unsigned int& ib,
2306 const unsigned int& ia, double& diss) {
2307
2308 if (ie >= m_nEfields || ib >= m_nBfields || ia >= m_nAngles) {
2309 std::cerr << m_className << "::GetIonDissociation:\n";
2310 std::cerr << " Index (" << ie << ", " << ib << ", " << ia
2311 << ") out of range.\n";
2312 diss = 0.;
2313 return false;
2314 }
2315 if (!m_hasIonDissociation) {
2316 if (m_debug) {
2317 std::cerr << m_className << "::GetIonDissociation:\n";
2318 std::cerr << " Data not available.\n";
2319 }
2320 diss = 0.;
2321 return false;
2322 }
2323
2324 diss = tabIonDissociation[ia][ib][ie];
2325 return true;
2326}
2327
2328void Medium::CloneTable(std::vector<std::vector<std::vector<double> > >& tab,
2329 const std::vector<double>& efields,
2330 const std::vector<double>& bfields,
2331 const std::vector<double>& angles,
2332 const unsigned int& intp,
2333 const unsigned int& extrLow,
2334 const unsigned int& extrHigh,
2335 const double init, const std::string label) {
2336
2337 if (m_debug) {
2338 std::cout << m_className << "::CloneTable:\n";
2339 std::cout << " Copying values of " << label << " to new grid.\n";
2340 }
2341
2342 // Get the dimensions of the new grid.
2343 const int nEfieldsNew = efields.size();
2344 const int nBfieldsNew = bfields.size();
2345 const int nAnglesNew = angles.size();
2346
2347 // Create a temporary table to store the values at the new grid points.
2348 std::vector<std::vector<std::vector<double> > > tabClone;
2349 tabClone.clear();
2350 InitParamArrays(nEfieldsNew, nBfieldsNew, nAnglesNew, tabClone, init);
2351
2352 // Fill the temporary table.
2353 for (int i = 0; i < nEfieldsNew; ++i) {
2354 for (int j = 0; j < nBfieldsNew; ++j) {
2355 for (int k = 0; k < nAnglesNew; ++k) {
2356 double val = 0.;
2357 if (m_map2d) {
2359 m_nBfields, m_nEfields, angles[k], bfields[j],
2360 efields[i], val, intp)) {
2361 std::cerr << m_className << "::SetFieldGrid:\n";
2362 std::cerr << " Interpolation of " << label << " failed.\n";
2363 std::cerr << " Cannot copy value to new grid at: \n";
2364 std::cerr << " E = " << efields[i] << "\n";
2365 std::cerr << " B = " << bfields[j] << "\n";
2366 std::cerr << " angle: " << angles[k] << "\n";
2367 } else {
2368 tabClone[k][j][i] = val;
2369 }
2370 } else {
2371 val = Interpolate1D(efields[i], tab[0][0], eFields, intp, extrLow,
2372 extrHigh);
2373 tabClone[k][j][i] = val;
2374 }
2375 }
2376 }
2377 }
2378 // Re-dimension the original table.
2379 InitParamArrays(nEfieldsNew, nBfieldsNew, nAnglesNew, tab, init);
2380 // Copy the values to the original table.
2381 for (int i = 0; i < nEfieldsNew; ++i) {
2382 for (int j = 0; j < nBfieldsNew; ++j) {
2383 for (int k = 0; k < nAnglesNew; ++k) {
2384 tab[k][j][i] = tabClone[k][j][i];
2385 }
2386 }
2387 }
2388 tabClone.clear();
2389}
2390
2392 std::vector<std::vector<std::vector<std::vector<double> > > >& tab,
2393 const unsigned int& n,
2394 const std::vector<double>& efields, const std::vector<double>& bfields,
2395 const std::vector<double>& angles,
2396 const unsigned int& intp,
2397 const unsigned int& extrLow, const unsigned int& extrHigh,
2398 const double& init,
2399 const std::string& label) {
2400
2401 // Get the dimensions of the new grid.
2402 const unsigned int nEfieldsNew = efields.size();
2403 const unsigned int nBfieldsNew = bfields.size();
2404 const unsigned int nAnglesNew = angles.size();
2405
2406 // Create a temporary table to store the values at the new grid points.
2407 std::vector<std::vector<std::vector<std::vector<double> > > > tabClone;
2408 tabClone.clear();
2409 InitParamTensor(nEfieldsNew, nBfieldsNew, nAnglesNew, n, tabClone, init);
2410
2411 // Fill the temporary table.
2412 for (unsigned int l = 0; l < n; ++l) {
2413 for (unsigned int i = 0; i < nEfieldsNew; ++i) {
2414 for (unsigned int j = 0; j < nBfieldsNew; ++j) {
2415 for (unsigned int k = 0; k < nAnglesNew; ++k) {
2416 double val = 0.;
2417 if (m_map2d) {
2419 m_nBfields, m_nEfields, angles[k], bfields[j],
2420 efields[i], val, intp)) {
2421 std::cerr << m_className << "::SetFieldGrid:\n";
2422 std::cerr << " Interpolation of " << label << " failed.\n";
2423 std::cerr << " Cannot copy value to new grid at: \n";
2424 std::cerr << " Index: " << l << "\n";
2425 std::cerr << " E = " << efields[i] << "\n";
2426 std::cerr << " B = " << bfields[j] << "\n";
2427 std::cerr << " angle: " << angles[k] << "\n";
2428 } else {
2429 tabClone[l][k][j][i] = val;
2430 }
2431 } else {
2432 val = Interpolate1D(efields[i], tab[l][0][0], eFields, intp,
2433 extrLow, extrHigh);
2434 tabClone[l][k][j][i] = val;
2435 }
2436 }
2437 }
2438 }
2439 }
2440 // Re-dimension the original table.
2441 InitParamTensor(nEfieldsNew, nBfieldsNew, nAnglesNew, n, tab, 0.);
2442 // Copy the values to the original table.
2443 for (unsigned int l = 0; l < n; ++l) {
2444 for (unsigned int i = 0; i < nEfieldsNew; ++i) {
2445 for (unsigned int j = 0; j < nBfieldsNew; ++j) {
2446 for (unsigned int k = 0; k < nAnglesNew; ++k) {
2447 tab[l][k][j][i] = tabClone[l][k][j][i];
2448 }
2449 }
2450 }
2451 }
2452}
2453
2454bool Medium::SetIonMobility(const unsigned int& ie, const unsigned int& ib,
2455 const unsigned int& ia, const double& mu) {
2456
2457 // Check the index.
2458 if (ie >= m_nEfields || ib >= m_nBfields || ia >= m_nAngles) {
2459 std::cerr << m_className << "::SetIonMobility:\n";
2460 std::cerr << " Index (" << ie << ", " << ib << ", " << ia
2461 << ") out of range.\n";
2462 return false;
2463 }
2464
2465 if (!m_hasIonMobility) {
2466 std::cerr << m_className << "::SetIonMobility:\n";
2467 std::cerr << " Ion mobility table not initialised.\n";
2468 return false;
2469 }
2470
2471 if (mu == 0.) {
2472 std::cerr << m_className << "::SetIonMobility:\n";
2473 std::cerr << " Zero value not permitted.\n";
2474 return false;
2475 }
2476
2477 tabIonMobility[ia][ib][ie] = mu;
2478 if (m_debug) {
2479 std::cout << m_className << "::SetIonMobility:\n";
2480 std::cout << " Ion mobility at E = " << eFields[ie]
2481 << " V/cm, B = " << bFields[ib] << " T, angle " << bAngles[ia]
2482 << " set to " << mu << " cm2/(V ns).\n";
2483 }
2484 return true;
2485}
2486
2487bool Medium::SetIonMobility(const std::vector<double>& efields,
2488 const std::vector<double>& mobilities) {
2489
2490 const int ne = efields.size();
2491 const int nm = mobilities.size();
2492 if (ne != nm) {
2493 std::cerr << m_className << "::SetIonMobility:\n";
2494 std::cerr << " E-field and mobility arrays have different sizes.\n";
2495 return false;
2496 }
2497
2500 for (unsigned int i = 0; i < m_nEfields; ++i) {
2501 const double e = eFields[i];
2502 const double mu = Interpolate1D(e, mobilities, efields, m_intpMobility,
2504 tabIonMobility[0][0][i] = mu;
2505 std::cout << "E = " << e << ", mu = " << mu << "\n";
2506 }
2507
2508 if (m_map2d) {
2509 for (unsigned int i = 0; i < m_nAngles; ++i) {
2510 for (unsigned int j = 0; j< m_nBfields; ++j) {
2511 for (unsigned int k = 0; k < m_nEfields; ++k) {
2512 tabIonMobility[i][j][k] = tabIonMobility[0][0][k];
2513 }
2514 }
2515 }
2516 }
2517 m_hasIonMobility = true;
2518
2519 return true;
2520}
2521
2522void Medium::SetExtrapolationMethodVelocity(const std::string& extrLow,
2523 const std::string& extrHigh) {
2524
2525 unsigned int iExtr = 0;
2526 if (GetExtrapolationIndex(extrLow, iExtr)) {
2527 m_extrLowVelocity = iExtr;
2528 } else {
2529 std::cerr << m_className << "::SetExtrapolationMethodVelocity:\n";
2530 std::cerr << " Unknown extrapolation method (" << extrLow << ")\n";
2531 }
2532
2533 if (GetExtrapolationIndex(extrHigh, iExtr)) {
2534 m_extrHighVelocity = iExtr;
2535 } else {
2536 std::cerr << m_className << "::SetExtrapolationMethodVelocity:\n";
2537 std::cerr << " Unknown extrapolation method (" << extrHigh << ")\n";
2538 }
2539}
2540
2541void Medium::SetExtrapolationMethodDiffusion(const std::string& extrLow,
2542 const std::string& extrHigh) {
2543
2544 unsigned int iExtr = 0;
2545 if (GetExtrapolationIndex(extrLow, iExtr)) {
2546 m_extrLowDiffusion = iExtr;
2547 } else {
2548 std::cerr << m_className << "::SetExtrapolationMethodDiffusion:\n";
2549 std::cerr << " Unknown extrapolation method (" << extrLow << ")\n";
2550 }
2551
2552 if (GetExtrapolationIndex(extrHigh, iExtr)) {
2553 m_extrHighDiffusion = iExtr;
2554 } else {
2555 std::cerr << m_className << "::SetExtrapolationMethodDiffusion:\n";
2556 std::cerr << " Unknown extrapolation method (" << extrHigh << ")\n";
2557 }
2558}
2559
2560void Medium::SetExtrapolationMethodTownsend(const std::string& extrLow,
2561 const std::string& extrHigh) {
2562
2563 unsigned int iExtr = 0;
2564 if (GetExtrapolationIndex(extrLow, iExtr)) {
2565 m_extrLowTownsend = iExtr;
2566 } else {
2567 std::cerr << m_className << "::SetExtrapolationMethodTownsend:\n";
2568 std::cerr << " Unknown extrapolation method (" << extrLow << ")\n";
2569 }
2570
2571 if (GetExtrapolationIndex(extrHigh, iExtr)) {
2572 m_extrHighTownsend = iExtr;
2573 } else {
2574 std::cerr << m_className << "::SetExtrapolationMethodTownsend:\n";
2575 std::cerr << " Unknown extrapolation method (" << extrHigh << ")\n";
2576 }
2577}
2578
2579void Medium::SetExtrapolationMethodAttachment(const std::string& extrLow,
2580 const std::string& extrHigh) {
2581
2582 unsigned int iExtr = 0;
2583 if (GetExtrapolationIndex(extrLow, iExtr)) {
2584 m_extrLowAttachment = iExtr;
2585 } else {
2586 std::cerr << m_className << "::SetExtrapolationMethodAttachment:\n";
2587 std::cerr << " Unknown extrapolation method (" << extrLow << ")\n";
2588 }
2589
2590 if (GetExtrapolationIndex(extrHigh, iExtr)) {
2591 m_extrHighAttachment = iExtr;
2592 } else {
2593 std::cerr << m_className << "::SetExtrapolationMethodAttachment:\n";
2594 std::cerr << " Unknown extrapolation method (" << extrHigh << ")\n";
2595 }
2596}
2597
2598void Medium::SetExtrapolationMethodIonMobility(const std::string& extrLow,
2599 const std::string& extrHigh) {
2600
2601 unsigned int iExtr = 0;
2602 if (GetExtrapolationIndex(extrLow, iExtr)) {
2603 m_extrLowMobility = iExtr;
2604 } else {
2605 std::cerr << m_className << "::SetExtrapolationMethodIonMobility:\n";
2606 std::cerr << " Unknown extrapolation method (" << extrLow << ")\n";
2607 }
2608 if (GetExtrapolationIndex(extrHigh, iExtr)) {
2609 m_extrHighMobility = iExtr;
2610 } else {
2611 std::cerr << m_className << "::SetExtrapolationMethodIonMobility:\n";
2612 std::cerr << " Unknown extrapolation method (" << extrHigh << ")\n";
2613 }
2614}
2615
2617 const std::string& extrHigh) {
2618
2619 unsigned int iExtr = 0;
2620 if (GetExtrapolationIndex(extrLow, iExtr)) {
2621 m_extrLowDissociation = iExtr;
2622 } else {
2623 std::cerr << m_className << "::SetExtrapolationMethodIonDissociation:\n";
2624 std::cerr << " Unknown extrapolation method (" << extrLow << ")\n";
2625 }
2626
2627 if (GetExtrapolationIndex(extrHigh, iExtr)) {
2628 m_extrHighDissociation = iExtr;
2629 } else {
2630 std::cerr << m_className << "::SetExtrapolationMethodIonDissociation:\n";
2631 std::cerr << " Unknown extrapolation method (" << extrHigh << ")\n";
2632 }
2633}
2634
2635bool Medium::GetExtrapolationIndex(std::string extrStr, unsigned int& extrNb) {
2636
2637 // Convert to upper-case
2638 for (unsigned int i = 0; i < extrStr.length(); ++i) {
2639 extrStr[i] = toupper(extrStr[i]);
2640 }
2641
2642 if (extrStr == "CONST" || extrStr == "CONSTANT") {
2643 extrNb = 0;
2644 } else if (extrStr == "LIN" || extrStr == "LINEAR") {
2645 extrNb = 1;
2646 } else if (extrStr == "EXP" || extrStr == "EXPONENTIAL") {
2647 extrNb = 2;
2648 } else {
2649 return false;
2650 }
2651
2652 return true;
2653}
2654
2655void Medium::SetInterpolationMethodVelocity(const unsigned int& intrp) {
2656
2657 if (intrp > 0) {
2658 m_intpVelocity = intrp;
2659 }
2660}
2661
2662void Medium::SetInterpolationMethodDiffusion(const unsigned int& intrp) {
2663
2664 if (intrp > 0) {
2665 m_intpDiffusion = intrp;
2666 }
2667}
2668
2669void Medium::SetInterpolationMethodTownsend(const unsigned int& intrp) {
2670
2671 if (intrp > 0) {
2672 m_intpTownsend = intrp;
2673 }
2674}
2675
2676void Medium::SetInterpolationMethodAttachment(const unsigned int& intrp) {
2677
2678 if (intrp > 0) {
2679 m_intpAttachment = intrp;
2680 }
2681}
2682
2683void Medium::SetInterpolationMethodIonMobility(const unsigned int& intrp) {
2684
2685 if (intrp > 0) {
2686 m_intpMobility = intrp;
2687 }
2688}
2689
2690void Medium::SetInterpolationMethodIonDissociation(const unsigned int& intrp) {
2691
2692 if (intrp > 0) {
2693 m_intpDissociation = intrp;
2694 }
2695}
2696
2697double Medium::Interpolate1D(const double& e, const std::vector<double>& table,
2698 const std::vector<double>& fields,
2699 const unsigned int& intpMeth, const int& extrLow,
2700 const int& extrHigh) {
2701
2702 // This function is a generalized version of the Fortran functions
2703 // GASVEL, GASVT1, GASVT2, GASLOR, GASMOB, GASDFT, and GASDFL
2704 // for the case of a 1D table. All variables are generic.
2705
2706 const int nSizeTable = fields.size();
2707
2708 if (e < 0. || nSizeTable < 1) return 0.;
2709
2710 double result = 0.;
2711
2712 if (nSizeTable == 1) {
2713 // Only one point
2714 result = table[0];
2715 } else if (e < fields[0]) {
2716 // Extrapolation towards small fields
2717 if (fields[0] >= fields[1]) {
2718 if (m_debug) {
2719 std::cerr << m_className << "::Interpolate1D:\n";
2720 std::cerr << " First two field values coincide.\n";
2721 std::cerr << " No extrapolation to lower fields.\n";
2722 }
2723 result = table[0];
2724 } else if (extrLow == 1) {
2725 // Linear extrapolation
2726 const double extr4 = (table[1] - table[0]) / (fields[1] - fields[0]);
2727 const double extr3 = table[0] - extr4 * fields[0];
2728 result = extr3 + extr4 * e;
2729 } else if (extrLow == 2) {
2730 // Logarithmic extrapolation
2731 const double extr4 = log(table[1] / table[0]) / (fields[1] - fields[0]);
2732 const double extr3 = log(table[0] - extr4 * fields[0]);
2733 result = std::exp(std::min(50., extr3 + extr4 * e));
2734 } else {
2735 result = table[0];
2736 }
2737 } else if (e > fields[nSizeTable - 1]) {
2738 // Extrapolation towards large fields
2739 if (fields[nSizeTable - 1] <= fields[nSizeTable - 2]) {
2740 if (m_debug) {
2741 std::cerr << m_className << "::Interpolate1D:\n";
2742 std::cerr << " Last two field values coincide.\n";
2743 std::cerr << " No extrapolation to higher fields.\n";
2744 }
2745 result = table[nSizeTable - 1];
2746 } else if (extrHigh == 1) {
2747 // Linear extrapolation
2748 const double extr2 = (table[nSizeTable - 1] - table[nSizeTable - 2]) /
2749 (fields[nSizeTable - 1] - fields[nSizeTable - 2]);
2750 const double extr1 =
2751 table[nSizeTable - 1] - extr2 * fields[nSizeTable - 1];
2752 result = extr1 + extr2 * e;
2753 } else if (extrHigh == 2) {
2754 // Logarithmic extrapolation
2755 const double extr2 = log(table[nSizeTable - 1] / table[nSizeTable - 2]) /
2756 (fields[nSizeTable - 1] - fields[nSizeTable - 2]);
2757 const double extr1 =
2758 log(table[nSizeTable - 1]) - extr2 * fields[nSizeTable - 1];
2759 result = exp(std::min(50., extr1 + extr2 * e));
2760 } else {
2761 result = table[nSizeTable - 1];
2762 }
2763 } else {
2764 // Intermediate points, spline interpolation (not implemented).
2765 // Intermediate points, Newtonian interpolation
2766 result = Numerics::Divdif(table, fields, nSizeTable, e, intpMeth);
2767 }
2768
2769 return result;
2770}
2771
2773 const unsigned int& eRes, const unsigned int& bRes,
2774 const unsigned int& aRes,
2775 std::vector<std::vector<std::vector<double> > >& tab, const double& val) {
2776
2777 if (eRes == 0 || bRes == 0 || aRes == 0) {
2778 std::cerr << m_className << "::InitParamArrays:\n";
2779 std::cerr << " Invalid grid.\n";
2780 return;
2781 }
2782
2783 tab.resize(aRes);
2784 for (unsigned int i = 0; i < aRes; ++i) {
2785 tab[i].resize(bRes);
2786 for (unsigned int j = 0; j < bRes; ++j) {
2787 tab[i][j].assign(eRes, val);
2788 }
2789 }
2790}
2791
2793 const unsigned int& eRes, const unsigned int& bRes,
2794 const unsigned int& aRes, const unsigned int& tRes,
2795 std::vector<std::vector<std::vector<std::vector<double> > > >& tab,
2796 const double& val) {
2797
2798 if (eRes == 0 || bRes == 0 || aRes == 0 || tRes == 0) {
2799 std::cerr << m_className << "::InitParamArrays:\n";
2800 std::cerr << " Invalid grid.\n";
2801 return;
2802 }
2803
2804 tab.resize(tRes);
2805 for (unsigned int l = 0; l < tRes; ++l) {
2806 tab[l].resize(aRes);
2807 for (unsigned int i = 0; i < aRes; ++i) {
2808 tab[l][i].resize(bRes);
2809 for (unsigned int j = 0; j < bRes; ++j) {
2810 tab[l][i][j].assign(eRes, val);
2811 }
2812 }
2813 }
2814}
2815}
DoubleAc cos(const DoubleAc &f)
Definition: DoubleAc.cpp:431
DoubleAc asin(const DoubleAc &f)
Definition: DoubleAc.cpp:468
DoubleAc pow(const DoubleAc &f, double p)
Definition: DoubleAc.cpp:336
DoubleAc sqrt(const DoubleAc &f)
Definition: DoubleAc.cpp:313
DoubleAc sin(const DoubleAc &f)
Definition: DoubleAc.cpp:383
DoubleAc acos(const DoubleAc &f)
Definition: DoubleAc.cpp:488
DoubleAc exp(const DoubleAc &f)
Definition: DoubleAc.cpp:376
DoubleAc fabs(const DoubleAc &f)
Definition: DoubleAc.h:616
void ResetHoleAttachment()
Definition: Medium.cc:1544
bool GetHoleVelocityE(const unsigned int &ie, const unsigned int &ib, const unsigned int &ia, double &v)
Definition: Medium.cc:2065
double m_density
Definition: Medium.hh:305
bool m_hasElectronDiffTens
Definition: Medium.hh:334
void ResetIonMobility()
Definition: Medium.cc:1550
unsigned int m_nBfields
Definition: Medium.hh:323
virtual bool GetPhotonCollision(const double e, int &type, int &level, double &e1, double &ctheta, int &nsec, double &esec)
Definition: Medium.cc:1474
bool GetElectronVelocityB(const unsigned int &ie, const unsigned int &ib, const unsigned int &ia, double &v)
Definition: Medium.cc:1943
void ResetElectronAttachment()
Definition: Medium.cc:1512
virtual double GetMassDensity() const
Definition: Medium.cc:150
unsigned int m_extrLowMobility
Definition: Medium.hh:383
void ResetIonDiffusion()
Definition: Medium.cc:1556
virtual void GetElectronMomentum(const double e, double &px, double &py, double &pz, int &band)
Definition: Medium.cc:693
bool SetIonMobility(const unsigned int &ie, const unsigned int &ib, const unsigned int &ia, const double &mu)
Definition: Medium.cc:2454
unsigned int m_intpDiffusion
Definition: Medium.hh:388
virtual void SetAtomicWeight(const double &a)
Definition: Medium.cc:178
bool GetElectronTransverseDiffusion(const unsigned int &ie, const unsigned int &ib, const unsigned int &ia, double &dt)
Definition: Medium.cc:1992
virtual void SetMassDensity(const double &rho)
Definition: Medium.cc:200
std::vector< std::vector< std::vector< double > > > tabHoleVelocityE
Definition: Medium.hh:351
virtual double ScaleElectricField(const double &e) const
Definition: Medium.hh:255
unsigned int m_extrLowDiffusion
Definition: Medium.hh:380
double m_pressure
Definition: Medium.hh:295
void InitParamTensor(const unsigned int &eRes, const unsigned int &bRes, const unsigned int &aRes, const unsigned int &tRes, std::vector< std::vector< std::vector< std::vector< double > > > > &tab, const double &val)
Definition: Medium.cc:2792
virtual bool HoleTownsend(const double ex, const double ey, const double ez, const double bx, const double by, const double bz, double &alpha)
Definition: Medium.cc:1079
virtual bool GetIonisationProduct(const int i, int &type, double &energy)
Definition: Medium.cc:748
bool m_hasElectronDiffTrans
Definition: Medium.hh:334
bool m_hasElectronTownsend
Definition: Medium.hh:335
void SetInterpolationMethodIonDissociation(const unsigned int &intrp)
Definition: Medium.cc:2690
virtual bool GetElectronCollision(const double e, int &type, int &level, double &e1, double &dx, double &dy, double &dz, int &nion, int &ndxc, int &band)
Definition: Medium.cc:727
void SetExtrapolationMethodIonDissociation(const std::string &extrLow, const std::string &extrHigh)
Definition: Medium.cc:2616
std::vector< double > bFields
Definition: Medium.hh:327
virtual double ScaleDiffusion(const double &d) const
Definition: Medium.hh:258
std::vector< std::vector< std::vector< double > > > tabElectronVelocityB
Definition: Medium.hh:338
unsigned int m_extrHighAttachment
Definition: Medium.hh:382
unsigned int m_nAngles
Definition: Medium.hh:324
bool GetIonLongitudinalDiffusion(const unsigned int &ie, const unsigned int &ib, const unsigned int &ia, double &dl)
Definition: Medium.cc:2256
bool GetIonDissociation(const unsigned int &ie, const unsigned int &ib, const unsigned int &ia, double &diss)
Definition: Medium.cc:2304
bool GetHoleVelocityExB(const unsigned int &ie, const unsigned int &ib, const unsigned int &ia, double &v)
Definition: Medium.cc:2089
virtual bool HoleVelocity(const double ex, const double ey, const double ez, const double bx, const double by, const double bz, double &vx, double &vy, double &vz)
Definition: Medium.cc:773
unsigned int m_intpMobility
Definition: Medium.hh:391
unsigned int m_intpAttachment
Definition: Medium.hh:390
bool GetElectronTownsend(const unsigned int &ie, const unsigned int &ib, const unsigned int &ia, double &alpha)
Definition: Medium.cc:2017
bool GetIonTransverseDiffusion(const unsigned int &ie, const unsigned int &ib, const unsigned int &ia, double &dt)
Definition: Medium.cc:2280
bool m_hasElectronVelocityB
Definition: Medium.hh:333
void ResetHoleVelocity()
Definition: Medium.cc:1518
bool GetExtrapolationIndex(std::string extrStr, unsigned int &extrNb)
Definition: Medium.cc:2635
void ResetIonDissociation()
Definition: Medium.cc:1564
unsigned int m_extrHighDiffusion
Definition: Medium.hh:380
std::vector< double > eFields
Definition: Medium.hh:326
std::vector< std::vector< std::vector< double > > > tabIonDissociation
Definition: Medium.hh:368
unsigned int m_extrHighMobility
Definition: Medium.hh:383
std::vector< std::vector< std::vector< double > > > tabElectronVelocityE
Definition: Medium.hh:336
void CloneTensor(std::vector< std::vector< std::vector< std::vector< double > > > > &tab, const unsigned int &n, const std::vector< double > &efields, const std::vector< double > &bfields, const std::vector< double > &angles, const unsigned int &intp, const unsigned int &extrLow, const unsigned int &extrHigh, const double &init, const std::string &label)
Definition: Medium.cc:2391
void SetFieldGrid(double emin, double emax, int ne, bool logE, double bmin=0., double bmax=0., int nb=1, double amin=0., double amax=0., int na=1)
Definition: Medium.cc:1570
std::string m_name
Definition: Medium.hh:291
unsigned int m_intpTownsend
Definition: Medium.hh:389
virtual void SetAtomicNumber(const double &z)
Definition: Medium.cc:167
unsigned int m_extrLowAttachment
Definition: Medium.hh:382
virtual bool GetOpticalDataRange(double &emin, double &emax, const unsigned int &i=0)
Definition: Medium.cc:1402
std::vector< double > bAngles
Definition: Medium.hh:328
unsigned int m_extrHighDissociation
Definition: Medium.hh:384
virtual double ScaleAttachment(const double &eta) const
Definition: Medium.hh:261
virtual void GetComponent(const unsigned int &i, std::string &label, double &f)
Definition: Medium.cc:155
virtual bool ElectronVelocity(const double ex, const double ey, const double ez, const double bx, const double by, const double bz, double &vx, double &vy, double &vz)
Definition: Medium.cc:217
virtual bool IonVelocity(const double ex, const double ey, const double ez, const double bx, const double by, const double bz, double &vx, double &vy, double &vz)
Definition: Medium.cc:1211
virtual double ScaleDiffusionTensor(const double &d) const
Definition: Medium.hh:259
unsigned int m_intpVelocity
Definition: Medium.hh:387
void SetExtrapolationMethodTownsend(const std::string &extrLow, const std::string &extrHigh)
Definition: Medium.cc:2560
bool m_hasHoleTownsend
Definition: Medium.hh:350
std::vector< std::vector< std::vector< double > > > tabElectronDiffLong
Definition: Medium.hh:339
void SetInterpolationMethodIonMobility(const unsigned int &intrp)
Definition: Medium.cc:2683
void SetExtrapolationMethodIonMobility(const std::string &extrLow, const std::string &extrHigh)
Definition: Medium.cc:2598
std::vector< std::vector< std::vector< double > > > tabElectronAttachment
Definition: Medium.hh:342
int thrIonDissociation
Definition: Medium.hh:376
virtual double GetElectronNullCollisionRate(const int band=0)
Definition: Medium.cc:708
unsigned int m_extrLowVelocity
Definition: Medium.hh:379
unsigned int m_extrHighTownsend
Definition: Medium.hh:381
virtual bool GetPhotoAbsorptionCrossSection(const double &e, double &sigma, const unsigned int &i=0)
Definition: Medium.cc:1443
virtual double ScaleDissociation(const double &diss) const
Definition: Medium.hh:262
virtual double GetElectronCollisionRate(const double e, const int band=0)
Definition: Medium.cc:717
void SetTemperature(const double &t)
Definition: Medium.cc:117
virtual bool ElectronDiffusion(const double ex, const double ey, const double ez, const double bx, const double by, const double bz, double &dl, double &dt)
Definition: Medium.cc:388
unsigned int m_extrHighVelocity
Definition: Medium.hh:379
std::vector< std::vector< std::vector< double > > > tabHoleTownsend
Definition: Medium.hh:356
void SetDielectricConstant(const double &eps)
Definition: Medium.cc:139
double m_epsilon
Definition: Medium.hh:297
unsigned int m_extrLowTownsend
Definition: Medium.hh:381
void SetExtrapolationMethodDiffusion(const std::string &extrLow, const std::string &extrHigh)
Definition: Medium.cc:2541
void GetFieldGrid(std::vector< double > &efields, std::vector< double > &bfields, std::vector< double > &angles)
Definition: Medium.cc:1886
double Interpolate1D(const double &e, const std::vector< double > &table, const std::vector< double > &fields, const unsigned int &intpMeth, const int &jExtr, const int &iExtr)
Definition: Medium.cc:2697
void SetPressure(const double &p)
Definition: Medium.cc:128
static int m_idCounter
Definition: Medium.hh:286
std::vector< std::vector< std::vector< std::vector< double > > > > tabHoleDiffTens
Definition: Medium.hh:359
virtual bool ElectronTownsend(const double ex, const double ey, const double ez, const double bx, const double by, const double bz, double &alpha)
Definition: Medium.cc:542
void ResetElectronDiffusion()
Definition: Medium.cc:1496
std::vector< std::vector< std::vector< double > > > tabIonDiffTrans
Definition: Medium.hh:367
void SetInterpolationMethodAttachment(const unsigned int &intrp)
Definition: Medium.cc:2676
unsigned int m_extrLowDissociation
Definition: Medium.hh:384
virtual bool GetDielectricFunction(const double &e, double &eps1, double &eps2, const unsigned int &i=0)
Definition: Medium.cc:1419
bool m_hasHoleVelocityB
Definition: Medium.hh:348
std::vector< std::vector< std::vector< std::vector< double > > > > tabElectronDiffTens
Definition: Medium.hh:345
bool GetHoleTransverseDiffusion(const unsigned int &ie, const unsigned int &ib, const unsigned int &ia, double &dt)
Definition: Medium.cc:2161
void SetInterpolationMethodVelocity(const unsigned int &intrp)
Definition: Medium.cc:2655
virtual bool GetDeexcitationProduct(const int i, double &t, double &s, int &type, double &energy)
Definition: Medium.cc:760
virtual double GetElectronEnergy(const double px, const double py, const double pz, double &vx, double &vy, double &vz, const int band=0)
Definition: Medium.cc:677
unsigned int m_nEfields
Definition: Medium.hh:322
std::vector< std::vector< std::vector< double > > > tabHoleVelocityExB
Definition: Medium.hh:352
void SetExtrapolationMethodVelocity(const std::string &extrLow, const std::string &extrHigh)
Definition: Medium.cc:2522
virtual bool ElectronAttachment(const double ex, const double ey, const double ez, const double bx, const double by, const double bz, double &eta)
Definition: Medium.cc:609
bool m_hasElectronVelocityExB
Definition: Medium.hh:333
bool GetHoleVelocityB(const unsigned int &ie, const unsigned int &ib, const unsigned int &ia, double &v)
Definition: Medium.cc:2113
std::vector< std::vector< std::vector< double > > > tabIonMobility
Definition: Medium.hh:365
bool m_hasHoleDiffTrans
Definition: Medium.hh:349
bool m_hasIonDiffTrans
Definition: Medium.hh:363
bool GetElectronVelocityExB(const unsigned int &ie, const unsigned int &ib, const unsigned int &ia, double &v)
Definition: Medium.cc:1919
int thrElectronAttachment
Definition: Medium.hh:372
bool m_hasIonMobility
Definition: Medium.hh:362
bool m_hasElectronDiffLong
Definition: Medium.hh:334
std::vector< std::vector< std::vector< double > > > tabHoleDiffTrans
Definition: Medium.hh:355
void InitParamArrays(const unsigned int &eRes, const unsigned int &bRes, const unsigned int &aRes, std::vector< std::vector< std::vector< double > > > &tab, const double &val)
Definition: Medium.cc:2772
bool GetElectronLongitudinalDiffusion(const unsigned int &ie, const unsigned int &ib, const unsigned int &ia, double &dl)
Definition: Medium.cc:1967
void SetExtrapolationMethodAttachment(const std::string &extrLow, const std::string &extrHigh)
Definition: Medium.cc:2579
std::vector< std::vector< std::vector< double > > > tabHoleVelocityB
Definition: Medium.hh:353
bool m_hasHoleDiffLong
Definition: Medium.hh:349
std::vector< std::vector< std::vector< double > > > tabHoleDiffLong
Definition: Medium.hh:354
unsigned int m_nComponents
Definition: Medium.hh:299
int thrHoleAttachment
Definition: Medium.hh:375
bool GetHoleAttachment(const unsigned int &ie, const unsigned int &ib, const unsigned int &ia, double &eta)
Definition: Medium.cc:2209
std::vector< std::vector< std::vector< double > > > tabIonDiffLong
Definition: Medium.hh:366
std::string m_className
Definition: Medium.hh:284
virtual bool HoleDiffusion(const double ex, const double ey, const double ez, const double bx, const double by, const double bz, double &dl, double &dt)
Definition: Medium.cc:928
bool GetHoleLongitudinalDiffusion(const unsigned int &ie, const unsigned int &ib, const unsigned int &ia, double &dl)
Definition: Medium.cc:2137
std::vector< std::vector< std::vector< double > > > tabHoleAttachment
Definition: Medium.hh:357
virtual bool IonDissociation(const double ex, const double ey, const double ez, const double bx, const double by, const double bz, double &diss)
Definition: Medium.cc:1335
bool m_hasIonDissociation
Definition: Medium.hh:364
void SetInterpolationMethodDiffusion(const unsigned int &intrp)
Definition: Medium.cc:2662
bool GetElectronAttachment(const unsigned int &ie, const unsigned int &ib, const unsigned int &ia, double &eta)
Definition: Medium.cc:2041
bool m_hasIonDiffLong
Definition: Medium.hh:363
bool GetHoleTownsend(const unsigned int &ie, const unsigned int &ib, const unsigned int &ia, double &alpha)
Definition: Medium.cc:2185
int thrHoleTownsend
Definition: Medium.hh:374
virtual double ScaleTownsend(const double &alpha) const
Definition: Medium.hh:260
unsigned int m_intpDissociation
Definition: Medium.hh:392
virtual double GetPhotonCollisionRate(const double &e)
Definition: Medium.cc:1466
bool m_hasHoleAttachment
Definition: Medium.hh:350
void ResetHoleDiffusion()
Definition: Medium.cc:1528
bool m_hasHoleVelocityExB
Definition: Medium.hh:348
void SetInterpolationMethodTownsend(const unsigned int &intrp)
Definition: Medium.cc:2669
bool m_isChanged
Definition: Medium.hh:316
bool m_hasElectronVelocityE
Definition: Medium.hh:333
bool GetElectronVelocityE(const unsigned int &ie, const unsigned int &ib, const unsigned int &ia, double &v)
Definition: Medium.cc:1895
std::vector< std::vector< std::vector< double > > > tabElectronTownsend
Definition: Medium.hh:341
void CloneTable(std::vector< std::vector< std::vector< double > > > &tab, const std::vector< double > &efields, const std::vector< double > &bfields, const std::vector< double > &angles, const unsigned int &intp, const unsigned int &extrLow, const unsigned int &extrHigh, const double init, const std::string label)
Definition: Medium.cc:2328
bool m_hasHoleVelocityE
Definition: Medium.hh:348
int thrElectronTownsend
Definition: Medium.hh:371
bool m_hasElectronAttachment
Definition: Medium.hh:335
void ResetElectronTownsend()
Definition: Medium.cc:1506
bool m_hasHoleDiffTens
Definition: Medium.hh:349
virtual bool HoleAttachment(const double ex, const double ey, const double ez, const double bx, const double by, const double bz, double &eta)
Definition: Medium.cc:1144
virtual void SetNumberDensity(const double &n)
Definition: Medium.cc:189
void ResetHoleTownsend()
Definition: Medium.cc:1538
void ResetElectronVelocity()
Definition: Medium.cc:1486
virtual bool IonDiffusion(const double ex, const double ey, const double ez, const double bx, const double by, const double bz, double &dl, double &dt)
Definition: Medium.cc:1268
double m_temperature
Definition: Medium.hh:293
std::vector< std::vector< std::vector< double > > > tabElectronDiffTrans
Definition: Medium.hh:340
std::vector< std::vector< std::vector< double > > > tabElectronVelocityExB
Definition: Medium.hh:337
bool GetIonMobility(const unsigned int &ie, const unsigned int &ib, const unsigned int &ia, double &mu)
Definition: Medium.cc:2233
bool Boxin3(std::vector< std::vector< std::vector< double > > > &value, std::vector< double > &xAxis, std::vector< double > &yAxis, std::vector< double > &zAxis, int nx, int ny, int nz, double xx, double yy, double zz, double &f, int iOrder)
Definition: Numerics.cc:771
double Divdif(const std::vector< double > &f, const std::vector< double > &a, int nn, double x, int mm)
Definition: Numerics.cc:650
double RndmUniform()
Definition: Random.hh:16