Garfield++ v2r0
A toolkit for the detailed simulation of particle detectors based on ionisation measurement in gases and semiconductors
Loading...
Searching...
No Matches
Garfield::ComponentAnalyticField Class Reference

#include <ComponentAnalyticField.hh>

+ Inheritance diagram for Garfield::ComponentAnalyticField:

Public Types

enum  Cell {
  A00 , B1X , B1Y , B2X ,
  B2Y , C10 , C2X , C2Y ,
  C30 , D10 , D20 , D30 ,
  D40 , Unknown
}
 

Public Member Functions

 ComponentAnalyticField ()
 Constructor.
 
 ~ComponentAnalyticField ()
 Destructor.
 
void ElectricField (const double x, const double y, const double z, double &ex, double &ey, double &ez, Medium *&m, int &status)
 
void ElectricField (const double x, const double y, const double z, double &ex, double &ey, double &ez, double &v, Medium *&m, int &status)
 
bool GetVoltageRange (double &pmin, double &pmax)
 Calculate the voltage range [V].
 
void WeightingField (const double x, const double y, const double z, double &wx, double &wy, double &wz, const std::string &label)
 
double WeightingPotential (const double x, const double y, const double z, const std::string &label)
 
bool GetBoundingBox (double &x0, double &y0, double &z0, double &x1, double &y1, double &z1)
 Get the bounding box coordinates.
 
bool IsWireCrossed (const double x0, const double y0, const double z0, const double x1, const double y1, const double z1, double &xc, double &yc, double &zc)
 
bool IsInTrapRadius (const double q0, const double x0, const double y0, const double z0, double &xw, double &yx, double &rw)
 
void AddWire (const double x, const double y, const double diameter, const double voltage, const std::string &label, const double length=100., const double tension=50., const double rho=19.3, const int ntrap=5)
 Add a wire at (x, y) .
 
void AddTube (const double radius, const double voltage, const int nEdges, const std::string &label)
 Add a tube.
 
void AddPlaneX (const double x, const double voltage, const std::string &label)
 Add a plane at constant x.
 
void AddPlaneY (const double y, const double voltage, const std::string &label)
 Add a plane at constant y.
 
void AddStripOnPlaneX (const char direction, const double x, const double smin, const double smax, const std::string &label, const double gap=-1.)
 
void AddStripOnPlaneY (const char direction, const double y, const double smin, const double smax, const std::string &label, const double gap=-1.)
 
void AddPixelOnPlaneX (const double x, const double ymin, const double ymax, const double zmin, const double zmax, const std::string &label, const double gap=-1.)
 
void AddPixelOnPlaneY (const double y, const double xmin, const double xmax, const double zmin, const double zmax, const std::string &label, const double gap=-1.)
 
void SetPeriodicityX (const double s)
 Set the periodic length [cm] in the x-direction.
 
void SetPeriodicityY (const double s)
 Set the periodic length [cm] in the y-direction.
 
bool GetPeriodicityX (double &s)
 
bool GetPeriodicityY (double &s)
 
void AddCharge (const double x, const double y, const double z, const double q)
 Add a point charge.
 
void ClearCharges ()
 
void PrintCharges () const
 
std::string GetCellType ()
 
void AddReadout (const std::string &label)
 Setup the weighting field for a given group of wires or planes.
 
void EnableChargeCheck (const bool on=true)
 
void DisableChargeCheck ()
 
unsigned int GetNumberOfWires () const
 
bool GetWire (const unsigned int i, double &x, double &y, double &diameter, double &voltage, std::string &label, double &length, double &charge, int &ntrap) const
 
unsigned int GetNumberOfPlanesX () const
 
unsigned int GetNumberOfPlanesY () const
 
bool GetPlaneX (const unsigned int i, double &x, double &voltage, std::string &label) const
 
bool GetPlaneY (const unsigned int i, double &y, double &voltage, std::string &label) const
 
bool GetTube (double &r, double &voltage, int &nEdges, std::string &label) const
 
- Public Member Functions inherited from Garfield::ComponentBase
 ComponentBase ()
 Constructor.
 
virtual ~ComponentBase ()
 Destructor.
 
virtual void SetGeometry (GeometryBase *geo)
 Define the geometry.
 
virtual void Clear ()
 Reset.
 
virtual MediumGetMedium (const double x, const double y, const double z)
 Get the medium at a given location (x, y, z).
 
virtual void ElectricField (const double x, const double y, const double z, double &ex, double &ey, double &ez, Medium *&m, int &status)=0
 
virtual void ElectricField (const double x, const double y, const double z, double &ex, double &ey, double &ez, double &v, Medium *&m, int &status)=0
 
virtual bool GetVoltageRange (double &vmin, double &vmax)=0
 Calculate the voltage range [V].
 
virtual void WeightingField (const double x, const double y, const double z, double &wx, double &wy, double &wz, const std::string &label)
 
virtual double WeightingPotential (const double x, const double y, const double z, const std::string &label)
 
virtual void MagneticField (const double x, const double y, const double z, double &bx, double &by, double &bz, int &status)
 
void SetMagneticField (const double bx, const double by, const double bz)
 Set a constant magnetic field.
 
virtual bool IsReady ()
 Ready for use?
 
virtual bool GetBoundingBox (double &xmin, double &ymin, double &zmin, double &xmax, double &ymax, double &zmax)
 Get the bounding box coordinates.
 
virtual bool IsWireCrossed (const double x0, const double y0, const double z0, const double x1, const double y1, const double z1, double &xc, double &yc, double &zc)
 
virtual bool IsInTrapRadius (const double q0, const double x0, const double y0, const double z0, double &xw, double &yw, double &rw)
 
void EnablePeriodicityX (const bool on=true)
 Enable simple periodicity in the $x$ direction.
 
void DisablePeriodicityX ()
 
void EnablePeriodicityY (const bool on=true)
 Enable simple periodicity in the $y$ direction.
 
void DisablePeriodicityY ()
 
void EnablePeriodicityZ (const bool on=true)
 Enable simple periodicity in the $z$ direction.
 
void DisablePeriodicityZ ()
 
void EnableMirrorPeriodicityX (const bool on=true)
 Enable mirror periodicity in the $x$ direction.
 
void DisableMirrorPeriodicityX ()
 
void EnableMirrorPeriodicityY (const bool on=true)
 Enable mirror periodicity in the $y$ direction.
 
void DisableMirrorPeriodicityY ()
 
void EnableMirrorPeriodicityZ (const bool on=true)
 Enable mirror periodicity in the $y$ direction.
 
void DisableMirrorPeriodicityZ ()
 
void EnableAxialPeriodicityX (const bool on=true)
 Enable axial periodicity in the $x$ direction.
 
void DisableAxialPeriodicityX ()
 
void EnableAxialPeriodicityY (const bool on=true)
 Enable axial periodicity in the $y$ direction.
 
void DisableAxialPeriodicityY ()
 
void EnableAxialPeriodicityZ (const bool on=true)
 Enable axial periodicity in the $z$ direction.
 
void DisableAxialPeriodicityZ ()
 
void EnableRotationSymmetryX (const bool on=true)
 Enable rotation symmetry around the $x$ axis.
 
void DisableRotationSymmetryX ()
 
void EnableRotationSymmetryY (const bool on=true)
 Enable rotation symmetry around the $y$ axis.
 
void DisableRotationSymmetryY ()
 
void EnableRotationSymmetryZ (const bool on=true)
 Enable rotation symmetry around the $z$ axis.
 
void DisableRotationSymmetryZ ()
 
void EnableDebugging ()
 Switch on debugging messages.
 
void DisableDebugging ()
 Switch off debugging messages.
 
void ActivateTraps ()
 Request trapping to be taken care of by the component (for TCAD).
 
void DeactivateTraps ()
 
bool IsTrapActive ()
 
void ActivateVelocityMap ()
 Request velocity to be taken care of by the component (for TCAD).
 
void DectivateVelocityMap ()
 
bool IsVelocityActive ()
 
virtual bool ElectronAttachment (const double, const double, const double, double &eta)
 Get the electron attachment coefficient.
 
virtual bool HoleAttachment (const double, const double, const double, double &eta)
 Get the hole attachment coefficient.
 
virtual void ElectronVelocity (const double, const double, const double, double &vx, double &vy, double &vz, Medium *&, int &status)
 Get the electron drift velocity.
 
virtual void HoleVelocity (const double, const double, const double, double &vx, double &vy, double &vz, Medium *&, int &status)
 Get the hole drift velocity.
 
virtual bool GetElectronLifetime (const double, const double, const double, double &etau)
 
virtual bool GetHoleLifetime (const double, const double, const double, double &htau)
 

Additional Inherited Members

virtual void Reset ()=0
 Geometry checks.
 
virtual void UpdatePeriodicity ()=0
 Verify periodicities.
 
- Protected Attributes inherited from Garfield::ComponentBase
std::string m_className
 Class name.
 
GeometryBasem_geometry
 Pointer to the geometry.
 
bool m_ready
 Ready for use?
 
bool m_activeTraps
 Does the component have traps?
 
bool m_hasVelocityMap
 Does the component have velocity maps?
 
bool m_xPeriodic
 Simple periodicity in x.
 
bool m_yPeriodic
 Simple periodicity in y.
 
bool m_zPeriodic
 Simple periodicity in z.
 
bool m_xMirrorPeriodic
 Mirror periodicity in x.
 
bool m_yMirrorPeriodic
 Mirror periodicity in y.
 
bool m_zMirrorPeriodic
 Mirror periodicity in z.
 
bool m_xAxiallyPeriodic
 Axial periodicity in x.
 
bool m_yAxiallyPeriodic
 Axial periodicity in y.
 
bool m_zAxiallyPeriodic
 Axial periodicity in z.
 
bool m_xRotationSymmetry
 Rotation symmetry around x-axis.
 
bool m_yRotationSymmetry
 Rotation symmetry around y-axis.
 
bool m_zRotationSymmetry
 Rotation symmetry around z-axis.
 
double m_bx0
 
double m_by0
 
double m_bz0
 
bool m_debug
 Switch on/off debugging messages.
 

Detailed Description

Semi-analytic calculation of two-dimensional configurations consisting of wires, planes, and tubes.

Definition at line 15 of file ComponentAnalyticField.hh.

Member Enumeration Documentation

◆ Cell

Constructor & Destructor Documentation

◆ ComponentAnalyticField()

Garfield::ComponentAnalyticField::ComponentAnalyticField ( )

Constructor.

Definition at line 12 of file ComponentAnalyticField.cc.

12 {
13
14 m_className = "ComponentAnalyticField";
15 m_chargeCheck = false;
16 CellInit();
17}
std::string m_className
Class name.

◆ ~ComponentAnalyticField()

Garfield::ComponentAnalyticField::~ComponentAnalyticField ( )
inline

Destructor.

Definition at line 21 of file ComponentAnalyticField.hh.

21{}

Member Function Documentation

◆ AddCharge()

void Garfield::ComponentAnalyticField::AddCharge ( const double  x,
const double  y,
const double  z,
const double  q 
)

Add a point charge.

Definition at line 637 of file ComponentAnalyticField.cc.

638 {
639
640 // Convert from fC to internal units (division by 4 pi epsilon0).
641 charge3d newCharge;
642 newCharge.x = x;
643 newCharge.y = y;
644 newCharge.z = z;
645 newCharge.e = q / FourPiEpsilon0;
646 m_ch3d.push_back(newCharge);
647}

◆ AddPixelOnPlaneX()

void Garfield::ComponentAnalyticField::AddPixelOnPlaneX ( const double  x,
const double  ymin,
const double  ymax,
const double  zmin,
const double  zmax,
const std::string &  label,
const double  gap = -1. 
)

Definition at line 454 of file ComponentAnalyticField.cc.

456 {
457
458 if (!m_ynplan[0] && !m_ynplan[1]) {
459 std::cerr << m_className << "::AddPixelOnPlaneX:\n";
460 std::cerr << " There are no planes at constant x defined.\n";
461 return;
462 }
463
464 if (fabs(ymax - ymin) < Small || fabs(zmax - zmin) < Small) {
465 std::cerr << m_className << "::AddSPixelOnPlaneX:\n";
466 std::cerr << " Pixel width must be greater than zero.\n";
467 return;
468 }
469
470 pixel newPixel;
471 newPixel.type = label;
472 newPixel.ind = -1;
473 newPixel.smin = std::min(ymin, ymax);
474 newPixel.smax = std::max(ymin, ymax);
475 newPixel.zmin = std::min(zmin, zmax);
476 newPixel.zmax = std::max(zmin, zmax);
477 if (gap > Small) {
478 newPixel.gap = gap;
479 } else {
480 newPixel.gap = -1.;
481 }
482
483 int iplane = 0;
484 if (m_ynplan[1]) {
485 const double d0 = fabs(m_coplan[0] - x);
486 const double d1 = fabs(m_coplan[1] - x);
487 if (d1 < d0) iplane = 1;
488 }
489
490 planes[iplane].pixels.push_back(newPixel);
491}
DoubleAc fabs(const DoubleAc &f)
Definition: DoubleAc.h:615

◆ AddPixelOnPlaneY()

void Garfield::ComponentAnalyticField::AddPixelOnPlaneY ( const double  y,
const double  xmin,
const double  xmax,
const double  zmin,
const double  zmax,
const std::string &  label,
const double  gap = -1. 
)

Definition at line 493 of file ComponentAnalyticField.cc.

495 {
496
497 if (!m_ynplan[2] && !m_ynplan[3]) {
498 std::cerr << m_className << "::AddPixelOnPlaneY:\n";
499 std::cerr << " There are no planes at constant y defined.\n";
500 return;
501 }
502
503 if (fabs(xmax - xmin) < Small || fabs(zmax - zmin) < Small) {
504 std::cerr << m_className << "::AddPixelOnPlaneY:\n";
505 std::cerr << " Pixel width must be greater than zero.\n";
506 return;
507 }
508
509 pixel newPixel;
510 newPixel.type = label;
511 newPixel.ind = -1;
512 newPixel.smin = std::min(xmin, xmax);
513 newPixel.smax = std::max(xmin, xmax);
514 newPixel.zmin = std::min(zmin, zmax);
515 newPixel.zmax = std::max(zmin, zmax);
516 if (gap > Small) {
517 newPixel.gap = gap;
518 } else {
519 newPixel.gap = -1.;
520 }
521
522 int iplane = 2;
523 if (m_ynplan[3]) {
524 const double d0 = fabs(m_coplan[2] - y);
525 const double d1 = fabs(m_coplan[3] - y);
526 if (d1 < d0) iplane = 3;
527 }
528
529 planes[iplane].pixels.push_back(newPixel);
530}

◆ AddPlaneX()

void Garfield::ComponentAnalyticField::AddPlaneX ( const double  x,
const double  voltage,
const std::string &  label 
)

Add a plane at constant x.

Definition at line 296 of file ComponentAnalyticField.cc.

297 {
298
299 if (m_ynplan[0] && m_ynplan[1]) {
300 std::cerr << m_className << "::AddPlaneX:\n";
301 std::cerr << " There are already two x planes defined.\n";
302 return;
303 }
304
305 if (m_ynplan[0]) {
306 m_ynplan[1] = true;
307 m_coplan[1] = x;
308 m_vtplan[1] = v;
309 planes[1].type = lab;
310 planes[1].ind = -1;
311 } else {
312 m_ynplan[0] = true;
313 m_coplan[0] = x;
314 m_vtplan[0] = v;
315 planes[0].type = lab;
316 planes[0].ind = -1;
317 }
318
319 // Force recalculation of the capacitance and signal matrices.
320 m_cellset = false;
321 m_sigset = false;
322}

◆ AddPlaneY()

void Garfield::ComponentAnalyticField::AddPlaneY ( const double  y,
const double  voltage,
const std::string &  label 
)

Add a plane at constant y.

Definition at line 324 of file ComponentAnalyticField.cc.

325 {
326
327 if (m_ynplan[2] && m_ynplan[3]) {
328 std::cerr << m_className << "::AddPlaneY:\n";
329 std::cerr << " There are already two y planes defined.\n";
330 return;
331 }
332
333 if (m_ynplan[2]) {
334 m_ynplan[3] = true;
335 m_coplan[3] = y;
336 m_vtplan[3] = v;
337 planes[3].type = lab;
338 planes[3].ind = -1;
339 } else {
340 m_ynplan[2] = true;
341 m_coplan[2] = y;
342 m_vtplan[2] = v;
343 planes[2].type = lab;
344 planes[2].ind = -1;
345 }
346
347 // Force recalculation of the capacitance and signal matrices.
348 m_cellset = false;
349 m_sigset = false;
350}

◆ AddReadout()

void Garfield::ComponentAnalyticField::AddReadout ( const std::string &  label)

Setup the weighting field for a given group of wires or planes.

Definition at line 1913 of file ComponentAnalyticField.cc.

1913 {
1914
1915 // Check if this readout group already exists.
1916 if (std::find(m_readout.begin(), m_readout.end(), label) != m_readout.end()) {
1917 std::cout << m_className << "::AddReadout:\n";
1918 std::cout << " Readout group " << label << " already exists.\n";
1919 return;
1920 }
1921 m_readout.push_back(label);
1922
1923 unsigned int nWiresFound = 0;
1924 for (unsigned int i = 0; i < m_nWires; ++i) {
1925 if (m_w[i].type == label) ++nWiresFound;
1926 }
1927
1928 unsigned int nPlanesFound = 0;
1929 unsigned int nStripsFound = 0;
1930 unsigned int nPixelsFound = 0;
1931 for (int i = 0; i < 5; ++i) {
1932 if (planes[i].type == label) ++nPlanesFound;
1933 const unsigned int nStrips1 = planes[i].strips1.size();
1934 for (unsigned int j = 0; j < nStrips1; ++j) {
1935 if (planes[i].strips1[j].type == label) ++nStripsFound;
1936 }
1937 const unsigned int nStrips2 = planes[i].strips2.size();
1938 for (unsigned int j = 0; j < nStrips2; ++j) {
1939 if (planes[i].strips2[j].type == label) ++nStripsFound;
1940 }
1941 const unsigned int nPixels = planes[i].pixels.size();
1942 for (unsigned int j = 0; j < nPixels; ++j) {
1943 if (planes[i].pixels[j].type == label) ++nPixelsFound;
1944 }
1945 }
1946
1947 if (nWiresFound == 0 && nPlanesFound == 0 && nStripsFound == 0 &&
1948 nPixelsFound == 0) {
1949 std::cerr << m_className << "::AddReadout:\n";
1950 std::cerr << " At present there are no wires, planes or strips\n";
1951 std::cerr << " associated to readout group " << label << ".\n";
1952 } else {
1953 std::cout << m_className << "::AddReadout:\n";
1954 std::cout << " Readout group " << label << " comprises:\n";
1955 if (nWiresFound > 1) {
1956 std::cout << " " << nWiresFound << " wires\n";
1957 } else if (nWiresFound == 1) {
1958 std::cout << " 1 wire\n";
1959 }
1960 if (nPlanesFound > 1) {
1961 std::cout << " " << nPlanesFound << " planes\n";
1962 } else if (nPlanesFound == 1) {
1963 std::cout << " 1 plane\n";
1964 }
1965 if (nStripsFound > 1) {
1966 std::cout << " " << nStripsFound << " strips\n";
1967 } else if (nStripsFound == 1) {
1968 std::cout << " 1 strip\n";
1969 }
1970 if (nPixelsFound > 1) {
1971 std::cout << " " << nPixelsFound << " pixels\n";
1972 } else if (nPixelsFound == 1) {
1973 std::cout << " 1 pixel\n";
1974 }
1975 }
1976
1977 m_sigset = false;
1978}

◆ AddStripOnPlaneX()

void Garfield::ComponentAnalyticField::AddStripOnPlaneX ( const char  direction,
const double  x,
const double  smin,
const double  smax,
const std::string &  label,
const double  gap = -1. 
)

Definition at line 352 of file ComponentAnalyticField.cc.

356 {
357
358 if (!m_ynplan[0] && !m_ynplan[1]) {
359 std::cerr << m_className << "::AddStripOnPlaneX:\n";
360 std::cerr << " There are no planes at constant x defined.\n";
361 return;
362 }
363
364 if (direction != 'y' && direction != 'Y' && direction != 'z' &&
365 direction != 'Z') {
366 std::cerr << m_className << "::AddStripOnPlaneX:\n";
367 std::cerr << " Invalid direction (" << direction << ").\n";
368 std::cerr << " Only strips in y or z direction are possible.\n";
369 return;
370 }
371
372 if (fabs(smax - smin) < Small) {
373 std::cerr << m_className << "::AddStripOnPlaneX:\n";
374 std::cerr << " Strip width must be greater than zero.\n";
375 return;
376 }
377
378 strip newStrip;
379 newStrip.type = label;
380 newStrip.ind = -1;
381 newStrip.smin = std::min(smin, smax);
382 newStrip.smax = std::max(smin, smax);
383 if (gap > Small) {
384 newStrip.gap = gap;
385 } else {
386 newStrip.gap = -1.;
387 }
388
389 int iplane = 0;
390 if (m_ynplan[1]) {
391 const double d0 = fabs(m_coplan[0] - x);
392 const double d1 = fabs(m_coplan[1] - x);
393 if (d1 < d0) iplane = 1;
394 }
395
396 if (direction == 'y' || direction == 'Y') {
397 planes[iplane].strips1.push_back(newStrip);
398 } else {
399 planes[iplane].strips2.push_back(newStrip);
400 }
401}

◆ AddStripOnPlaneY()

void Garfield::ComponentAnalyticField::AddStripOnPlaneY ( const char  direction,
const double  y,
const double  smin,
const double  smax,
const std::string &  label,
const double  gap = -1. 
)

Definition at line 403 of file ComponentAnalyticField.cc.

407 {
408
409 if (!m_ynplan[2] && !m_ynplan[3]) {
410 std::cerr << m_className << "::AddStripOnPlaneY:\n";
411 std::cerr << " There are no planes at constant y defined.\n";
412 return;
413 }
414
415 if (direction != 'x' && direction != 'X' && direction != 'z' &&
416 direction != 'Z') {
417 std::cerr << m_className << "::AddStripOnPlaneY:\n";
418 std::cerr << " Invalid direction (" << direction << ").\n";
419 std::cerr << " Only strips in x or z direction are possible.\n";
420 return;
421 }
422
423 if (fabs(smax - smin) < Small) {
424 std::cerr << m_className << "::AddStripOnPlaneY:\n";
425 std::cerr << " Strip width must be greater than zero.\n";
426 return;
427 }
428
429 strip newStrip;
430 newStrip.type = label;
431 newStrip.ind = -1;
432 newStrip.smin = std::min(smin, smax);
433 newStrip.smax = std::max(smin, smax);
434 if (gap > Small) {
435 newStrip.gap = gap;
436 } else {
437 newStrip.gap = -1.;
438 }
439
440 int iplane = 2;
441 if (m_ynplan[3]) {
442 const double d2 = fabs(m_coplan[2] - y);
443 const double d3 = fabs(m_coplan[3] - y);
444 if (d3 < d2) iplane = 3;
445 }
446
447 if (direction == 'x' || direction == 'X') {
448 planes[iplane].strips1.push_back(newStrip);
449 } else {
450 planes[iplane].strips2.push_back(newStrip);
451 }
452}

◆ AddTube()

void Garfield::ComponentAnalyticField::AddTube ( const double  radius,
const double  voltage,
const int  nEdges,
const std::string &  label 
)

Add a tube.

Definition at line 254 of file ComponentAnalyticField.cc.

256 {
257
258 // Check if the provided parameters make sense.
259 if (radius <= 0.0) {
260 std::cerr << m_className << "::AddTube:\n"
261 << " Unphysical tube dimension.\n";
262 return;
263 }
264
265 if (nEdges < 3 && nEdges != 0) {
266 std::cerr << m_className << "::AddTube:\n"
267 << " Unphysical number of tube edges (" << nEdges << ")\n";
268 return;
269 }
270
271 // If there is already a tube defined, print a warning message.
272 if (m_tube) {
273 std::cout << m_className << "::AddTube:\n"
274 << " Warning: Existing tube settings will be overwritten.\n";
275 }
276
277 // Set the coordinate system.
278 m_tube = true;
279 m_polar = false;
280
281 // Set the tube parameters.
282 m_cotube = radius;
283 m_cotube2 = radius * radius;
284 m_vttube = voltage;
285
286 m_ntube = nEdges;
287
288 planes[4].type = label;
289 planes[4].ind = -1;
290
291 // Force recalculation of the capacitance and signal matrices.
292 m_cellset = false;
293 m_sigset = false;
294}

Referenced by GarfieldPhysics::CreateGeometry().

◆ AddWire()

void Garfield::ComponentAnalyticField::AddWire ( const double  x,
const double  y,
const double  diameter,
const double  voltage,
const std::string &  label,
const double  length = 100.,
const double  tension = 50.,
const double  rho = 19.3,
const int  ntrap = 5 
)

Add a wire at (x, y) .

Definition at line 197 of file ComponentAnalyticField.cc.

202 {
203
204 // Check if the provided parameters make sense.
205 if (diameter <= 0.) {
206 std::cerr << m_className << "::AddWire:\n";
207 std::cerr << " Unphysical wire diameter.\n";
208 return;
209 }
210
211 if (tension <= 0.) {
212 std::cerr << m_className << "::AddWire:\n";
213 std::cerr << " Unphysical wire tension.\n";
214 return;
215 }
216
217 if (rho <= 0.0) {
218 std::cerr << m_className << "::AddWire:\n";
219 std::cerr << " Unphysical wire density.\n";
220 return;
221 }
222
223 if (length <= 0.0) {
224 std::cerr << m_className << "::AddWire:\n";
225 std::cerr << " Unphysical wire length.\n";
226 return;
227 }
228
229 if (ntrap <= 0) {
230 std::cerr << m_className << "::AddWire:\n";
231 std::cerr << " Number of trap radii must be > 0.\n";
232 return;
233 }
234 // Create a new wire
235 wire newWire;
236 newWire.x = x;
237 newWire.y = y;
238 newWire.d = diameter;
239 newWire.v = voltage;
240 newWire.u = length;
241 newWire.type = label;
242 newWire.e = 0.;
243 newWire.ind = -1;
244 newWire.nTrap = ntrap;
245 // Add the wire to the list
246 m_w.push_back(newWire);
247 ++m_nWires;
248
249 // Force recalculation of the capacitance and signal matrices.
250 m_cellset = false;
251 m_sigset = false;
252}

Referenced by GarfieldPhysics::CreateGeometry().

◆ ClearCharges()

void Garfield::ComponentAnalyticField::ClearCharges ( )

Definition at line 649 of file ComponentAnalyticField.cc.

649 {
650
651 m_ch3d.clear();
652 m_nTermBessel = 10;
653 m_nTermPoly = 100;
654}

◆ DisableChargeCheck()

void Garfield::ComponentAnalyticField::DisableChargeCheck ( )
inline

Definition at line 158 of file ComponentAnalyticField.hh.

158{ EnableChargeCheck(false); }
void EnableChargeCheck(const bool on=true)

◆ ElectricField() [1/2]

void Garfield::ComponentAnalyticField::ElectricField ( const double  x,
const double  y,
const double  z,
double &  ex,
double &  ey,
double &  ez,
double &  v,
Medium *&  m,
int &  status 
)
inlinevirtual

Implements Garfield::ComponentBase.

Definition at line 41 of file ComponentAnalyticField.hh.

43 {
44 m = NULL;
45 // Calculate the field.
46 status = Field(x, y, z, ex, ey, ez, v, true);
47 // If the field is ok, get the medium.
48 if (status == 0) {
49 m = GetMedium(x, y, z);
50 if (!m) {
51 status = -6;
52 } else if (!m->IsDriftable()) {
53 status = -5;
54 }
55 }
56 }
virtual Medium * GetMedium(const double x, const double y, const double z)
Get the medium at a given location (x, y, z).

◆ ElectricField() [2/2]

void Garfield::ComponentAnalyticField::ElectricField ( const double  x,
const double  y,
const double  z,
double &  ex,
double &  ey,
double &  ez,
Medium *&  m,
int &  status 
)
inlinevirtual

Calculate the drift field at given point.

Parameters
x,y,zcoordinates [cm].
ex,ey,ezcomponents of the electric field [V/cm].
mpointer to the medium at this location.
statusstatus flag

Status flags:

        0: Inside an active medium
      > 0: Inside a wire of type X
-4 ... -1: On the side of a plane where no wires are
       -5: Inside the mesh but not in an active medium
       -6: Outside the mesh
      -10: Unknown potential type (should not occur)
    other: Other cases (should not occur)

Implements Garfield::ComponentBase.

Definition at line 23 of file ComponentAnalyticField.hh.

24 {
25
26 m = NULL;
27 // Calculate the field.
28 double v = 0.;
29 status = Field(x, y, z, ex, ey, ez, v, false);
30 // If the field is ok, get the medium.
31 if (status == 0) {
32 m = GetMedium(x, y, z);
33 if (!m) {
34 status = -6;
35 } else if (!m->IsDriftable()) {
36 status = -5;
37 }
38 }
39 }

◆ EnableChargeCheck()

void Garfield::ComponentAnalyticField::EnableChargeCheck ( const bool  on = true)
inline

Definition at line 157 of file ComponentAnalyticField.hh.

157{ m_chargeCheck = on; }

Referenced by DisableChargeCheck().

◆ GetBoundingBox()

bool Garfield::ComponentAnalyticField::GetBoundingBox ( double &  xmin,
double &  ymin,
double &  zmin,
double &  xmax,
double &  ymax,
double &  zmax 
)
virtual

Get the bounding box coordinates.

Reimplemented from Garfield::ComponentBase.

Definition at line 35 of file ComponentAnalyticField.cc.

37 {
38
39 // If a geometry is present, try to get the bounding box from there.
40 if (m_geometry) {
41 if (m_geometry->GetBoundingBox(x0, y0, z0, x1, y1, z1)) return true;
42 }
43 // Otherwise, return the cell dimensions.
44 if (!m_cellset) return false;
45 x0 = m_xmin;
46 y0 = m_ymin;
47 z0 = m_zmin;
48 x1 = m_xmax;
49 y1 = m_ymax;
50 z1 = m_zmax;
51 return true;
52}
GeometryBase * m_geometry
Pointer to the geometry.
virtual bool GetBoundingBox(double &xmin, double &ymin, double &zmin, double &xmax, double &ymax, double &zmax)=0

◆ GetCellType()

std::string Garfield::ComponentAnalyticField::GetCellType ( )
inline

Return the cell type. Cells are classified according to the number and orientation of planes, the presence of periodicities and the location of the wires as one of the following types:

A non-periodic cells with at most 1 x- and 1 y-plane B1X x-periodic cells without x-planes and at most 1 y-plane B1Y y-periodic cells without y-planes and at most 1 x-plane B2X cells with 2 x-planes and at most 1 y-plane B2Y cells with 2 y-planes and at most 1 x-plane C1 doubly periodic cells without planes C2X doubly periodic cells with x-planes C2Y doubly periodic cells with y-planes C3 double periodic cells with x- and y-planes D1 round tubes without axial periodicity D2 round tubes with axial periodicity D3 polygonal tubes without axial periodicity

Definition at line 147 of file ComponentAnalyticField.hh.

147 {
148 if (!m_cellset) {
149 if (CellCheck()) CellType();
150 }
151 return m_scellType;
152 }

◆ GetNumberOfPlanesX()

unsigned int Garfield::ComponentAnalyticField::GetNumberOfPlanesX ( ) const

Definition at line 672 of file ComponentAnalyticField.cc.

672 {
673
674 if (m_ynplan[0] && m_ynplan[1]) {
675 return 2;
676 } else if (m_ynplan[0] || m_ynplan[1]) {
677 return 1;
678 }
679 return 0;
680}

◆ GetNumberOfPlanesY()

unsigned int Garfield::ComponentAnalyticField::GetNumberOfPlanesY ( ) const

Definition at line 682 of file ComponentAnalyticField.cc.

682 {
683
684 if (m_ynplan[2] && m_ynplan[3]) {
685 return 2;
686 } else if (m_ynplan[2] || m_ynplan[3]) {
687 return 1;
688 }
689 return 0;
690}

◆ GetNumberOfWires()

unsigned int Garfield::ComponentAnalyticField::GetNumberOfWires ( ) const
inline

Definition at line 160 of file ComponentAnalyticField.hh.

160{ return m_nWires; }

◆ GetPeriodicityX()

bool Garfield::ComponentAnalyticField::GetPeriodicityX ( double &  s)

Definition at line 558 of file ComponentAnalyticField.cc.

558 {
559
560 if (!m_xPeriodic) {
561 s = 0.;
562 return false;
563 }
564
565 s = m_sx;
566 return true;
567}
bool m_xPeriodic
Simple periodicity in x.

◆ GetPeriodicityY()

bool Garfield::ComponentAnalyticField::GetPeriodicityY ( double &  s)

Definition at line 569 of file ComponentAnalyticField.cc.

569 {
570
571 if (!m_yPeriodic) {
572 s = 0.;
573 return false;
574 }
575
576 s = m_sy;
577 return true;
578}
bool m_yPeriodic
Simple periodicity in y.

◆ GetPlaneX()

bool Garfield::ComponentAnalyticField::GetPlaneX ( const unsigned int  i,
double &  x,
double &  voltage,
std::string &  label 
) const

Definition at line 714 of file ComponentAnalyticField.cc.

716 {
717
718 if (i >= 2 || (i == 1 && !m_ynplan[1])) {
719 std::cerr << m_className << "::GetPlaneX:\n";
720 std::cerr << " Plane index is out of range.\n";
721 return false;
722 }
723
724 x = m_coplan[i];
725 voltage = m_vtplan[i];
726 label = planes[i].type;
727 return true;
728}

◆ GetPlaneY()

bool Garfield::ComponentAnalyticField::GetPlaneY ( const unsigned int  i,
double &  y,
double &  voltage,
std::string &  label 
) const

Definition at line 730 of file ComponentAnalyticField.cc.

732 {
733
734 if (i >= 2 || (i == 1 && !m_ynplan[3])) {
735 std::cerr << m_className << "::GetPlaneY:\n";
736 std::cerr << " Plane index is out of range.\n";
737 return false;
738 }
739
740 y = m_coplan[i + 2];
741 voltage = m_vtplan[i + 2];
742 label = planes[i + 2].type;
743 return true;
744}

◆ GetTube()

bool Garfield::ComponentAnalyticField::GetTube ( double &  r,
double &  voltage,
int &  nEdges,
std::string &  label 
) const

Definition at line 746 of file ComponentAnalyticField.cc.

747 {
748
749 if (!m_tube) return false;
750 r = m_cotube;
751 voltage = m_vttube;
752 nEdges = m_ntube;
753 label = planes[4].type;
754 return true;
755}

◆ GetVoltageRange()

bool Garfield::ComponentAnalyticField::GetVoltageRange ( double &  vmin,
double &  vmax 
)
virtual

Calculate the voltage range [V].

Implements Garfield::ComponentBase.

Definition at line 19 of file ComponentAnalyticField.cc.

19 {
20
21 // Make sure the cell is prepared.
22 if (!m_cellset) {
23 if (!Prepare()) {
24 std::cerr << m_className << "::GetVoltageRange:\n Unable to return "
25 << "voltage range (could not set up the cell).\n";
26 return false;
27 }
28 }
29
30 pmin = vmin;
31 pmax = vmax;
32 return true;
33}

◆ GetWire()

bool Garfield::ComponentAnalyticField::GetWire ( const unsigned int  i,
double &  x,
double &  y,
double &  diameter,
double &  voltage,
std::string &  label,
double &  length,
double &  charge,
int &  ntrap 
) const

Definition at line 692 of file ComponentAnalyticField.cc.

695 {
696
697 if (i >= m_nWires) {
698 std::cerr << m_className << "::GetWire:\n";
699 std::cerr << " Wire index is out of range.\n";
700 return false;
701 }
702
703 x = m_w[i].x;
704 y = m_w[i].y;
705 diameter = m_w[i].d;
706 voltage = m_w[i].v;
707 label = m_w[i].type;
708 length = m_w[i].u;
709 charge = m_w[i].e;
710 ntrap = m_w[i].nTrap;
711 return true;
712}

◆ IsInTrapRadius()

bool Garfield::ComponentAnalyticField::IsInTrapRadius ( const double  q0,
const double  x0,
const double  y0,
const double  z0,
double &  xw,
double &  yw,
double &  rw 
)
virtual

Determine whether a particle is inside the trap radius of a wire.

Parameters
q0charge of the particle [in elementary charges].
x0,y0,z0position [cm] of the particle.
xw,ywcoordinates of the wire (if applicable).
rwradius of the wire (if applicable).

Reimplemented from Garfield::ComponentBase.

Definition at line 132 of file ComponentAnalyticField.cc.

135 {
136
137 // In case of periodicity, move the point into the basic cell.
138 double x0 = xin;
139 double y0 = yin;
140 int nX = 0, nY = 0, nPhi = 0;
141 if (m_perx) {
142 nX = int(round(xin / m_sx));
143 x0 -= m_sx * nX;
144 }
145 if (m_pery && m_tube) {
146 Cartesian2Polar(xin, yin, x0, y0);
147 nPhi = int(round(DegreeToRad * y0 / m_sy));
148 y0 -= RadToDegree * m_sy * nPhi;
149 Polar2Cartesian(x0, y0, x0, y0);
150 } else if (m_pery) {
151 nY = int(round(yin / m_sy));
152 y0 -= m_sy * nY;
153 }
154
155 // Move the point to the correct side of the plane.
156 if (m_perx && m_ynplan[0] && x0 <= m_coplan[0]) x0 += m_sx;
157 if (m_perx && m_ynplan[1] && x0 >= m_coplan[1]) x0 -= m_sx;
158 if (m_pery && m_ynplan[2] && y0 <= m_coplan[2]) y0 += m_sy;
159 if (m_pery && m_ynplan[3] && y0 >= m_coplan[3]) y0 -= m_sy;
160
161 for (unsigned int i = 0; i < m_nWires; ++i) {
162 // Skip wires with the wrong charge.
163 if (qin * m_w[i].e > 0.) continue;
164 const double dxw0 = m_w[i].x - x0;
165 const double dyw0 = m_w[i].y - y0;
166 const double r2 = dxw0 * dxw0 + dyw0 * dyw0;
167 const double rTrap = 0.5 * m_w[i].d * m_w[i].nTrap;
168 if (r2 < rTrap * rTrap) {
169 xw = m_w[i].x;
170 yw = m_w[i].y;
171 rw = m_w[i].d * 0.5;
172 if (m_perx && m_ynplan[0] && x0 <= m_coplan[0]) x0 -= m_sx;
173 if (m_perx && m_ynplan[1] && x0 >= m_coplan[1]) x0 += m_sx;
174 if (m_pery && m_ynplan[2] && y0 <= m_coplan[2]) y0 -= m_sy;
175 if (m_pery && m_ynplan[3] && y0 >= m_coplan[3]) y0 += m_sy;
176 if (m_pery && m_tube) {
177 double rhow, phiw;
178 Cartesian2Polar(xw, yw, rhow, phiw);
179 phiw += RadToDegree * m_sy * nPhi;
180 Polar2Cartesian(rhow, phiw, xw, yw);
181 } else if (m_pery) {
182 y0 += m_sy * nY;
183 }
184 if (m_perx) xw += m_sx * nX;
185 if (m_debug) {
186 std::cout << m_className << "::IsInTrapRadius:\n";
187 std::cout << " (" << xin << ", " << yin << ", " << zin << ")"
188 << " within trap radius of wire " << i << ".\n";
189 }
190 return true;
191 }
192 }
193
194 return false;
195}
bool m_debug
Switch on/off debugging messages.

◆ IsWireCrossed()

bool Garfield::ComponentAnalyticField::IsWireCrossed ( const double  x0,
const double  y0,
const double  z0,
const double  x1,
const double  y1,
const double  z1,
double &  xc,
double &  yc,
double &  zc 
)
virtual

Determine whether the line between two points crosses a wire.

Parameters
x0,y0,z0first point [cm].
x1,y1,z1second point [cm]
xc,yc,zcpoint [cm] where the line crosses the wire.

Reimplemented from Garfield::ComponentBase.

Definition at line 54 of file ComponentAnalyticField.cc.

58 {
59
60 xc = x0;
61 yc = y0;
62 zc = z0;
63
64 if (m_w.empty()) return false;
65
66 const double dx = x1 - x0;
67 const double dy = y1 - y0;
68 const double d2 = dx * dx + dy * dy;
69 // Check that the step length is non-zero.
70 if (d2 < Small) return false;
71
72 // Check if a whole period has been crossed.
73 if ((m_perx && fabs(dx) >= m_sx) || (m_pery && fabs(dy) >= m_sy)) {
74 std::cerr << m_className << "::IsWireCrossed:\n"
75 << " Particle crossed more than one period.\n";
76 return false;
77 }
78
79 // Both coordinates are assumed to be located inside
80 // the drift area and inside a drift medium.
81 // This should have been checked before this call.
82
83 const double xm = 0.5 * (x0 + x1);
84 const double ym = 0.5 * (y0 + y1);
85 double dMin2 = 0.;
86 for (unsigned int i = 0; i < m_nWires; ++i) {
87 double xw = m_w[i].x, yw = m_w[i].y;
88 if (m_perx) {
89 xw += m_sx * int(round((xm - xw) / m_sx));
90 }
91 if (m_pery) {
92 yw += m_sy * int(round((ym - yw) / m_sy));
93 }
94 // Calculate the smallest distance between track and wire.
95 const double xIn0 = dx * (xw - x0) + dy * (yw - y0);
96 // Check if the minimum is located before (x0, y0).
97 if (xIn0 < 0.) continue;
98 const double xIn1 = -(dx * (xw - x1) + dy * (yw - y1));
99 // Check if the minimum is located behind (x1, y1).
100 if (xIn1 < 0.) continue;
101 // Minimum is located between (x0, y0) and (x1, y1).
102 const double xw0 = xw - x0;
103 const double xw1 = xw - x1;
104 const double yw0 = yw - y0;
105 const double yw1 = yw - y1;
106 const double dw02 = xw0 * xw0 + yw0 * yw0;
107 const double dw12 = xw1 * xw1 + yw1 * yw1;
108 if (xIn1 * xIn1 * dw02 > xIn0 * xIn0 * dw12) {
109 dMin2 = dw02 - xIn0 * xIn0 / d2;
110 } else {
111 dMin2 = dw12 - xIn1 * xIn1 / d2;
112 }
113 // Add in the times nTrap to account for the trap radius.
114 const double r2 = 0.25 * m_w[i].d * m_w[i].d;
115 if (dMin2 < r2) {
116 // Wire has been crossed.
117 // Find the point of intersection.
118 const double p = -xIn0 / d2;
119 const double q = (dw02 - r2) / d2;
120 const double t1 = -p + sqrt(p * p - q);
121 const double t2 = -p - sqrt(p * p - q);
122 const double t = std::min(t1, t2);
123 xc = x0 + t * dx;
124 yc = y0 + t * dy;
125 zc = z0 + t * (z1 - z0);
126 return true;
127 }
128 }
129 return false;
130}
DoubleAc sqrt(const DoubleAc &f)
Definition: DoubleAc.cpp:314

◆ PrintCharges()

void Garfield::ComponentAnalyticField::PrintCharges ( ) const

Definition at line 656 of file ComponentAnalyticField.cc.

656 {
657
658 std::cout << m_className << "::PrintCharges:\n";
659 if (m_ch3d.empty()) {
660 std::cout << " No charges present.\n";
661 return;
662 }
663 std::cout << " x [cm] y [cm] z [cm] charge [fC]\n";
664 const unsigned int n3d = m_ch3d.size();
665 for (unsigned int i = 0; i < n3d; ++i) {
666 std::cout << " " << std::setw(9) << m_ch3d[i].x << " " << std::setw(9)
667 << m_ch3d[i].y << " " << std::setw(9) << m_ch3d[i].z << " "
668 << std::setw(11) << m_ch3d[i].e * FourPiEpsilon0 << "\n";
669 }
670}

◆ SetPeriodicityX()

void Garfield::ComponentAnalyticField::SetPeriodicityX ( const double  s)

Set the periodic length [cm] in the x-direction.

Definition at line 532 of file ComponentAnalyticField.cc.

532 {
533
534 if (s < Small) {
535 std::cerr << m_className << "::SetPeriodicityX:\n";
536 std::cerr << " Periodic length must be greater than zero.\n";
537 return;
538 }
539
540 m_xPeriodic = true;
541 m_sx = s;
542 UpdatePeriodicity();
543}

◆ SetPeriodicityY()

void Garfield::ComponentAnalyticField::SetPeriodicityY ( const double  s)

Set the periodic length [cm] in the y-direction.

Definition at line 545 of file ComponentAnalyticField.cc.

545 {
546
547 if (s < Small) {
548 std::cerr << m_className << "::SetPeriodicityY:\n";
549 std::cerr << " Periodic length must be greater than zero.\n";
550 return;
551 }
552
553 m_yPeriodic = true;
554 m_sy = s;
555 UpdatePeriodicity();
556}

◆ WeightingField()

void Garfield::ComponentAnalyticField::WeightingField ( const double  x,
const double  y,
const double  z,
double &  wx,
double &  wy,
double &  wz,
const std::string &  label 
)
inlinevirtual

Calculate the weighting field at a given point and for a given electrode.

Parameters
x,y,zcoordinates [cm].
wx,wy,wzcomponents of the weighting field [1/cm].
labelname of the electrode

Reimplemented from Garfield::ComponentBase.

Definition at line 60 of file ComponentAnalyticField.hh.

62 {
63 wx = wy = wz = 0.;
64 double volt = 0.;
65 if (!m_sigset) PrepareSignals();
66 Wfield(x, y, z, wx, wy, wz, volt, label, false);
67 }

◆ WeightingPotential()

double Garfield::ComponentAnalyticField::WeightingPotential ( const double  x,
const double  y,
const double  z,
const std::string &  label 
)
inlinevirtual

Reimplemented from Garfield::ComponentBase.

Definition at line 68 of file ComponentAnalyticField.hh.

69 {
70 double wx = 0., wy = 0., wz = 0.;
71 double volt = 0.;
72 if (!m_sigset) PrepareSignals();
73 Wfield(x, y, z, wx, wy, wz, volt, label, true);
74 return volt;
75 }

The documentation for this class was generated from the following files: