Commit 238cf495 authored by Heinrich Schindler's avatar Heinrich Schindler
Browse files

Merge branch 'bfield' into 'master'

Adapt ViewField to be able to plot magnetic fields.

See merge request !246
parents 9b8d1ab2 ee85d853
Pipeline #3157401 passed with stage
in 6 minutes and 11 seconds
......@@ -30,6 +30,8 @@ class ViewField : public ViewBase {
void SetElectricFieldRange(const double emin, const double emax);
/// Set the plot limits for the weighting field.
void SetWeightingFieldRange(const double wmin, const double wmax);
/// Set the plot limits for the magnetic field.
void SetMagneticFieldRange(const double bmin, const double bmax);
/// Set the number of contour levels.
void SetNumberOfContours(const unsigned int n);
......@@ -38,22 +40,28 @@ class ViewField : public ViewBase {
/// Set the number of points used for drawing 2D functions.
void SetNumberOfSamples2d(const unsigned int nx, const unsigned int ny);
/** Make a contour plot of the electric potential or field.
/** Make a contour plot of the electric potential, electric field,
* or magnetic field.
* \param option quantity to be plotted
* - potential: "v", "voltage", "p", "potential"
* - magnitude of the electric field: "e", "field"
* - magnitude of the electric field: "emag", "field"
* - x-component of the electric field: "ex"
* - y-component of the electric field: "ey"
* - z-component of the electric field: "ez"
* - magnitude of the magnetic field: "bmag"
* - x-component of the magnetic field: "bx"
* - y-component of the magnetic field: "by"
* - z-component of the magnetic field: "bz"
**/
void PlotContour(const std::string& option = "v");
/** Make a 2D plot of the electric potential or field.
/** Make a 2D plot of the electric potential, electric field or
* magnetic field.
* \param option quantity to be plotted (see PlotContour)
* \param drawopt option string passed to TF2::Draw
**/
void Plot(const std::string& option = "v",
const std::string& drawopt = "arr");
/** Make a 1D plot of the electric potential or field along a line.
/** Make a 1D plot of the potential or field along a line.
* \param x0,y0,z0 starting point
* \param x1,y1,z1 end point
* \param option quantity to be plotted (see PlotContour)
......@@ -128,7 +136,17 @@ class ViewField : public ViewBase {
const double interval = 10.) const;
private:
enum class Parameter { Potential = 0, Magnitude, Ex, Ey, Ez, Unknown };
enum class Parameter {
Potential = 0,
Emag,
Ex,
Ey,
Ez,
Bmag,
Bx,
By,
Bz,
Unknown };
bool m_useAutoRange = true;
bool m_samplePotential = true;
......@@ -143,6 +161,7 @@ class ViewField : public ViewBase {
double m_vmin = 0., m_vmax = 100.;
double m_emin = 0., m_emax = 10000.;
double m_wmin = 0., m_wmax = 100.;
double m_bmin = 0., m_bmax = 10.;
// Number of contours
unsigned int m_nContours = 20;
......@@ -159,11 +178,14 @@ class ViewField : public ViewBase {
const double x1, const double y1, const double z1,
const std::string& option, const bool wfield,
const std::string& electrode, const bool normalised);
Parameter GetPar(const std::string& option, std::string& title) const;
double Field(const double x, const double y, const double z,
const Parameter par) const;
Parameter GetPar(const std::string& option, std::string& title,
bool& bfield) const;
double Efield(const double x, const double y, const double z,
const Parameter par) const;
double Wfield(const double x, const double y, const double z,
const Parameter par, const std::string& electrode) const;
double Bfield(const double x, const double y, const double z,
const Parameter par) const;
};
}
......
......@@ -105,6 +105,12 @@ void ViewField::SetWeightingFieldRange(const double wmin, const double wmax) {
m_useAutoRange = false;
}
void ViewField::SetMagneticFieldRange(const double bmin, const double bmax) {
m_bmin = std::min(bmin, bmax);
m_bmax = std::max(bmin, bmax);
m_useAutoRange = false;
}
void ViewField::SetNumberOfContours(const unsigned int n) {
if (n > 0) m_nContours = n;
}
......@@ -162,12 +168,29 @@ void ViewField::PlotProfileWeightingField(const std::string& label,
ViewField::Parameter ViewField::GetPar(const std::string& option,
std::string& title) const {
std::string& title, bool& bfield) const {
bfield = false;
std::string opt;
std::transform(option.begin(), option.end(),
std::back_inserter(opt), toupper);
if (opt == "V" || opt == "P" || opt == "PHI" ||
if (opt == "BMAG") {
title = "field";
bfield = true;
return Parameter::Bmag;
} else if (opt == "BX") {
title = "field (x-component)";
bfield = true;
return Parameter::Bx;
} else if (opt == "BY") {
title = "field (y-component)";
bfield = true;
return Parameter::By;
} else if (opt == "BZ") {
title = "field (z-component)";
bfield = true;
return Parameter::Bz;
} else if (opt == "V" || opt == "P" || opt == "PHI" ||
opt.find("VOLT") != std::string::npos ||
opt.find("POT") != std::string::npos) {
title = "potential";
......@@ -175,7 +198,7 @@ ViewField::Parameter ViewField::GetPar(const std::string& option,
} else if (opt == "E" || opt == "FIELD" || opt == "NORM" ||
opt.find("MAG") != std::string::npos) {
title = "field";
return Parameter::Magnitude;
return Parameter::Emag;
} else if (opt.find("X") != std::string::npos) {
title = "field (x-component)";
return Parameter::Ex;
......@@ -205,14 +228,16 @@ void ViewField::Draw2d(const std::string& option, const bool contour,
// Determine the quantity to be plotted.
std::string title;
const Parameter par = GetPar(option, title);
bool bfield = false;
const Parameter par = GetPar(option, title, bfield);
auto eval = [this, par, wfield, electrode](double* u, double* /*p*/) {
auto eval = [this, par, wfield, bfield, electrode](double* u, double* /*p*/) {
// Transform to global coordinates.
const double x = m_proj[0][0] * u[0] + m_proj[1][0] * u[1] + m_proj[2][0];
const double y = m_proj[0][1] * u[0] + m_proj[1][1] * u[1] + m_proj[2][1];
const double z = m_proj[0][2] * u[0] + m_proj[1][2] * u[1] + m_proj[2][2];
return wfield ? Wfield(x, y, z, par, electrode) : Field(x, y, z, par);
return wfield ? Wfield(x, y, z, par, electrode) :
bfield ? Bfield(x, y, z, par) : Efield(x, y, z, par);
};
const std::string fname = FindUnusedFunctionName("f2D");
TF2 f2(fname.c_str(), eval, m_xMinPlot, m_xMaxPlot, m_yMinPlot, m_yMaxPlot, 0);
......@@ -239,6 +264,19 @@ void ViewField::Draw2d(const std::string& option, const bool contour,
zmin = m_wmin;
zmax = m_wmax;
}
} else if (bfield) {
if (contour) {
title = "Contours of the magnetic " + title;
} else {
title = "Magnetic " + title;
}
if (m_useAutoRange) {
SampleRange(m_xMinPlot, m_yMinPlot, m_xMaxPlot, m_yMaxPlot,
&f2, zmin, zmax);
} else {
zmin = m_bmin;
zmax = m_bmax;
}
} else {
if (contour) {
title = "Contours of the electric " + title;
......@@ -335,7 +373,8 @@ void ViewField::DrawProfile(const double x0, const double y0, const double z0,
// Determine the quantity to be plotted.
std::string title;
const Parameter par = GetPar(option, title);
bool bfield = false;
const Parameter par = GetPar(option, title, bfield);
double t0 = 0.;
double t1 = 1.;
......@@ -359,7 +398,7 @@ void ViewField::DrawProfile(const double x0, const double y0, const double z0,
dz /= t1;
}
auto eval = [this, par, wfield, electrode, dir,
auto eval = [this, par, wfield, bfield, electrode, dir,
x0, y0, z0, dx, dy, dz](double* u, double* /*p*/) {
// Get the position.
const double t = u[0];
......@@ -371,7 +410,8 @@ void ViewField::DrawProfile(const double x0, const double y0, const double z0,
y += t * dy;
z += t * dz;
}
return wfield ? Wfield(x, y, z, par, electrode) : Field(x, y, z, par);
return wfield ? Wfield(x, y, z, par, electrode) :
bfield ? Bfield(x, y, z, par) : Efield(x, y, z, par);
};
const std::string fname = FindUnusedFunctionName("fProfile");
......@@ -396,6 +436,14 @@ void ViewField::DrawProfile(const double x0, const double y0, const double z0,
fmax = m_wmax;
}
}
} else if (bfield) {
title = "magnetic " + title;
if (m_useAutoRange) {
SampleRange(&f1, fmin, fmax);
} else {
fmin = m_bmin;
fmax = m_bmax;
}
} else {
title = "electric " + title;
if (par == Parameter::Potential) {
......@@ -435,7 +483,17 @@ void ViewField::DrawProfile(const double x0, const double y0, const double z0,
} else if (!normalised) {
labels = ";distance [cm];";
}
if (par == Parameter::Potential) {
if (bfield) {
labels += "#it{B}";
if (par == Parameter::Bx) {
labels += "_{x}";
} else if (par == Parameter::By) {
labels += "_{y}";
} else if (par == Parameter::Bz) {
labels += "_{z}";
}
labels += " [T]";
} else if (par == Parameter::Potential) {
labels += "#phi";
if (wfield) {
labels += "_w";
......@@ -446,8 +504,8 @@ void ViewField::DrawProfile(const double x0, const double y0, const double z0,
labels += "#it{E}";
if (wfield) {
labels += "_{w";
if (par != Parameter::Magnitude) labels += ",";
} else if (par != Parameter::Magnitude) {
if (par != Parameter::Emag) labels += ",";
} else if (par != Parameter::Emag) {
labels += "_{";
}
if (par == Parameter::Ex) {
......@@ -457,7 +515,7 @@ void ViewField::DrawProfile(const double x0, const double y0, const double z0,
} else if (par == Parameter::Ez) {
labels += "z";
}
if (wfield || par != Parameter::Magnitude) labels += "}";
if (wfield || par != Parameter::Emag) labels += "}";
if (wfield) {
labels += " [1/cm]";
} else {
......@@ -505,8 +563,8 @@ bool ViewField::SetPlotLimits() {
return ok;
}
double ViewField::Field(const double x, const double y, const double z,
const Parameter par) const {
double ViewField::Efield(const double x, const double y, const double z,
const Parameter par) const {
// Compute the field.
double ex = 0., ey = 0., ez = 0., volt = 0.;
......@@ -521,7 +579,7 @@ double ViewField::Field(const double x, const double y, const double z,
switch (par) {
case Parameter::Potential:
return volt;
case Parameter::Magnitude:
case Parameter::Emag:
return sqrt(ex * ex + ey * ey + ez * ez);
case Parameter::Ex:
return ex;
......@@ -557,7 +615,7 @@ double ViewField::Wfield(const double x, const double y, const double z,
}
switch (par) {
case Parameter::Magnitude:
case Parameter::Emag:
return sqrt(ex * ex + ey * ey + ez * ez);
case Parameter::Ex:
return ex;
......@@ -571,6 +629,33 @@ double ViewField::Wfield(const double x, const double y, const double z,
return 0.;
}
double ViewField::Bfield(const double x, const double y, const double z,
const Parameter par) const {
// Compute the field.
double bx = 0., by = 0., bz = 0.;
int status = 0;
if (!m_sensor) {
m_component->MagneticField(x, y, z, bx, by, bz, status);
} else {
m_sensor->MagneticField(x, y, z, bx, by, bz, status);
}
if (m_useStatus && status != 0) return 0.;
switch (par) {
case Parameter::Bmag:
return sqrt(bx * bx + by * by + bz * bz);
case Parameter::Bx:
return bx;
case Parameter::By:
return by;
case Parameter::Bz:
return bz;
default:
break;
}
return 0.;
}
void ViewField::PlotFieldLines(const std::vector<double>& x0,
const std::vector<double>& y0,
const std::vector<double>& z0,
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment