19int FindIndex(
const std::vector<double>& fields,
const double field,
22 if (fields.empty())
return -1;
23 const int n = fields.size();
24 for (
int i = 0; i < n; ++i) {
25 const double sum =
fabs(fields[i]) +
fabs(field);
26 const double tol = std::max(eps * sum, Garfield::Small);
27 if (
fabs(fields[i] - field) < tol)
return i;
32bool NonZero(
const std::vector<double>& v) {
34 constexpr double tol = 1.e-10;
35 return std::any_of(v.cbegin(), v.cend(), [](
double x){ return fabs(x) > tol; });
46 std::cerr <<
m_className <<
"::SetMedium: Null pointer.\n";
54 const bool logscale) {
55 if (emin >= emax || emin < 0.) {
56 std::cerr <<
m_className <<
"::SetRangeE: Incorrect range.\n";
66 if (bmin >= bmax || bmin < 0.) {
67 std::cerr <<
m_className <<
"::SetRangeB: Incorrect range.\n";
77 if (amin >= amax || amin < 0.) {
78 std::cerr <<
m_className <<
"::SetRangeA: Incorrect range.\n";
88 const bool logscale) {
89 if (ymin >= ymax || ymin < 0.) {
90 std::cerr <<
m_className <<
"::SetRangeY: Incorrect range.\n";
100 std::cerr <<
m_className <<
"::PlotElectronCrossSections: Not implemented.\n";
103void ViewMedium::Draw() {
105 if (m_yPlot.empty())
return;
110 const double xmin = m_xPlot.front();
111 const double xmax = m_xPlot.back();
112 double ymin = m_yMin;
113 double ymax = m_yMax;
115 ymin = std::numeric_limits<double>::max();
116 ymax = -std::numeric_limits<double>::max();
117 for (
const auto& plot : m_yPlot) {
118 ymin = std::min(ymin, *std::min_element(plot.cbegin(), plot.cend()));
119 ymax = std::max(ymax, *std::max_element(plot.cbegin(), plot.cend()));
121 const double dy = 0.05 * fabs(ymax - ymin);
122 ymin = std::max(0., ymin - dy);
125 auto frame = canvas->DrawFrame(xmin, ymin, xmax, ymax);
127 if (m_xaxis == Axis::E) {
128 frame->GetXaxis()->SetTitle(
"electric field [V/cm]");
129 }
else if (m_xaxis == Axis::B) {
130 frame->GetXaxis()->SetTitle(
"magnetic field [T]");
131 }
else if (m_xaxis == Axis::Angle) {
132 frame->GetXaxis()->SetTitle(
"angle between #bf{E} and #bf{B} [rad]");
134 std::cerr <<
m_className <<
"::Draw: Invalid x axis.\n";
137 auto yaxis = frame->GetYaxis();
139 case Parameter::VelocityE:
140 case Parameter::VelocityB:
141 case Parameter::VelocityExB:
142 yaxis->SetTitle(
"drift velocity [cm/ns]");
143 canvas->SetTitle(
"Drift velocity");
145 case Parameter::LongitudinalDiffusion:
146 case Parameter::TransverseDiffusion:
147 yaxis->SetTitle(
"diffusion coefficient [#kern[-0.1]{#sqrt{cm}}#kern[0.1]{]}");
148 canvas->SetTitle(
"Diffusion");
150 case Parameter::Townsend:
151 case Parameter::Attachment:
152 if (std::all_of(m_par.cbegin(), m_par.cend(), [](Parameter p) {
153 return p == Parameter::Townsend; })) {
154 yaxis->SetTitle(
"#it{#alpha} [1/cm]");
155 canvas->SetTitle(
"Multiplication");
156 }
else if (std::all_of(m_par.cbegin(), m_par.cend(), [](Parameter p) {
157 return p == Parameter::Attachment; })) {
158 yaxis->SetTitle(
"#it{#eta} [1/cm]");
159 canvas->SetTitle(
"Attachment");
161 yaxis->SetTitle(
"#it{#alpha}, #it{#eta} [1/cm]");
162 canvas->SetTitle(
"Multiplication and attachment");
165 case Parameter::LorentzAngle:
166 yaxis->SetTitle(
"Angle between #bf{v} and #bf{E} [rad]");
167 canvas->SetTitle(
"Lorentz angle");
172 yaxis->SetTitleOffset(0);
173 gPad->SetLeftMargin(0.15);
176 const unsigned int nPlots = m_yPlot.size();
178 std::vector<short> cols(nPlots, 0);
179 if (m_colours.empty()) {
180 auto it = std::find(m_q.cbegin(), m_q.cend(), Charge::Electron);
181 if (it != m_q.cend()) {
182 cols[std::distance(m_q.cbegin(), it)] = kOrange - 3;
184 it = std::find(std::next(it), m_q.cend(), Charge::Electron);
185 if (it != m_q.cend()) {
186 cols[std::distance(m_q.cbegin(), it)] = kGreen + 3;
188 it = std::find(m_q.cbegin(), m_q.cend(), Charge::Hole);
189 if (it != m_q.cend()) {
190 cols[std::distance(m_q.cbegin(), it)] = kRed + 1;
192 it = std::find(m_q.cbegin(), m_q.cend(), Charge::Ion);
193 if (it != m_q.cend()) {
194 cols[std::distance(m_q.cbegin(), it)] = kRed + 1;
197 for (
unsigned int i = 0; i < nPlots; ++i) {
198 cols[i] = m_colours[i % m_colours.size()];
202 std::vector<std::string> labels = m_labels;
203 labels.resize(nPlots,
"");
204 if (nPlots > 1 && m_labels.empty()) {
205 bool allEqual = std::equal(m_q.begin() + 1, m_q.end(), m_q.begin());
207 for (
unsigned int i = 0; i < nPlots; ++i) {
208 if (m_q[i] == Charge::Electron) {
209 labels[i] =
"electrons";
210 }
else if (m_q[i] == Charge::Hole) {
217 allEqual = std::equal(m_par.begin() + 1, m_par.end(), m_par.begin());
219 for (
unsigned int i = 0; i < nPlots; ++i) {
220 if (!labels[i].empty()) labels[i] +=
", ";
222 case Parameter::VelocityE:
223 labels[i] +=
"#it{v}_{#it{E}}";
225 case Parameter::VelocityB:
226 labels[i] +=
"#it{v}_{#it{B}#kern[0.1]{t}}";
228 case Parameter::VelocityExB:
229 labels[i] +=
"#it{v}_{#it{E}#kern[0.05]{#times}#it{B}}";
231 case Parameter::LongitudinalDiffusion:
232 labels[i] +=
"#it{D}_{L}";
234 case Parameter::TransverseDiffusion:
235 labels[i] +=
"#it{D}_{T}";
237 case Parameter::Townsend:
238 labels[i] +=
"#alpha";
240 case Parameter::Attachment:
243 case Parameter::LorentzAngle:
244 labels[i] +=
"Lorentz angle";
251 double xsize = 0., ysize = 0.;
252 for (
const auto& label : labels) {
253 latex.SetText(0, 0, label.c_str());
254 xsize = std::max(xsize, latex.GetXsize());
255 ysize = std::max(ysize, latex.GetYsize());
258 xsize /= (gPad->GetX2() - gPad->GetX1());
259 ysize /= (gPad->GetY2() - gPad->GetY1());
261 const double lm = gPad->GetLeftMargin();
262 const double rm = 1. - gPad->GetRightMargin();
263 const double tm = 1. - gPad->GetTopMargin();
264 const double bm = gPad->GetBottomMargin();
265 double xLabel = lm + 0.1 * (rm - lm);
266 if (m_par[0] == Parameter::LongitudinalDiffusion ||
267 m_par[0] == Parameter::TransverseDiffusion) {
268 xLabel = rm - 0.1 * (rm - lm) - xsize;
270 double yLabel = tm - 0.1 * (tm - bm);
271 const double colrange = gStyle->GetNumberOfColors() / double(nPlots);
272 for (
unsigned int i = 0; i < nPlots; ++i) {
273 int col = cols[i] > 0 ? cols[i] : gStyle->GetColorPalette(i * colrange);
274 graph.SetLineColor(col);
275 graph.SetMarkerColor(col);
276 graph.DrawGraph(m_xPlot.size(),
277 m_xPlot.data(), m_yPlot[i].data(),
"L");
278 graph.SetMarkerStyle(20 + i);
279 if (!m_xGraph[i].empty()) {
280 graph.DrawGraph(m_xGraph[i].size(),
281 m_xGraph[i].data(), m_yGraph[i].data(),
"P");
284 if (labels[i].empty())
continue;
285 latex.SetTextColor(col);
286 latex.DrawLatexNDC(xLabel, yLabel, labels[i].c_str());
287 yLabel -= 1.5 * ysize;
289 if (m_logX && xmin > 0.) {
294 if (m_logY && ymin > 0. && !m_autoRangeY) {
302void ViewMedium::ResetY() {
310void ViewMedium::ResetX(
const Axis xaxis) {
312 double xmin = 0., xmax = 0.;
314 if (xaxis == Axis::E) {
318 }
else if (xaxis == Axis::B) {
322 }
else if (xaxis == Axis::Angle) {
327 m_xaxis = Axis::None;
333 std::vector<double> efields;
334 std::vector<double> bfields;
335 std::vector<double> bangles;
337 if (xaxis == Axis::E && !efields.empty()) {
338 if (efields.front() > 0. && efields.back() > 10. * efields.front()) {
340 xmin = efields.front() / 1.5;
341 xmax = efields.back() * 1.5;
344 const double dx = 0.05 *
fabs(efields.back() - efields.front());
345 xmin = std::max(0., efields.front() - dx);
346 xmax = efields.back() + dx;
348 }
else if (xaxis == Axis::B && !bfields.empty()) {
350 const double dx = 0.05 *
fabs(bfields.back() - bfields.front());
351 xmin = std::max(0., bfields.front() - dx);
352 xmax = bfields.back() + dx;
353 }
else if (xaxis == Axis::Angle && !bangles.empty()) {
355 const double dx = 0.05 *
fabs(bangles.back() - bangles.front());
356 xmin = std::max(0., bangles.front() - dx);
357 xmax = std::min(TwoPi, bangles.back() + dx);
361 constexpr unsigned int nX = 1000;
362 m_xPlot.assign(nX, 0.);
365 const double r =
pow(xmax / xmin, 1. / (nX - 1));
366 for (
unsigned int i = 1; i < nX; ++i) {
367 m_xPlot[i] = m_xPlot[i - 1] * r;
370 const double dx = (xmax - xmin) / (nX - 1);
371 for (
unsigned int i = 0; i < nX; ++i) {
372 m_xPlot[i] = xmin + i * dx;
379void ViewMedium::PlotDiffusion(
const Axis xaxis,
const Charge charge,
383 std::cerr <<
m_className <<
"::PlotDiffusion: Medium is not defined.\n";
386 if (xaxis != m_xaxis) {
391 }
else if (!m_par.empty()) {
392 if (m_par[0] != Parameter::TransverseDiffusion &&
393 m_par[0] != Parameter::LongitudinalDiffusion) {
397 const unsigned int nX = m_xPlot.size();
398 std::array<std::vector<double>, 2> ypl;
399 for (
unsigned int i = 0; i < 2; ++i) ypl[i].assign(nX, 0.);
401 double ex = m_efield;
402 double ctheta =
cos(m_angle);
403 double stheta =
sin(m_angle);
404 double bx = m_bfield * ctheta;
405 double by = m_bfield * stheta;
406 for (
unsigned int i = 0; i < nX; ++i) {
407 if (xaxis == Axis::E) {
409 }
else if (xaxis == Axis::B) {
410 bx = m_xPlot[i] * ctheta;
411 by = m_xPlot[i] * stheta;
413 bx = m_bfield *
cos(m_xPlot[i]);
414 by = m_bfield *
sin(m_xPlot[i]);
416 double dl = 0., dt = 0.;
417 if (charge == Charge::Electron) {
419 }
else if (charge == Charge::Hole) {
420 if (!m_medium->
HoleDiffusion(ex, 0, 0, bx, by, 0, dl, dt))
continue;
422 if (!m_medium->
IonDiffusion(ex, 0, 0, bx, by, 0, dl, dt))
continue;
428 std::array<std::vector<double>, 2> xgr;
429 std::array<std::vector<double>, 2> ygr;
431 std::array<std::vector<double>, 3> grid;
432 int ie = 0, ib = 0, ia = 0;
433 if (GetGrid(grid, ie, ib, ia, xaxis)) {
434 const auto nPoints = xaxis == Axis::E ? grid[0].size() :
435 xaxis == Axis::B ? grid[1].size() : grid[2].size();
436 for (
unsigned int j = 0; j < nPoints; ++j) {
437 double x = 0.,
y = 0.;
438 if (xaxis == Axis::E) {
441 }
else if (xaxis == Axis::B) {
444 }
else if (xaxis == Axis::Angle) {
448 if (charge == Charge::Electron) {
457 }
else if (charge == Charge::Hole) {
479 const std::array<Parameter, 2> pars = {Parameter::LongitudinalDiffusion,
480 Parameter::TransverseDiffusion};
481 for (
unsigned int i = 0; i < 2; ++i) {
482 if (!NonZero(ypl[i]))
continue;
483 m_yPlot.push_back(std::move(ypl[i]));
484 m_par.push_back(pars[i]);
485 m_q.push_back(charge);
486 m_xGraph.push_back(std::move(xgr[i]));
487 m_yGraph.push_back(std::move(ygr[i]));
492void ViewMedium::PlotVelocity(
const Axis xaxis,
const Charge charge,
496 std::cerr <<
m_className <<
"::PlotVelocity: Medium is not defined.\n";
499 if (xaxis != m_xaxis) {
504 }
else if (!m_par.empty()) {
505 if (m_par[0] != Parameter::VelocityE &&
506 m_par[0] != Parameter::VelocityB &&
507 m_par[0] != Parameter::VelocityExB) {
511 const unsigned int nX = m_xPlot.size();
512 std::array<std::vector<double>, 3> ypl;
513 for (
unsigned int i = 0; i < 3; ++i) ypl[i].assign(nX, 0.);
515 double e0 = m_efield;
516 double b0 = m_bfield;
517 double ctheta =
cos(m_angle);
518 double stheta =
sin(m_angle);
520 for (
unsigned int i = 0; i < nX; ++i) {
521 if (xaxis == Axis::E) {
523 }
else if (xaxis == Axis::B) {
526 ctheta =
cos(m_xPlot[i]);
527 stheta =
sin(m_xPlot[i]);
529 double vx = 0., vy = 0., vz = 0.;
530 if (charge == Charge::Electron) {
533 ypl[0][i] =
fabs(vx);
534 ypl[1][i] =
fabs(vy);
535 ypl[2][i] =
fabs(vz);
537 }
else if (charge == Charge::Hole) {
538 if (m_medium->
HoleVelocity(e0, 0, 0, b0 * ctheta, b0 * stheta, 0,
540 ypl[0][i] =
fabs(vx);
541 ypl[1][i] =
fabs(vy);
542 ypl[2][i] =
fabs(vz);
545 if (m_medium->
IonVelocity(e0, 0, 0, b0 * ctheta, b0 * stheta, 0,
547 ypl[0][i] =
fabs(vx);
551 std::array<std::vector<double>, 3> xgr;
552 std::array<std::vector<double>, 3> ygr;
554 std::array<std::vector<double>, 3> grid;
555 int ie = 0, ib = 0, ia = 0;
556 if (GetGrid(grid, ie, ib, ia, xaxis)) {
557 const auto nPoints = xaxis == Axis::E ? grid[0].size() :
558 xaxis == Axis::B ? grid[1].size() : grid[2].size();
559 for (
unsigned int j = 0; j < nPoints; ++j) {
560 double x = 0.,
y = 0.;
561 if (xaxis == Axis::E) {
564 }
else if (xaxis == Axis::B) {
567 }
else if (xaxis == Axis::Angle) {
571 if (charge == Charge::Electron) {
584 }
else if (charge == Charge::Hole) {
606 const std::array<Parameter, 3> pars = {Parameter::VelocityE,
607 Parameter::VelocityB,
608 Parameter::VelocityExB};
609 for (
unsigned int i = 0; i < 3; ++i) {
610 if (!NonZero(ypl[i]))
continue;
611 m_yPlot.push_back(std::move(ypl[i]));
612 m_par.push_back(pars[i]);
613 m_q.push_back(charge);
614 m_xGraph.push_back(std::move(xgr[i]));
615 m_yGraph.push_back(std::move(ygr[i]));
620void ViewMedium::Plot(
const Axis xaxis,
const Charge charge,
621 const Parameter par,
const bool same) {
625 std::cerr <<
m_className <<
"::Plot: Medium is not defined.\n";
628 if (xaxis != m_xaxis) {
633 }
else if (!m_par.empty()) {
634 if (m_par[0] != Parameter::Townsend &&
635 m_par[0] != Parameter::Attachment) {
640 const unsigned int nX = m_xPlot.size();
641 std::vector<double> ypl(nX, 0.);
642 double ex = m_efield;
643 double ctheta =
cos(m_angle);
644 double stheta =
sin(m_angle);
645 double bx = m_bfield * ctheta;
646 double by = m_bfield * stheta;
647 for (
unsigned int i = 0; i < nX; ++i) {
648 if (xaxis == Axis::E) {
650 }
else if (xaxis == Axis::B) {
651 bx = m_xPlot[i] * ctheta;
652 by = m_xPlot[i] * stheta;
654 bx = m_bfield *
cos(m_xPlot[i]);
655 by = m_bfield *
sin(m_xPlot[i]);
658 if (charge == Charge::Electron) {
659 if (par == Parameter::Townsend) {
666 if (par == Parameter::Townsend) {
667 if (!m_medium->
HoleTownsend(ex, 0, 0, bx, by, 0, y))
continue;
676 std::vector<double> xgr;
677 std::vector<double> ygr;
679 std::array<std::vector<double>, 3> grid;
680 int ie = 0, ib = 0, ia = 0;
681 if (GetGrid(grid, ie, ib, ia, xaxis)) {
682 const auto nPoints = xaxis == Axis::E ? grid[0].size() :
683 xaxis == Axis::B ? grid[1].size() : grid[2].size();
684 for (
unsigned int j = 0; j < nPoints; ++j) {
685 double x = 0.,
y = 0.;
686 if (xaxis == Axis::E) {
689 }
else if (xaxis == Axis::B) {
692 }
else if (xaxis == Axis::Angle) {
696 if (charge == Charge::Electron) {
697 if (par == Parameter::Townsend) {
708 }
else if (charge == Charge::Hole) {
709 if (par == Parameter::Townsend) {
724 if (!NonZero(ypl))
return;
725 m_yPlot.push_back(std::move(ypl));
726 m_par.push_back(par);
727 m_q.push_back(charge);
728 m_xGraph.push_back(std::move(xgr));
729 m_yGraph.push_back(std::move(ygr));
733void ViewMedium::PlotLorentzAngle(
const Axis xaxis,
const Charge charge,
738 std::cerr <<
m_className <<
"::PlotLorentzAngle: Medium is not defined.\n";
741 if (xaxis != m_xaxis) {
746 }
else if (!m_par.empty()) {
747 if (m_par[0] != Parameter::LorentzAngle) ResetY();
750 const unsigned int nX = m_xPlot.size();
751 std::vector<double> ypl(nX, 0.);
752 double ex = m_efield;
753 double ctheta =
cos(m_angle);
754 double stheta =
sin(m_angle);
755 double bx = m_bfield * ctheta;
756 double by = m_bfield * stheta;
757 for (
unsigned int i = 0; i < nX; ++i) {
758 if (xaxis == Axis::E) {
760 }
else if (xaxis == Axis::B) {
761 bx = m_xPlot[i] * ctheta;
762 by = m_xPlot[i] * stheta;
764 bx = m_bfield *
cos(m_xPlot[i]);
765 by = m_bfield *
sin(m_xPlot[i]);
772 std::vector<double> xgr;
773 std::vector<double> ygr;
775 std::array<std::vector<double>, 3> grid;
776 int ie = 0, ib = 0, ia = 0;
777 if (GetGrid(grid, ie, ib, ia, xaxis)) {
778 const auto nPoints = xaxis == Axis::E ? grid[0].size() :
779 xaxis == Axis::B ? grid[1].size() : grid[2].size();
780 for (
unsigned int j = 0; j < nPoints; ++j) {
781 double x = 0.,
y = 0.;
782 if (xaxis == Axis::E) {
785 }
else if (xaxis == Axis::B) {
788 }
else if (xaxis == Axis::Angle) {
799 if (!NonZero(ypl))
return;
800 m_yPlot.push_back(std::move(ypl));
801 m_par.push_back(Parameter::LorentzAngle);
802 m_q.push_back(charge);
803 m_xGraph.push_back(std::move(xgr));
804 m_yGraph.push_back(std::move(ygr));
808ViewMedium::Axis ViewMedium::GetAxis(
const char xaxis)
const {
810 if (std::toupper(xaxis) ==
'E') {
812 }
else if (std::toupper(xaxis) ==
'B') {
814 }
else if (std::toupper(xaxis) ==
'A') {
820bool ViewMedium::GetGrid(std::array<std::vector<double>, 3>& grid,
821 int& ie,
int& ib,
int& ia,
822 const Axis xaxis)
const {
824 if (!m_medium)
return false;
826 if (grid[0].empty() || grid[1].empty() || grid[2].empty())
return false;
827 constexpr double eps = 1.e-3;
828 ie = FindIndex(grid[0], m_efield, eps);
829 ib = FindIndex(grid[1], m_bfield, eps);
830 ia = FindIndex(grid[2], m_angle, eps);
831 if (xaxis == Axis::E) {
832 if (ib < 0 || ia < 0)
return false;
833 }
else if (xaxis == Axis::B) {
834 if (ie < 0 || ia < 0)
return false;
835 }
else if (xaxis == Axis::Angle) {
836 if (ie < 0 || ib < 0)
return false;
Abstract base class for media.
virtual double UnScaleElectricField(const double e) const
bool GetHoleLongitudinalDiffusion(const size_t ie, const size_t ib, const size_t ia, double &dl)
Get an entry in the table of longitudinal diffusion coefficients.
virtual double ScaleVelocity(const double v) const
bool GetHoleTownsend(const size_t ie, const size_t ib, const size_t ia, double &alpha)
Get an entry in the table of Townsend coefficients.
virtual bool HoleTownsend(const double ex, const double ey, const double ez, const double bx, const double by, const double bz, double &alpha)
Ionisation coefficient [cm-1].
bool GetElectronLorentzAngle(const size_t ie, const size_t ib, const size_t ia, double &lor)
Get an entry in the table of Lorentz angles.
virtual double ScaleAttachment(const double eta) const
virtual double ScaleDiffusion(const double d) const
bool GetHoleAttachment(const size_t ie, const size_t ib, const size_t ia, double &eta)
Get an entry in the table of attachment coefficients.
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)
Drift velocity [cm / ns].
virtual bool ElectronLorentzAngle(const double ex, const double ey, const double ez, const double bx, const double by, const double bz, double &lor)
Lorentz angle.
bool GetIonTransverseDiffusion(const size_t ie, const size_t ib, const size_t ia, double &dt)
Get an entry in the table of transverse diffusion coefficients.
bool GetElectronTransverseDiffusion(const size_t ie, const size_t ib, const size_t ia, double &dt)
Get an entry in the table of transverse diffusion coefficients.
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)
Drift velocity [cm / ns].
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)
Drift velocity [cm / ns].
bool GetHoleTransverseDiffusion(const size_t ie, const size_t ib, const size_t ia, double &dt)
Get an entry in the table of transverse diffusion coefficients.
bool GetHoleVelocityExB(const size_t ie, const size_t ib, const size_t ia, double &v)
Get an entry in the table of drift speeds along ExB.
virtual double ScaleTownsend(const double alpha) const
bool GetElectronAttachment(const size_t ie, const size_t ib, const size_t ia, double &eta)
Get an entry in the table of attachment coefficients.
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)
Longitudinal and transverse diffusion coefficients [cm1/2].
bool GetElectronVelocityE(const size_t ie, const size_t ib, const size_t ia, double &v)
Get an entry in the table of drift speeds along E.
void GetFieldGrid(std::vector< double > &efields, std::vector< double > &bfields, std::vector< double > &angles)
Get the fields and E-B angles used in the transport tables.
virtual bool ElectronTownsend(const double ex, const double ey, const double ez, const double bx, const double by, const double bz, double &alpha)
Ionisation coefficient [cm-1].
bool GetHoleVelocityB(const size_t ie, const size_t ib, const size_t ia, double &v)
Get an entry in the table of drift speeds along Btrans.
bool GetElectronTownsend(const size_t ie, const size_t ib, const size_t ia, double &alpha)
Get an entry in the table of Townsend coefficients.
bool GetIonMobility(const size_t ie, const size_t ib, const size_t ia, double &mu)
Get an entry in the table of ion mobilities.
virtual bool ElectronAttachment(const double ex, const double ey, const double ez, const double bx, const double by, const double bz, double &eta)
Attachment coefficient [cm-1].
bool GetElectronVelocityExB(const size_t ie, const size_t ib, const size_t ia, double &v)
Get an entry in the table of drift speeds along ExB.
bool GetElectronVelocityB(const size_t ie, const size_t ib, const size_t ia, double &v)
Get an entry in the table of drift speeds along Btrans.
bool GetIonLongitudinalDiffusion(const size_t ie, const size_t ib, const size_t ia, double &dl)
Get an entry in the table of longitudinal diffusion coefficients.
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)
Longitudinal and transverse diffusion coefficients [cm1/2].
bool GetElectronLongitudinalDiffusion(const size_t ie, const size_t ib, const size_t ia, double &dl)
Get an entry in the table of longitudinal diffusion coefficients.
bool GetHoleVelocityE(const size_t ie, const size_t ib, const size_t ia, double &v)
Get an entry in the table of drift speeds along E.
virtual bool HoleAttachment(const double ex, const double ey, const double ez, const double bx, const double by, const double bz, double &eta)
Attachment coefficient [cm-1].
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)
Longitudinal and transverse diffusion coefficients [cm1/2].
Base class for visualization classes.
TPad * GetCanvas()
Retrieve the canvas.
void SetRangeY(const double ymin, const double ymax, const bool logscale=false)
Set the range of the function (velocity etc.) to be plotted.
void SetRangeB(const double bmin, const double bmax, const bool logscale)
Set the limits of the magnetic field.
void SetMedium(Medium *m)
Set the medium from which to retrieve the transport coefficients.
void PlotElectronCrossSections()
void SetRangeE(const double emin, const double emax, const bool logscale)
Set the limits of the electric field.
void SetRangeA(const double amin, const double amax, const bool logscale)
Set the limits of the angle between electric and magnetic field.
DoubleAc cos(const DoubleAc &f)
DoubleAc pow(const DoubleAc &f, double p)
DoubleAc exp(const DoubleAc &f)
DoubleAc fabs(const DoubleAc &f)
DoubleAc sin(const DoubleAc &f)