15int FindIndex(
const std::vector<double>& fields,
const double field,
18 if (fields.empty())
return -1;
19 const int n = fields.size();
20 for (
int i = 0; i < n; ++i) {
21 const double sum =
fabs(fields[i]) +
fabs(field);
22 const double tol = std::max(eps * sum, Garfield::Small);
23 if (
fabs(fields[i] - field) < tol)
return i;
36 std::cerr <<
m_className <<
"::SetMedium: Null pointer.\n";
44 const bool logscale) {
45 if (emin >= emax || emin < 0.) {
46 std::cerr <<
m_className <<
"::SetRangeE: Incorrect range.\n";
56 if (bmin >= bmax || bmin < 0.) {
57 std::cerr <<
m_className <<
"::SetRangeB: Incorrect range.\n";
67 if (amin >= amax || amin < 0.) {
68 std::cerr <<
m_className <<
"::SetRangeA: Incorrect range.\n";
78 const bool logscale) {
79 if (ymin >= ymax || ymin < 0.) {
80 std::cerr <<
m_className <<
"::SetRangeY: Incorrect range.\n";
152 std::cerr <<
m_className <<
"::PlotElectronCrossSections: Not implemented.\n";
155void ViewMedium::SetupCanvas() {
162 gPad->SetLeftMargin(0.15);
165void ViewMedium::AddFunction(
const bool keep,
const Property type,
169 std::cerr <<
m_className <<
"::AddFunction: Medium is not defined.\n";
176 std::cout <<
m_className <<
"::AddFunction: Adding " << fname <<
"\n";
180 for (
auto graph : m_graphs)
delete graph;
186 std::vector<double> efields;
187 std::vector<double> bfields;
188 std::vector<double> bangles;
190 double xmin = 0., xmax = 0.;
192 GetAxisRangeX(efields, bfields, bangles, xaxis, xmin, xmax, logx);
196 xmin, xmax, 5,
"ViewMedium",
"EvaluateFunction");
198 const std::string xlabel = GetLabelX(xaxis);
199 const std::string ylabel = GetLabelY(type);
200 const std::string title =
";" + xlabel +
";" + ylabel;
201 fcn.SetRange(xmin, xmax);
202 if (!m_autoRangeY && (
fabs(m_yMax - m_yMin) > 0.)) {
203 fcn.SetMinimum(m_yMin);
204 fcn.SetMaximum(m_yMax);
206 fcn.GetXaxis()->SetTitle(xlabel.c_str());
207 fcn.GetYaxis()->SetTitle(ylabel.c_str());
208 fcn.SetTitle(title.c_str());
209 fcn.SetParameter(0, type);
210 fcn.SetParameter(1, xaxis);
211 fcn.SetParameter(2, m_efield);
212 fcn.SetParameter(3, m_bfield);
213 fcn.SetParameter(4, m_angle);
214 const auto color = GetColor(type);
215 fcn.SetLineColor(color);
216 m_functions.push_back(std::move(fcn));
217 m_labels.emplace_back(std::make_pair(GetLegend(type), color));
218 const unsigned int nE = efields.size();
219 const unsigned int nB = bfields.size();
220 const unsigned int nA = bangles.size();
222 if (!efields.empty() && !bfields.empty() && !bangles.empty()) {
224 int nPoints = xaxis ==
'e' ? nE : xaxis ==
'b' ? nB : nA;
225 TGraph* graph =
new TGraph(nPoints);
226 graph->SetMarkerStyle(20);
227 graph->SetMarkerColor(color);
230 constexpr double eps = 1.e-3;
231 int ie = FindIndex(efields, m_efield, eps);
232 int ib = FindIndex(bfields, m_bfield, eps);
233 int ia = FindIndex(bangles, m_angle, eps);
234 if ((xaxis ==
'e' && (ib < 0 || ia < 0)) ||
235 (xaxis ==
'b' && (ie < 0 || ia < 0)) ||
236 (xaxis ==
'a' && (ie < 0 || ib < 0))) {
239 bool nonzero =
false;
240 for (
int j = 0; j < nPoints; ++j) {
245 }
else if (xaxis ==
'b') {
247 }
else if (xaxis ==
'a') {
250 std::cerr <<
m_className <<
"::AddFunction: Unexpected axis.\n";
329 else if (xaxis ==
'b')
330 graph->SetPoint(j, bfields[j], value);
331 else if (xaxis ==
'a')
332 graph->SetPoint(j, bangles[j], value);
333 if (
fabs(value) > 1.e-10) nonzero =
true;
336 m_graphs.push_back(graph);
339 std::cerr <<
m_className <<
"::AddFunction:\n Could not retrieve "
340 <<
"table for " << GetLegend(type) <<
".\n";
345 if (m_functions.empty())
return;
347 const unsigned int nFunctions = m_functions.size();
348 if (keep && nFunctions > 1) {
350 double ymin = m_functions[0].GetMinimum();
351 double ymax = m_functions[0].GetMaximum();
352 for (
unsigned int i = 1; i < nFunctions; ++i) {
353 const double fmin = m_functions[i].GetMinimum();
354 const double fmax = m_functions[i].GetMaximum();
355 constexpr double tol = 1.e-10;
356 if (
fabs(fmin) < tol &&
fabs(fmax) < tol)
continue;
357 ymin = std::min(ymin, fmin);
358 ymax = std::max(ymax, fmax);
361 const double dy = ymax - ymin;
362 for (
unsigned int i = 0; i < nFunctions; ++i) {
363 m_functions[i].SetMinimum(std::max(0., ymin - 0.1 * dy));
364 m_functions[i].SetMaximum(ymax + 0.1 * dy);
367 m_functions[0].Draw();
369 m_functions[0].DrawCopy()->GetYaxis()->SetTitleOffset(0);
370 double xLabel = 1.3 * xmin;
371 double yLabel = 0.9 * ymax;
372 label.SetText(xLabel, yLabel, m_labels[0].first.c_str());
373 xLabel += label.GetXsize();
374 label.SetTextColor(m_labels[0].second);
375 label.DrawLatex(xLabel, yLabel, m_labels[0].first.c_str());
376 for (
unsigned int i = 1; i < nFunctions; ++i) {
378 const double fmin = m_functions[i].GetMinimum();
379 const double fmax = m_functions[i].GetMaximum();
380 constexpr double tol = 1.e-10;
381 if (
fabs(fmin) < tol &&
fabs(fmax) < tol)
continue;
382 m_functions[i].DrawCopy(
"lsame");
383 yLabel -= 1.5 * label.GetYsize();
384 label.SetTextColor(m_labels[i].second);
385 label.DrawLatex(xLabel, yLabel, m_labels[i].first.c_str());
388 m_functions.back().DrawCopy()->GetYaxis()->SetTitleOffset(0);
390 for (
auto& graph : m_graphs) {
391 graph->DrawGraph(graph->GetN(), graph->GetX(), graph->GetY(),
"p");
398 if (m_logY && !m_autoRangeY) {
409 if (!m_medium)
return 0.;
410 int type = int(par[0]);
411 char xaxis = char(par[1]);
412 const double x = pos[0];
414 const double ctheta = xaxis ==
'a' ? cos(x) : cos(par[4]);
415 const double stheta = xaxis ==
'a' ? sin(x) : sin(par[4]);
416 double ex = xaxis ==
'e' ? x : par[2];
418 double bx = xaxis ==
'b' ? x : par[3];
423 ey = xaxis ==
'e' ? x * stheta : par[2] * stheta;
426 by = xaxis ==
'b' ? x * stheta : par[3] * stheta;
431 double s = 0., t = 0.;
453 if (!m_medium->
HoleVelocity(ex, 0, 0, bx, by, 0, y, s, t))
return 0.;
456 if (!m_medium->
HoleDiffusion(ex, 0, 0, bx, by, 0, s, y))
return 0.;
459 if (!m_medium->
HoleDiffusion(ex, 0, 0, bx, by, 0, y, s))
return 0.;
462 if (!m_medium->
HoleTownsend(ex, 0, 0, bx, by, 0, y))
return 0.;
468 if (!m_medium->
IonVelocity(ex, 0, 0, bx, by, 0, y, s, t))
return 0.;
471 if (!m_medium->
IonDiffusion(ex, 0, 0, bx, by, 0, s, y))
return 0.;
474 if (!m_medium->
IonDiffusion(ex, 0, 0, bx, by, 0, y, s))
return 0.;
485 if (!m_medium->
HoleVelocity(ex, ey, 0, bx, 0, 0, y, s, t))
return 0.;
489 if (!m_medium->
HoleVelocity(ex, ey, 0, bx, 0, 0, s, t, y))
return 0.;
493 std::cerr <<
m_className <<
"::EvaluateFunction:\n "
494 <<
"Unknown type of transport coefficient requested. Bug!\n";
501void ViewMedium::GetAxisRangeX(
const std::vector<double>& efields,
502 const std::vector<double>& bfields,
const std::vector<double>& angles,
503 const char xaxis,
double& xmin,
double& xmax,
bool& logx)
const {
507 if (xaxis ==
'e' && !efields.empty()) {
508 xmin = efields.front();
509 xmax = efields.back();
510 const double dx = xmax - xmin;
511 if (dx > Small && xmax > Small) {
521 }
else if (xaxis ==
'b' && !bfields.empty()) {
523 xmin = bfields.front();
524 xmax = bfields.back();
525 const double dx = xmax - xmin;
526 if (dx > Small && xmax > Small) {
527 if (xmin > Small) xmin *= 0.8;
531 }
else if (xaxis ==
'a' && !angles.empty()) {
533 xmin = angles.front();
534 xmax = angles.back();
535 const double dx = xmax - xmin;
536 if (dx > Small && xmax > Small) {
546 }
else if (xaxis ==
'b') {
550 }
else if (xaxis ==
'a') {
557int ViewMedium::GetColor(
const Property prop)
const {
576std::string ViewMedium::GetLabelX(
const char xaxis)
const {
579 return "electric field [V/cm]";
580 }
else if (xaxis ==
'b') {
581 return "magnetic field [T]";
582 }
else if (xaxis ==
'a') {
583 return "angle between #bf{E} and #bf{B} [rad]";
588std::string ViewMedium::GetLabelY(
const Property prop)
const {
598 return "drift velocity [cm/ns]";
606 return "diffusion coefficient [#kern[-0.1]{#sqrt{cm}}#kern[0.1]{]}";
610 return "#it{#alpha} [1/cm]";
614 return "#it{#eta} [1/cm]";
617 return "Angle between #bf{v} and #bf{E} [rad]";
625std::string ViewMedium::GetLegend(
const Property prop)
const {
627 std::string label =
"";
631 label +=
"velocity #parallel #bf{E}";
635 label +=
"velocity #parallel #bf{B}_{t}";
639 label +=
"velocity #parallel #bf{E}#times #bf{B}";
642 label +=
"ion velocity";
647 label +=
"longitudinal diffusion";
652 label +=
"transverse diffusion";
660 label +=
"Attachment";
663 label +=
"Lorenz angle";
Abstract base class for media.
virtual double UnScaleElectricField(const double e) const
virtual double ScaleVelocity(const double v) const
bool GetElectronVelocityB(const unsigned int ie, const unsigned int ib, const unsigned int ia, double &v)
Get an entry in the table of drift speeds along Btrans.
bool GetElectronVelocityE(const unsigned int ie, const unsigned int ib, const unsigned int ia, double &v)
Get an entry in the table of drift speeds along E.
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].
virtual double ScaleAttachment(const double eta) const
virtual double ScaleDiffusion(const double d) const
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 double ScaleLorentzAngle(const double lor) const
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 GetIonLongitudinalDiffusion(const unsigned int ie, const unsigned int ib, const unsigned int ia, double &dl)
Get an entry in the table of longitudinal diffusion coefficients.
bool GetHoleAttachment(const unsigned int ie, const unsigned int ib, const unsigned int ia, double &eta)
Get an entry in the table of attachment coefficients.
bool GetHoleVelocityExB(const unsigned int ie, const unsigned int ib, const unsigned int ia, double &v)
Get an entry in the table of drift speeds along ExB.
bool GetElectronAttachment(const unsigned int ie, const unsigned int ib, const unsigned int ia, double &eta)
Get an entry in the table of attachment 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 GetIonMobility(const unsigned int ie, const unsigned int ib, const unsigned int ia, double &mu)
Get an entry in the table of ion mobilities.
bool GetElectronTownsend(const unsigned int ie, const unsigned int ib, const unsigned int ia, double &alpha)
Get an entry in the table of Townsend coefficients.
bool GetElectronLorentzAngle(const unsigned int ie, const unsigned int ib, const unsigned int ia, double &lor)
Get an entry in the table of Lorentz angles.
virtual double ScaleTownsend(const double alpha) const
bool GetHoleTownsend(const unsigned int ie, const unsigned int ib, const unsigned int ia, double &alpha)
Get an entry in the table of Townsend 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].
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 GetElectronVelocityExB(const unsigned int ie, const unsigned int ib, const unsigned int ia, double &v)
Get an entry in the table of drift speeds along ExB.
bool GetElectronTransverseDiffusion(const unsigned int ie, const unsigned int ib, const unsigned int ia, double &dt)
Get an entry in the table of transverse diffusion coefficients.
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 GetHoleVelocityE(const unsigned int ie, const unsigned int ib, const unsigned int ia, double &v)
Get an entry in the table of drift speeds along E.
bool GetHoleVelocityB(const unsigned int ie, const unsigned int ib, const unsigned int ia, double &v)
Get an entry in the table of drift speeds along Btrans.
bool GetHoleTransverseDiffusion(const unsigned int ie, const unsigned int ib, const unsigned int ia, double &dt)
Get an entry in the table of transverse diffusion coefficients.
bool GetElectronLongitudinalDiffusion(const unsigned int ie, const unsigned int ib, const unsigned int 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 GetHoleLongitudinalDiffusion(const unsigned int ie, const unsigned int ib, const unsigned int ia, double &dl)
Get an entry in the table of longitudinal diffusion coefficients.
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].
bool GetIonTransverseDiffusion(const unsigned int ie, const unsigned int ib, const unsigned int ia, double &dt)
Get an entry in the table of transverse diffusion coefficients.
int GetRootColorElectron()
Base class for visualization classes.
std::string FindUnusedFunctionName(const std::string &s) const
double EvaluateFunction(double *pos, double *par)
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 PlotIonVelocity(const char xaxis, const bool same=false)
void PlotElectronTownsend(const char xaxis, const bool same=false)
void SetMedium(Medium *m)
Set the medium from which to retrieve the transport coefficients.
void PlotHoleVelocity(const char xaxis, const bool same=false)
void PlotHoleDiffusion(const char xaxis, const bool same=false)
void PlotElectronAttachment(const char xaxis, const bool same=false)
@ HoleTransverseDiffusion
@ HoleLongitudinalDiffusion
@ ElectronTransverseDiffusion
@ ElectronLongitudinalDiffusion
@ IonLongitudinalDiffusion
void PlotIonDiffusion(const char xaxis, const bool same=false)
void PlotElectronCrossSections()
void PlotElectronLorentzAngle(const char xaxis, const bool same=false)
void PlotElectronVelocity(const char xaxis, const bool same=false)
void SetRangeE(const double emin, const double emax, const bool logscale)
Set the limits of the electric field.
void PlotHoleAttachment(const char xaxis, const bool same=false)
void SetRangeA(const double amin, const double amax, const bool logscale)
Set the limits of the angle between electric and magnetic field.
void PlotElectronDiffusion(const char xaxis, const bool same=false)
void PlotHoleTownsend(const char xaxis, const bool same=false)
PlottingEngineRoot plottingEngine
DoubleAc exp(const DoubleAc &f)
DoubleAc fabs(const DoubleAc &f)