3#include <TInterpreter.h>
10void RemoveSpecialCharacters(std::string& str) {
12 str.erase(std::remove_if(str.begin(), str.end(),
13 [](
char c) { return std::isspace(c) || !std::isalnum(c); }),
17void* MakeFieldFunction(
const std::string& fname,
18 const std::string& expression,
19 const bool wfield =
false,
20 const bool bfield =
false,
21 const bool timeDependent =
false) {
22 std::string code =
"std::function<void("
23 "const double, const double, const double, ";
24 if (timeDependent) code +=
"const double, ";
25 code +=
"double&, double&, double&)> ";
26 code += fname +
" = [](const double x, const double y, const double z, ";
27 if (timeDependent) code +=
"const double t, ";
28 if (wfield && (expression.find(
"wx") != std::string::npos ||
29 expression.find(
"wy") != std::string::npos ||
30 expression.find(
"wz") != std::string::npos)) {
31 code +=
"double& wx, double& wy, double& wz) {";
32 code +=
"wx = wy = wz = 0.;";
34 code +=
"double& bx, double& by, double& bz) {";
35 code +=
"bx = by = bz = 0.;";
37 code +=
"double& ex, double& ey, double& ez) {";
38 code +=
"ex = ey = ez = 0.;";
40 code += expression +
";};";
43 TInterpreter::EErrorCode ecode;
44 gInterpreter->ProcessLine(code.c_str(), &ecode);
46 return (
void*)gInterpreter->ProcessLine(code.c_str());
49void* MakePotentialFunction(
const std::string& fname,
50 const std::string& expression,
51 const bool timeDependent =
false) {
52 std::string code =
"std::function<double("
53 "const double, const double, const double";
54 if (timeDependent) code +=
", const double";
56 code += fname +
" = [](const double x, const double y, const double z";
57 if (timeDependent) code +=
", const double t";
59 if (expression.find(
"return") == std::string::npos) code +=
"return ";
60 code += expression +
";};";
63 TInterpreter::EErrorCode ecode;
64 gInterpreter->ProcessLine(code.c_str(), &ecode);
66 return (
void*)gInterpreter->ProcessLine(code.c_str());
76 const double z,
double& ex,
double& ey,
77 double& ez,
Medium*& m,
int& status) {
85 m_efield(x, y, z, ex, ey, ez);
89 std::cerr <<
m_className <<
"::ElectricField:\n (" << x <<
", " << y
90 <<
", " << z <<
") is not inside a medium.\n";
100 const double z,
double& ex,
double& ey,
101 double& ez,
double& v,
Medium*& m,
104 ex = ey = ez = v = 0.;
109 m_efield(x, y, z, ex, ey, ez);
111 v = m_epot ? m_epot(x, y, z) : 0.;
115 std::cerr <<
m_className <<
"::ElectricField:\n (" << x <<
", " << y
116 <<
", " << z <<
") is not inside a medium.\n";
131 const double z,
double& bx,
double& by,
132 double& bz,
int& status) {
137 m_bfield(x, y, z, bx, by, bz);
142 const double z,
double& wx,
double& wy,
143 double& wz,
const std::string& label) {
145 if (m_wfield.count(label) > 0) {
146 m_wfield[label](x, y, z, wx, wy, wz);
152 const std::string& label) {
154 if (m_wpot.count(label) > 0) v = m_wpot[label](x, y, z);
159 const double z,
const double t,
160 double& wx,
double& wy,
double& wz,
161 const std::string& label) {
163 if (m_dwfield.count(label) > 0) {
164 m_dwfield[label](x, y, z, t, wx, wy, wz);
169 const double x,
const double y,
const double z,
const double t,
170 const std::string& label) {
173 if (m_dwpot.count(label) > 0) v = m_dwpot[label](x, y, z, t);
178 double& xmin,
double& ymin,
double& zmin,
179 double& xmax,
double& ymax,
double& zmax) {
198 std::function<
void(
const double,
const double,
const double,
199 double&,
double&,
double&)> f) {
201 std::cerr <<
m_className <<
"::SetElectricField: Function is empty.\n";
209 const std::string fname =
"fComponentUserEfield";
210 auto fPtr = MakeFieldFunction(fname, expression);
213 <<
"Could not convert the expression.\n";
216 typedef std::function<void(
const double,
const double,
const double,
217 double&,
double&,
double&)> Fcn;
218 Fcn& f = *((Fcn *) fPtr);
224 std::function<
double(
const double,
const double,
const double)> f) {
226 std::cerr <<
m_className <<
"::SetPotential: Function is empty.\n";
233 const std::string fname =
"fComponentUserEpot";
234 auto fPtr = MakePotentialFunction(fname, expression);
237 <<
"Could not convert the expression.\n";
240 typedef std::function<double(
const double,
const double,
const double)> Fcn;
241 Fcn& f = *((Fcn *) fPtr);
246 std::function<
void(
const double,
const double,
const double,
247 double&,
double&,
double&)> f,
248 const std::string& label) {
250 std::cerr <<
m_className <<
"::SetWeightingField: Function is empty.\n";
257 const std::string& label) {
258 std::string fname = label;
259 RemoveSpecialCharacters(fname);
260 fname =
"fComponentUserWfield" + fname;
261 auto fPtr = MakeFieldFunction(fname, expression,
true);
263 std::cerr <<
m_className <<
"::SetWeightingField: "
264 <<
"Could not convert the expression.\n";
267 typedef std::function<void(
const double,
const double,
const double,
268 double&,
double&,
double&)> Fcn;
269 Fcn& f = *((Fcn *) fPtr);
274 std::function<
double(
const double,
const double,
const double)> f,
275 const std::string& label) {
277 std::cerr <<
m_className <<
"::SetWeightingPotential: Function is empty.\n";
284 const std::string& label) {
285 std::string fname = label;
286 RemoveSpecialCharacters(fname);
287 fname =
"fComponentUserWpot" + fname;
288 auto fPtr = MakePotentialFunction(fname, expression);
290 std::cerr <<
m_className <<
"::SetWeightingPotential: "
291 <<
"Could not convert the expression.\n";
294 typedef std::function<double(
const double,
const double,
const double)> Fcn;
295 Fcn& f = *((Fcn *) fPtr);
300 std::function<
void(
const double,
const double,
const double,
const double,
301 double&,
double&,
double&)> f,
302 const std::string& label) {
305 std::cerr <<
m_className <<
"::SetDelayedWeightingField: "
306 <<
"Function is empty.\n";
309 m_dwfield[label] = f;
313 const std::string& label) {
315 std::string fname = label;
316 RemoveSpecialCharacters(fname);
317 fname =
"fComponentUserDWfield" + fname;
318 auto fPtr = MakeFieldFunction(fname, expression,
true,
false,
true);
320 std::cerr <<
m_className <<
"::SetDelayedWeightingField: "
321 <<
"Could not convert the expression.\n";
324 typedef std::function<void(
const double,
const double,
const double,
325 const double,
double&,
double&,
double&)> Fcn;
326 Fcn& f = *((Fcn *) fPtr);
327 m_dwfield[label] = f;
331 std::function<
double(
const double,
const double,
const double,
333 const std::string& label) {
335 std::cerr <<
m_className <<
"::SetDelayedWeightingPotential: "
336 <<
"Function is empty.\n";
343 const std::string& expression,
const std::string& label) {
344 std::string fname = label;
345 RemoveSpecialCharacters(fname);
346 fname =
"fComponentUserDWpot" + fname;
347 auto fPtr = MakePotentialFunction(fname, expression,
true);
349 std::cerr <<
m_className <<
"::SetDelayedWeightingPotential: "
350 <<
"Could not convert the expression.\n";
353 typedef std::function<double(
const double,
const double,
const double,
355 Fcn& f = *((Fcn *) fPtr);
360 std::function<
void(
const double,
const double,
const double,
361 double&,
double&,
double&)> f) {
363 std::cerr <<
m_className <<
"::SetMagneticField: Function is empty.\n";
371 const std::string fname =
"fComponentUserBfield";
372 auto fPtr = MakeFieldFunction(fname, expression,
false,
true);
375 <<
"Could not convert the expression.\n";
378 typedef std::function<void(
const double,
const double,
const double,
379 double&,
double&,
double&)> Fcn;
380 Fcn& f = *((Fcn *) fPtr);
385 const double xmin,
const double ymin,
const double zmin,
386 const double xmax,
const double ymax,
const double zmax) {
388 m_xmin[0] = std::min(xmin, xmax);
389 m_xmin[1] = std::min(ymin, ymax);
390 m_xmin[2] = std::min(zmin, zmax);
391 m_xmax[0] = std::max(xmin, xmax);
392 m_xmax[1] = std::max(ymin, ymax);
393 m_xmax[2] = std::max(zmin, zmax);
403void ComponentUser::Reset() {
416void ComponentUser::UpdatePeriodicity() {
418 std::cerr <<
m_className <<
"::UpdatePeriodicity:\n"
419 <<
" Periodicities are not supported.\n";
void DelayedWeightingField(const double x, const double y, const double z, const double t, double &wx, double &wy, double &wz, const std::string &label) override
void SetDelayedWeightingPotential(std::function< double(const double, const double, const double, const double)>, const std::string &label)
double WeightingPotential(const double x, const double y, const double z, const std::string &label) override
bool GetBoundingBox(double &xmin, double &ymin, double &zmin, double &xmax, double &ymax, double &zmax) override
Get the bounding box coordinates.
void SetDelayedWeightingField(std::function< void(const double, const double, const double, const double, double &, double &, double &)>, const std::string &label)
Set the function to be called for calculating the delayed weighting field.
double DelayedWeightingPotential(const double x, const double y, const double z, const double t, const std::string &label) override
void UnsetArea()
Remove the explicit limits of the active area.
void SetElectricField(std::function< void(const double, const double, const double, double &, double &, double &)>)
Set the function to be called for calculating the electric field.
void WeightingField(const double x, const double y, const double z, double &wx, double &wy, double &wz, const std::string &label) override
ComponentUser()
Constructor.
void MagneticField(const double x, const double y, const double z, double &bx, double &by, double &bz, int &status) override
void SetWeightingPotential(std::function< double(const double, const double, const double)>, const std::string &label)
Set the function to be called for calculating the weighting potential.
void SetPotential(std::function< double(const double, const double, const double)>)
Set the function to be called for calculating the electric potential.
Medium * GetMedium(const double x, const double y, const double z) override
Get the medium at a given location (x, y, z).
void SetArea(const double xmin, const double ymin, const double zmin, const double xmax, const double ymax, const double zmax)
bool GetVoltageRange(double &vmin, double &vmax) override
Calculate the voltage range [V].
bool HasMagneticField() const override
Does the component have a non-zero magnetic field?
void SetWeightingField(std::function< void(const double, const double, const double, double &, double &, double &)>, const std::string &label)
Set the function to be called for calculating the weighting field.
void ElectricField(const double x, const double y, const double z, double &ex, double &ey, double &ez, Medium *&m, int &status) override
void SetMagneticField(std::function< void(const double, const double, const double, double &, double &, double &)>)
Set the function to be called for calculating the magnetic field.
virtual bool GetBoundingBox(double &xmin, double &ymin, double &zmin, double &xmax, double &ymax, double &zmax)
Get the bounding box coordinates.
bool m_debug
Switch on/off debugging messages.
Component()=delete
Default constructor.
virtual bool HasMagneticField() const
Does the component have a non-zero magnetic field?
std::string m_className
Class name.
virtual void MagneticField(const double x, const double y, const double z, double &bx, double &by, double &bz, int &status)
bool m_ready
Ready for use?
Abstract base class for media.
bool IsDriftable() const
Is charge carrier transport enabled in this medium?