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

Component for importing and interpolating Comsol field maps. More...

#include <ComponentComsol.hh>

+ Inheritance diagram for Garfield::ComponentComsol:

Classes

struct  nodeCmp
 

Public Member Functions

 ComponentComsol ()
 
 ComponentComsol (std::string mesh, std::string mplist, std::string field)
 
 ~ComponentComsol ()
 
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)
 
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)
 
MediumGetMedium (const double x, const double y, const double z)
 Get the medium at a given location (x, y, z).
 
virtual bool IsInBoundingBox (const double x, const double y, const double z) const
 
bool Initialise (std::string header="mesh.mphtxt", std::string mplist="dielectrics.dat", std::string field="field.txt")
 
bool SetWeightingField (std::string file, std::string label)
 
- Public Member Functions inherited from Garfield::ComponentFieldMap
 ComponentFieldMap ()
 Constructor.
 
virtual ~ComponentFieldMap ()
 Destructor.
 
virtual void SetRange ()
 Calculate x, y, z, V and angular ranges.
 
void PrintRange ()
 Show x, y, z, V and angular ranges.
 
virtual bool IsInBoundingBox (const double x, const double y, const double z) const
 
virtual bool GetBoundingBox (double &xmin, double &ymin, double &zmin, double &xmax, double &ymax, double &zmax)
 Get the bounding box coordinates.
 
virtual bool GetVoltageRange (double &vmin, double &vmax)
 Calculate the voltage range [V].
 
void PrintMaterials ()
 List all currently defined materials.
 
void DriftMedium (const unsigned int imat)
 Flag a field map material as a drift medium.
 
void NotDriftMedium (const unsigned int imat)
 Flag a field map materials as a non-drift medium.
 
unsigned int GetNumberOfMaterials () const
 Return the number of materials in the field map.
 
double GetPermittivity (const unsigned int imat) const
 Return the permittivity of a field map material.
 
double GetConductivity (const unsigned int imat) const
 Return the conductivity of a field map material.
 
void SetMedium (const unsigned int imat, Medium *medium)
 Associate a field map material with a Medium class.
 
MediumGetMedium (const unsigned int i) const
 Return the Medium associated to a field map material.
 
MediumGetMedium (const double x, const double y, const double z)=0
 Get the medium at a given location (x, y, z).
 
unsigned int GetNumberOfMedia () const
 
int GetNumberOfElements () const
 Return the number of mesh elements.
 
bool GetElement (const unsigned int i, double &vol, double &dmin, double &dmax)
 Return the volume and aspect ratio of a mesh element.
 
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 void WeightingField (const double x, const double y, const double z, double &wx, double &wy, double &wz, const std::string &label)=0
 
virtual double WeightingPotential (const double x, const double y, const double z, const std::string &label)=0
 
void EnableCheckMapIndices ()
 
void DisableCheckMapIndices ()
 
void EnableDeleteBackgroundElements ()
 
void DisableDeleteBackgroundElements ()
 
void EnableTetrahedralTreeForElementSearch (const bool on=true)
 
- 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)
 

Protected Member Functions

void UpdatePeriodicity ()
 Verify periodicities.
 
double GetElementVolume (const unsigned int i)
 
void GetAspectRatio (const unsigned int i, double &dmin, double &dmax)
 
- Protected Member Functions inherited from Garfield::ComponentFieldMap
void Reset ()
 Geometry checks.
 
virtual void UpdatePeriodicity ()=0
 Verify periodicities.
 
void UpdatePeriodicity2d ()
 
void UpdatePeriodicityCommon ()
 
int FindElement5 (const double x, const double y, const double z, double &t1, double &t2, double &t3, double &t4, double jac[4][4], double &det)
 Find the element for a point in curved quadratic quadrilaterals.
 
int FindElement13 (const double x, const double y, const double z, double &t1, double &t2, double &t3, double &t4, double jac[4][4], double &det)
 Find the element for a point in curved quadratic tetrahedra.
 
int FindElementCube (const double x, const double y, const double z, double &t1, double &t2, double &t3, TMatrixD *&jac, std::vector< TMatrixD * > &dN)
 Find the element for a point in a cube.
 
void MapCoordinates (double &xpos, double &ypos, double &zpos, bool &xmirrored, bool &ymirrored, bool &zmirrored, double &rcoordinate, double &rotation) const
 Move (xpos, ypos, zpos) to field map coordinates.
 
void UnmapFields (double &ex, double &ey, double &ez, double &xpos, double &ypos, double &zpos, bool &xmirrored, bool &ymirrored, bool &zmirrored, double &rcoordinate, double &rotation) const
 Move (ex, ey, ez) to global coordinates.
 
int ReadInteger (char *token, int def, bool &error)
 
double ReadDouble (char *token, double def, bool &error)
 
virtual double GetElementVolume (const unsigned int i)=0
 
virtual void GetAspectRatio (const unsigned int i, double &dmin, double &dmax)=0
 
void PrintWarning (const std::string &header)
 
void PrintNotReady (const std::string &header) const
 
void PrintElement (const std::string &header, const double x, const double y, const double z, const double t1, const double t2, const double t3, const double t4, const unsigned int i, const unsigned int n, const int iw=-1) const
 
virtual void Reset ()=0
 Geometry checks.
 
virtual void UpdatePeriodicity ()=0
 Verify periodicities.
 

Additional Inherited Members

- Protected Attributes inherited from Garfield::ComponentFieldMap
bool m_is3d
 
int nElements
 
std::vector< Elementelements
 
int nNodes
 
std::vector< Nodenodes
 
unsigned int m_nMaterials
 
std::vector< Materialmaterials
 
int nWeightingFields
 
std::vector< std::string > wfields
 
std::vector< bool > wfieldsOk
 
bool hasBoundingBox
 
double xMinBoundingBox
 
double yMinBoundingBox
 
double zMinBoundingBox
 
double xMaxBoundingBox
 
double yMaxBoundingBox
 
double zMaxBoundingBox
 
double mapxmin
 
double mapymin
 
double mapzmin
 
double mapxmax
 
double mapymax
 
double mapzmax
 
double mapxamin
 
double mapyamin
 
double mapzamin
 
double mapxamax
 
double mapyamax
 
double mapzamax
 
double mapvmin
 
double mapvmax
 
bool setangx
 
bool setangy
 
bool setangz
 
double mapsx
 
double mapsy
 
double mapsz
 
double cellsx
 
double cellsy
 
double cellsz
 
double mapnxa
 
double mapnya
 
double mapnza
 
bool m_deleteBackground
 
bool m_warning
 
unsigned int m_nWarnings
 
- 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

Component for importing and interpolating Comsol field maps.

Definition at line 9 of file ComponentComsol.hh.

Constructor & Destructor Documentation

◆ ComponentComsol() [1/2]

Garfield::ComponentComsol::ComponentComsol ( )

Definition at line 14 of file ComponentComsol.cc.

15
16 m_className = "ComponentComsol";
17}
std::string m_className
Class name.

◆ ComponentComsol() [2/2]

Garfield::ComponentComsol::ComponentComsol ( std::string  mesh,
std::string  mplist,
std::string  field 
)

Definition at line 19 of file ComponentComsol.cc.

22
23 m_className = "ComponentComsol";
24 Initialise(mesh, mplist, field);
25}
bool Initialise(std::string header="mesh.mphtxt", std::string mplist="dielectrics.dat", std::string field="field.txt")

◆ ~ComponentComsol()

Garfield::ComponentComsol::~ComponentComsol ( )
inline

Definition at line 16 of file ComponentComsol.hh.

16{}

Member Function Documentation

◆ ElectricField() [1/2]

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

Implements Garfield::ComponentFieldMap.

Definition at line 344 of file ComponentComsol.cc.

347 {
348
349 // Copy the coordinates
350 double x = xin, y = yin, z = zin;
351
352 // Map the coordinates onto field map coordinates
353 bool xmirr, ymirr, zmirr;
354 double rcoordinate, rotation;
355 MapCoordinates(x, y, z, xmirr, ymirr, zmirr, rcoordinate, rotation);
356
357 // Initial values
358 ex = ey = ez = volt = 0.;
359 status = 0;
360 m = NULL;
361
362 // Do not proceed if not properly initialised.
363 if (!m_ready) {
364 status = -10;
365 PrintNotReady("ElectricField");
366 return;
367 }
368
369 if (m_warning) PrintWarning("ElectricField");
370
371 // Find the element that contains this point
372 double t1, t2, t3, t4, jac[4][4], det;
373 const int imap = FindElement13(x, y, z, t1, t2, t3, t4, jac, det);
374 if (imap < 0) {
375 if (m_debug) {
376 std::cout << m_className << "::ElectricField:\n";
377 std::cout << " Point (" << x << ", " << y << ", " << z
378 << " not in the mesh.\n";
379 }
380 status = -6;
381 return;
382 }
383
384 if (m_debug) {
385 PrintElement("ElectricField", x, y, z, t1, t2, t3, t4, imap, 10);
386 }
387
388 const Element& element = elements[imap];
389 const Node& n0 = nodes[element.emap[0]];
390 const Node& n1 = nodes[element.emap[1]];
391 const Node& n2 = nodes[element.emap[2]];
392 const Node& n3 = nodes[element.emap[3]];
393 const Node& n4 = nodes[element.emap[4]];
394 const Node& n5 = nodes[element.emap[5]];
395 const Node& n6 = nodes[element.emap[6]];
396 const Node& n7 = nodes[element.emap[7]];
397 const Node& n8 = nodes[element.emap[8]];
398 const Node& n9 = nodes[element.emap[9]];
399 // Tetrahedral field
400 volt = n0.v * t1 * (2 * t1 - 1) + n1.v * t2 * (2 * t2 - 1) +
401 n2.v * t3 * (2 * t3 - 1) + n3.v * t4 * (2 * t4 - 1) +
402 4 * n4.v * t1 * t2 + 4 * n5.v * t1 * t3 + 4 * n6.v * t1 * t4 +
403 4 * n7.v * t2 * t3 + 4 * n8.v * t2 * t4 + 4 * n9.v * t3 * t4;
404 ex = -(n0.v * (4 * t1 - 1) * jac[0][1] + n1.v * (4 * t2 - 1) * jac[1][1] +
405 n2.v * (4 * t3 - 1) * jac[2][1] + n3.v * (4 * t4 - 1) * jac[3][1] +
406 n4.v * (4 * t2 * jac[0][1] + 4 * t1 * jac[1][1]) +
407 n5.v * (4 * t3 * jac[0][1] + 4 * t1 * jac[2][1]) +
408 n6.v * (4 * t4 * jac[0][1] + 4 * t1 * jac[3][1]) +
409 n7.v * (4 * t3 * jac[1][1] + 4 * t2 * jac[2][1]) +
410 n8.v * (4 * t4 * jac[1][1] + 4 * t2 * jac[3][1]) +
411 n9.v * (4 * t4 * jac[2][1] + 4 * t3 * jac[3][1])) /
412 det;
413 ey = -(n0.v * (4 * t1 - 1) * jac[0][2] + n1.v * (4 * t2 - 1) * jac[1][2] +
414 n2.v * (4 * t3 - 1) * jac[2][2] + n3.v * (4 * t4 - 1) * jac[3][2] +
415 n4.v * (4 * t2 * jac[0][2] + 4 * t1 * jac[1][2]) +
416 n5.v * (4 * t3 * jac[0][2] + 4 * t1 * jac[2][2]) +
417 n6.v * (4 * t4 * jac[0][2] + 4 * t1 * jac[3][2]) +
418 n7.v * (4 * t3 * jac[1][2] + 4 * t2 * jac[2][2]) +
419 n8.v * (4 * t4 * jac[1][2] + 4 * t2 * jac[3][2]) +
420 n9.v * (4 * t4 * jac[2][2] + 4 * t3 * jac[3][2])) /
421 det;
422 ez = -(n0.v * (4 * t1 - 1) * jac[0][3] + n1.v * (4 * t2 - 1) * jac[1][3] +
423 n2.v * (4 * t3 - 1) * jac[2][3] + n3.v * (4 * t4 - 1) * jac[3][3] +
424 n4.v * (4 * t2 * jac[0][3] + 4 * t1 * jac[1][3]) +
425 n5.v * (4 * t3 * jac[0][3] + 4 * t1 * jac[2][3]) +
426 n6.v * (4 * t4 * jac[0][3] + 4 * t1 * jac[3][3]) +
427 n7.v * (4 * t3 * jac[1][3] + 4 * t2 * jac[2][3]) +
428 n8.v * (4 * t4 * jac[1][3] + 4 * t2 * jac[3][3]) +
429 n9.v * (4 * t4 * jac[2][3] + 4 * t3 * jac[3][3])) /
430 det;
431
432 // Transform field to global coordinates
433 UnmapFields(ex, ey, ez, x, y, z, xmirr, ymirr, zmirr, rcoordinate, rotation);
434 // std::cout << "ef @(" << xin << ", " << yin << ", " << zin << ") = " <<
435 // volt << "\n";
436
437 // Drift medium?
438 if (m_debug) {
439 std::cout << m_className << "::ElectricField:\n";
440 std::cout << " Material " << element.matmap << ", drift flag "
441 << materials[element.matmap].driftmedium << "\n";
442 }
443 m = materials[element.matmap].medium;
444 status = -5;
445 if (materials[element.matmap].driftmedium) {
446 if (m && m->IsDriftable()) status = 0;
447 }
448}
bool m_ready
Ready for use?
bool m_debug
Switch on/off debugging messages.
void MapCoordinates(double &xpos, double &ypos, double &zpos, bool &xmirrored, bool &ymirrored, bool &zmirrored, double &rcoordinate, double &rotation) const
Move (xpos, ypos, zpos) to field map coordinates.
void PrintWarning(const std::string &header)
void PrintElement(const std::string &header, const double x, const double y, const double z, const double t1, const double t2, const double t3, const double t4, const unsigned int i, const unsigned int n, const int iw=-1) const
std::vector< Material > materials
int FindElement13(const double x, const double y, const double z, double &t1, double &t2, double &t3, double &t4, double jac[4][4], double &det)
Find the element for a point in curved quadratic tetrahedra.
std::vector< Element > elements
void UnmapFields(double &ex, double &ey, double &ez, double &xpos, double &ypos, double &zpos, bool &xmirrored, bool &ymirrored, bool &zmirrored, double &rcoordinate, double &rotation) const
Move (ex, ey, ez) to global coordinates.
void PrintNotReady(const std::string &header) const

◆ ElectricField() [2/2]

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

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::ComponentFieldMap.

Definition at line 336 of file ComponentComsol.cc.

338 {
339
340 double v = 0.;
341 ElectricField(x, y, z, ex, ey, ez, v, m, status);
342}
void ElectricField(const double x, const double y, const double z, double &ex, double &ey, double &ez, Medium *&m, int &status)

Referenced by ElectricField().

◆ GetAspectRatio()

void Garfield::ComponentComsol::GetAspectRatio ( const unsigned int  i,
double &  dmin,
double &  dmax 
)
protectedvirtual

Implements Garfield::ComponentFieldMap.

Definition at line 677 of file ComponentComsol.cc.

678 {
679
680 if (i >= elements.size()) {
681 dmin = dmax = 0.;
682 return;
683 }
684
685 const Element& element = elements[i];
686 const int np = 4;
687 // Loop over all pairs of vertices.
688 for (int j = 0; j < np - 1; ++j) {
689 const Node& nj = nodes[element.emap[j]];
690 for (int k = j + 1; k < np; ++k) {
691 const Node& nk = nodes[element.emap[k]];
692 // Compute distance.
693 const double dx = nj.x - nk.x;
694 const double dy = nj.y - nk.y;
695 const double dz = nj.z - nk.z;
696 const double dist = sqrt(dx * dx + dy * dy + dz * dz);
697 if (k == 1) {
698 dmin = dmax = dist;
699 } else {
700 if (dist < dmin) dmin = dist;
701 if (dist > dmax) dmax = dist;
702 }
703 }
704 }
705}
DoubleAc sqrt(const DoubleAc &f)
Definition: DoubleAc.cpp:314

◆ GetElementVolume()

double Garfield::ComponentComsol::GetElementVolume ( const unsigned int  i)
protectedvirtual

Implements Garfield::ComponentFieldMap.

Definition at line 655 of file ComponentComsol.cc.

655 {
656
657 if (i >= elements.size()) return 0.;
658 const Element& element = elements[i];
659 const Node& n0 = nodes[element.emap[0]];
660 const Node& n1 = nodes[element.emap[1]];
661 const Node& n2 = nodes[element.emap[2]];
662 const Node& n3 = nodes[element.emap[3]];
663
664 // Uses formula V = |a (dot) b x c|/6
665 // with a => "3", b => "1", c => "2" and origin "0"
666 const double vol =
667 fabs((n3.x - n0.x) *
668 ((n1.y - n0.y) * (n2.z - n0.z) - (n2.y - n0.y) * (n1.z - n0.z)) +
669 (n3.y - n0.y) *
670 ((n1.z - n0.z) * (n2.x - n0.x) - (n2.z - n0.z) * (n1.x - n0.x)) +
671 (n3.z - n0.z) * ((n1.x - n0.x) * (n2.y - n0.y) -
672 (n3.x - n0.x) * (n1.y - n0.y))) /
673 6.;
674 return vol;
675}
DoubleAc fabs(const DoubleAc &f)
Definition: DoubleAc.h:615

◆ GetMedium()

Medium * Garfield::ComponentComsol::GetMedium ( const double  x,
const double  y,
const double  z 
)
virtual

Get the medium at a given location (x, y, z).

Implements Garfield::ComponentFieldMap.

Definition at line 609 of file ComponentComsol.cc.

610 {
611
612 // Copy the coordinates
613 double x = xin, y = yin, z = zin;
614
615 // Map the coordinates onto field map coordinates
616 bool xmirr, ymirr, zmirr;
617 double rcoordinate, rotation;
618 MapCoordinates(x, y, z, xmirr, ymirr, zmirr, rcoordinate, rotation);
619
620 // Do not proceed if not properly initialised.
621 if (!m_ready) {
622 PrintNotReady("GetMedium");
623 return nullptr;
624 }
625 if (m_warning) PrintWarning("GetMedium");
626
627 // Find the element that contains this point
628 double t1, t2, t3, t4, jac[4][4], det;
629 const int imap = FindElement13(x, y, z, t1, t2, t3, t4, jac, det);
630 if (imap < 0) {
631 if (m_debug) {
632 std::cout << m_className << "::GetMedium:\n";
633 std::cout << " Point (" << x << ", " << y << ", " << z
634 << ") not in the mesh.\n";
635 }
636 return nullptr;
637 }
638 const Element& element = elements[imap];
639 if (element.matmap >= m_nMaterials) {
640 if (m_debug) {
641 std::cerr << m_className << "::GetMedium:\n";
642 std::cerr << " Point (" << x << ", " << y
643 << ") has out of range material number " << imap << ".\n";
644 }
645 return nullptr;
646 }
647
648 if (m_debug) {
649 PrintElement("GetMedium", x, y, z, t1, t2, t3, t4, imap, 10);
650 }
651
652 return materials[element.matmap].medium;
653}

◆ Initialise()

bool Garfield::ComponentComsol::Initialise ( std::string  header = "mesh.mphtxt",
std::string  mplist = "dielectrics.dat",
std::string  field = "field.txt" 
)

Definition at line 38 of file ComponentComsol.cc.

39 {
40
41 m_ready = false;
42 m_warning = false;
43 m_nWarnings = 0;
44
45 double unit = 100.0; // m
46
47 std::string line;
48
49 // Open the materials file.
50 materials.clear();
51 std::ifstream fmplist;
52 fmplist.open(mplist.c_str(), std::ios::in);
53 if (fmplist.fail()) {
54 std::cerr << m_className << "::Initialise:\n";
55 std::cerr << " Could not open result file " << mplist
56 << " for reading.\n";
57 return false;
58 }
59 fmplist >> m_nMaterials;
60 for (unsigned int i = 0; i < m_nMaterials; ++i) {
61 Material newMaterial;
62 newMaterial.driftmedium = true;
63 newMaterial.medium = nullptr;
64 newMaterial.ohm = -1;
65 fmplist >> newMaterial.eps;
66 materials.push_back(newMaterial);
67 }
68 {
69 // add default material
70 Material newMaterial;
71 newMaterial.driftmedium = false;
72 newMaterial.medium = nullptr;
73 newMaterial.eps = newMaterial.ohm = -1;
74 materials.push_back(newMaterial);
76 }
77 std::map<int, int> domain2material;
78 int d2msize;
79 fmplist >> d2msize;
80 for (int i = 0; i < d2msize; ++i) {
81 int domain;
82 fmplist >> domain;
83 fmplist >> domain2material[domain];
84 }
85 fmplist.close();
86
87 nodes.clear();
88 std::ifstream fmesh;
89 fmesh.open(mesh.c_str(), std::ios::in);
90 if (fmesh.fail()) {
91 std::cerr << m_className << "::Initialise:\n";
92 std::cerr << " Could not open nodes file " << mesh << " for reading.\n";
93 return false;
94 }
95
96 do {
97 std::getline(fmesh, line);
98 } while (!ends_with(line, "# number of mesh points"));
99 nNodes = readInt(line);
100
101 std::cout << m_className << "::Initialise:\n";
102 std::cout << " Read " << nNodes << " nodes from file " << mesh << ".\n";
103 do {
104 std::getline(fmesh, line);
105 } while (line != "# Mesh point coordinates");
106 double minx = 1e100, miny = 1e100, minz = 1e100, maxx = -1e100, maxy = -1e100,
107 maxz = -1e100;
108 for (int i = 0; i < nNodes; ++i) {
109 Node newNode;
110 fmesh >> newNode.x >> newNode.y >> newNode.z;
111 newNode.x *= unit;
112 newNode.y *= unit;
113 newNode.z *= unit;
114 nodes.push_back(newNode);
115 minx = std::min(minx, newNode.x);
116 maxx = std::max(maxx, newNode.x);
117 miny = std::min(miny, newNode.y);
118 maxy = std::max(maxy, newNode.y);
119 minz = std::min(minz, newNode.z);
120 maxz = std::max(maxz, newNode.z);
121 }
122 std::cout << minx << " < x < " << maxx << "\n";
123 std::cout << miny << " < y < " << maxy << "\n";
124 std::cout << minz << " < z < " << maxz << "\n";
125
126 do {
127 std::getline(fmesh, line);
128 } while (line != "4 tet2 # type name");
129 do {
130 std::getline(fmesh, line);
131 } while (!ends_with(line, "# number of elements"));
132 nElements = readInt(line);
133 elements.clear();
134 std::cout << m_className << "::Initialise:\n";
135 std::cout << " Read " << nElements << " elements from file " << mesh
136 << ".\n";
137 std::getline(fmesh, line);
138 // elements 6 & 7 are swapped due to differences in COMSOL and ANSYS
139 // representation
140 int perm[10] = {0, 1, 2, 3, 4, 5, 7, 6, 8, 9};
141 for (int i = 0; i < nElements; ++i) {
142 Element newElement;
143 newElement.degenerate = false;
144 for (int j = 0; j < 10; ++j) {
145 fmesh >> newElement.emap[perm[j]];
146 }
147 elements.push_back(newElement);
148 }
149
150 do {
151 std::getline(fmesh, line);
152 } while (line != "# Geometric entity indices");
153 for (int i = 0; i < nElements; ++i) {
154 int domain;
155 fmesh >> domain;
156 elements[i].matmap = domain2material.count(domain) ? domain2material[domain]
157 : m_nMaterials - 1;
158 }
159 fmesh.close();
160
161 std::map<Node, std::vector<int>, nodeCmp> nodeIdx;
162 for (int i = 0; i < nNodes; ++i) {
163 nodeIdx[nodes[i]].push_back(i);
164 }
165 std::cout << "Map size: " << nodeIdx.size() << std::endl;
166
167 std::ifstream ffield;
168 ffield.open(field.c_str(), std::ios::in);
169 if (ffield.fail()) {
170 std::cerr << m_className << "::Initialise:\n";
171 std::cerr << " Could not open field potentials file " << field
172 << " for reading.\n";
173 return false;
174 }
175 do {
176 std::getline(ffield, line);
177 } while (line.substr(0, 81) !=
178 "% x y z "
179 " V (V)");
180 {
181 std::istringstream sline(line);
182 std::string token;
183 sline >> token; // %
184 sline >> token; // x
185 sline >> token; // y
186 sline >> token; // z
187 sline >> token; // V
188 sline >> token; // (V)
189 while (sline >> token) {
190 std::cout << m_className << "::Initialise:\n";
191 std::cout << " Reading data for weighting field " << token << ".\n";
193 wfields.push_back(token);
194 wfieldsOk.push_back(true);
195 sline >> token; // (V)
196 }
197 }
198 for (int i = 0; i < nNodes; ++i) {
199 Node tmp;
200 ffield >> tmp.x >> tmp.y >> tmp.z >> tmp.v;
201 tmp.x *= unit;
202 tmp.y *= unit;
203 tmp.z *= unit;
204 for (int j = 0; j < nWeightingFields; ++j) {
205 double w;
206 ffield >> w;
207 tmp.w.push_back(w);
208 }
209 int closest = -1;
210 double closestDist = 1;
211 const unsigned int nIdx = nodeIdx[tmp].size();
212 // for (int j : nodeIdx[tmp]) {
213 for (unsigned int k = 0; k < nIdx; ++k) {
214 int j = nodeIdx[tmp][k];
215 double dist = (tmp.x - nodes[j].x) * (tmp.x - nodes[j].x) +
216 (tmp.y - nodes[j].y) * (tmp.y - nodes[j].y) +
217 (tmp.z - nodes[j].z) * (tmp.z - nodes[j].z);
218 if (dist < closestDist) {
219 closestDist = dist;
220 closest = j;
221 }
222 }
223 if (closest == -1) {
224 std::cerr << m_className << "::Initialise:\n";
225 std::cerr << " Could not match the node from field potentials file: "
226 << tmp.x << " " << tmp.y << " " << tmp.z << "\n.";
227 return false;
228 }
229 nodes[closest].v = tmp.v;
230 nodes[closest].w = tmp.w;
231 }
232
233 m_ready = true;
234
235 // for (int i = 0; i < nNodes; ++i) {
236 // double ex, ey, ez, v;
237 // Medium* m;
238 // int status;
239 // ElectricField(nodes[i].x, nodes[i].y, nodes[i].z, ex, ey, ez, v, m,
240 // status);
241 // std::cout << "Field at " << nodes[i].x << " " << nodes[i].y << " " <<
242 // nodes[i].z << ": " << ex << " " << ey << " " << ez << " " << v << "\n";
243 // }
244
245 // Establish the ranges.
246 SetRange();
248 return true;
249}
void UpdatePeriodicity()
Verify periodicities.
virtual void SetRange()
Calculate x, y, z, V and angular ranges.
std::vector< std::string > wfields
int readInt(std::string s)
bool ends_with(std::string s, std::string t)

Referenced by ComponentComsol().

◆ IsInBoundingBox()

virtual bool Garfield::ComponentComsol::IsInBoundingBox ( const double  x,
const double  y,
const double  z 
) const
inlinevirtual

◆ SetWeightingField()

bool Garfield::ComponentComsol::SetWeightingField ( std::string  file,
std::string  label 
)

Definition at line 251 of file ComponentComsol.cc.

251 {
252 double unit = 100.0; // m;
253
254 if (!m_ready) {
255 std::cerr << m_className << "::SetWeightingField:\n";
256 std::cerr << " No valid field map is present.\n";
257 std::cerr << " Weighting field cannot be added.\n";
258 return false;
259 }
260
261 // Open the voltage list.
262 std::ifstream ffield;
263 ffield.open(field.c_str(), std::ios::in);
264 if (ffield.fail()) {
265 std::cerr << m_className << "::Initialise:\n";
266 std::cerr << " Could not open field potentials file " << field
267 << " for reading.\n";
268 return false;
269 }
270
271 // Check if a weighting field with the same label alm_ready exists.
272 int iw = nWeightingFields;
273 for (int i = nWeightingFields; i--;) {
274 if (wfields[i] == label) {
275 iw = i;
276 break;
277 }
278 }
279 if (iw == nWeightingFields) {
283 for (int j = 0; j < nNodes; ++j) {
284 nodes[j].w.resize(nWeightingFields);
285 }
286 } else {
287 std::cout << m_className << "::SetWeightingField:\n";
288 std::cout << " Replacing existing weighting field " << label << ".\n";
289 }
290 wfields[iw] = label;
291 wfieldsOk[iw] = false;
292 std::map<Node, std::vector<int>, nodeCmp> nodeIdx;
293 for (int i = 0; i < nNodes; ++i) {
294 nodeIdx[nodes[i]].push_back(i);
295 }
296 std::cout << "Map size: " << nodeIdx.size() << std::endl;
297
298 std::string line;
299 do {
300 std::getline(ffield, line);
301 } while (line !=
302 "% x y z "
303 " V (V)");
304 for (int i = 0; i < nNodes; ++i) {
305 Node tmp;
306 ffield >> tmp.x >> tmp.y >> tmp.z >> tmp.v;
307 tmp.x *= unit;
308 tmp.y *= unit;
309 tmp.z *= unit;
310 int closest = -1;
311 double closestDist = 1;
312 const unsigned int nIdx = nodeIdx[tmp].size();
313 // for (int j : nodeIdx[tmp]) {
314 for (unsigned int k = 0; k < nIdx; ++k) {
315 int j = nodeIdx[tmp][k];
316 double dist = (tmp.x - nodes[j].x) * (tmp.x - nodes[j].x) +
317 (tmp.y - nodes[j].y) * (tmp.y - nodes[j].y) +
318 (tmp.z - nodes[j].z) * (tmp.z - nodes[j].z);
319 if (dist < closestDist) {
320 closestDist = dist;
321 closest = j;
322 }
323 }
324 if (closest == -1) {
325 std::cerr << m_className << "::Initialise:\n";
326 std::cerr << " Could not match the node from field potentials file: "
327 << tmp.x << " " << tmp.y << " " << tmp.z << "\n.";
328 return false;
329 }
330 nodes[closest].w[iw] = tmp.v;
331 }
332
333 return true;
334}

◆ UpdatePeriodicity()

void Garfield::ComponentComsol::UpdatePeriodicity ( )
inlineprotectedvirtual

Verify periodicities.

Implements Garfield::ComponentFieldMap.

Definition at line 48 of file ComponentComsol.hh.

Referenced by Initialise().

◆ WeightingField()

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

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

Implements Garfield::ComponentFieldMap.

Definition at line 450 of file ComponentComsol.cc.

452 {
453
454 // Initial values
455 wx = wy = wz = 0;
456
457 // Do not proceed if not properly initialised.
458 if (!m_ready) return;
459
460 // Look for the label.
461 int iw = 0;
462 bool found = false;
463 for (int i = nWeightingFields; i--;) {
464 if (wfields[i] == label) {
465 iw = i;
466 found = true;
467 break;
468 }
469 }
470
471 // Do not proceed if the requested weighting field does not exist.
472 if (!found) return;
473 // Check if the weighting field is properly initialised.
474 if (!wfieldsOk[iw]) return;
475
476 // Copy the coordinates.
477 double x = xin, y = yin, z = zin;
478
479 // Map the coordinates onto field map coordinates
480 bool xmirr, ymirr, zmirr;
481 double rcoordinate, rotation;
482 MapCoordinates(x, y, z, xmirr, ymirr, zmirr, rcoordinate, rotation);
483
484 if (m_warning) PrintWarning("WeightingField");
485
486 // Find the element that contains this point.
487 double t1, t2, t3, t4, jac[4][4], det;
488 const int imap = FindElement13(x, y, z, t1, t2, t3, t4, jac, det);
489 // Check if the point is in the mesh.
490 if (imap < 0) return;
491
492 if (m_debug) {
493 PrintElement("WeightingField", x, y, z, t1, t2, t3, t4, imap, 10, iw);
494 }
495
496 const Element& element = elements[imap];
497 const Node& n0 = nodes[element.emap[0]];
498 const Node& n1 = nodes[element.emap[1]];
499 const Node& n2 = nodes[element.emap[2]];
500 const Node& n3 = nodes[element.emap[3]];
501 const Node& n4 = nodes[element.emap[4]];
502 const Node& n5 = nodes[element.emap[5]];
503 const Node& n6 = nodes[element.emap[6]];
504 const Node& n7 = nodes[element.emap[7]];
505 const Node& n8 = nodes[element.emap[8]];
506 const Node& n9 = nodes[element.emap[9]];
507 // Tetrahedral field
508 wx = -(n0.w[iw] * (4 * t1 - 1) * jac[0][1] +
509 n1.w[iw] * (4 * t2 - 1) * jac[1][1] +
510 n2.w[iw] * (4 * t3 - 1) * jac[2][1] +
511 n3.w[iw] * (4 * t4 - 1) * jac[3][1] +
512 n4.w[iw] * (4 * t2 * jac[0][1] + 4 * t1 * jac[1][1]) +
513 n5.w[iw] * (4 * t3 * jac[0][1] + 4 * t1 * jac[2][1]) +
514 n6.w[iw] * (4 * t4 * jac[0][1] + 4 * t1 * jac[3][1]) +
515 n7.w[iw] * (4 * t3 * jac[1][1] + 4 * t2 * jac[2][1]) +
516 n8.w[iw] * (4 * t4 * jac[1][1] + 4 * t2 * jac[3][1]) +
517 n9.w[iw] * (4 * t4 * jac[2][1] + 4 * t3 * jac[3][1])) /
518 det;
519
520 wy = -(n0.w[iw] * (4 * t1 - 1) * jac[0][2] +
521 n1.w[iw] * (4 * t2 - 1) * jac[1][2] +
522 n2.w[iw] * (4 * t3 - 1) * jac[2][2] +
523 n3.w[iw] * (4 * t4 - 1) * jac[3][2] +
524 n4.w[iw] * (4 * t2 * jac[0][2] + 4 * t1 * jac[1][2]) +
525 n5.w[iw] * (4 * t3 * jac[0][2] + 4 * t1 * jac[2][2]) +
526 n6.w[iw] * (4 * t4 * jac[0][2] + 4 * t1 * jac[3][2]) +
527 n7.w[iw] * (4 * t3 * jac[1][2] + 4 * t2 * jac[2][2]) +
528 n8.w[iw] * (4 * t4 * jac[1][2] + 4 * t2 * jac[3][2]) +
529 n9.w[iw] * (4 * t4 * jac[2][2] + 4 * t3 * jac[3][2])) /
530 det;
531
532 wz = -(n0.w[iw] * (4 * t1 - 1) * jac[0][3] +
533 n1.w[iw] * (4 * t2 - 1) * jac[1][3] +
534 n2.w[iw] * (4 * t3 - 1) * jac[2][3] +
535 n3.w[iw] * (4 * t4 - 1) * jac[3][3] +
536 n4.w[iw] * (4 * t2 * jac[0][3] + 4 * t1 * jac[1][3]) +
537 n5.w[iw] * (4 * t3 * jac[0][3] + 4 * t1 * jac[2][3]) +
538 n6.w[iw] * (4 * t4 * jac[0][3] + 4 * t1 * jac[3][3]) +
539 n7.w[iw] * (4 * t3 * jac[1][3] + 4 * t2 * jac[2][3]) +
540 n8.w[iw] * (4 * t4 * jac[1][3] + 4 * t2 * jac[3][3]) +
541 n9.w[iw] * (4 * t4 * jac[2][3] + 4 * t3 * jac[3][3])) /
542 det;
543
544 // Transform field to global coordinates
545 UnmapFields(wx, wy, wz, x, y, z, xmirr, ymirr, zmirr, rcoordinate, rotation);
546}

◆ WeightingPotential()

double Garfield::ComponentComsol::WeightingPotential ( const double  x,
const double  y,
const double  z,
const std::string &  label 
)
virtual

Implements Garfield::ComponentFieldMap.

Definition at line 548 of file ComponentComsol.cc.

550 {
551
552 // Do not proceed if not properly initialised.
553 if (!m_ready) return 0.;
554
555 // Look for the label.
556 int iw = 0;
557 bool found = false;
558 for (int i = nWeightingFields; i--;) {
559 if (wfields[i] == label) {
560 iw = i;
561 found = true;
562 break;
563 }
564 }
565
566 // Do not proceed if the requested weighting field does not exist.
567 if (!found) return 0.;
568 // Check if the weighting field is properly initialised.
569 if (!wfieldsOk[iw]) return 0.;
570
571 // Copy the coordinates.
572 double x = xin, y = yin, z = zin;
573
574 // Map the coordinates onto field map coordinates.
575 bool xmirr, ymirr, zmirr;
576 double rcoordinate, rotation;
577 MapCoordinates(x, y, z, xmirr, ymirr, zmirr, rcoordinate, rotation);
578
579 if (m_warning) PrintWarning("WeightingPotential");
580
581 // Find the element that contains this point.
582 double t1, t2, t3, t4, jac[4][4], det;
583 const int imap = FindElement13(x, y, z, t1, t2, t3, t4, jac, det);
584 if (imap < 0) return 0.;
585
586 if (m_debug) {
587 PrintElement("WeightingPotential", x, y, z, t1, t2, t3, t4, imap, 10, iw);
588 }
589
590 const Element& element = elements[imap];
591 const Node& n0 = nodes[element.emap[0]];
592 const Node& n1 = nodes[element.emap[1]];
593 const Node& n2 = nodes[element.emap[2]];
594 const Node& n3 = nodes[element.emap[3]];
595 const Node& n4 = nodes[element.emap[4]];
596 const Node& n5 = nodes[element.emap[5]];
597 const Node& n6 = nodes[element.emap[6]];
598 const Node& n7 = nodes[element.emap[7]];
599 const Node& n8 = nodes[element.emap[8]];
600 const Node& n9 = nodes[element.emap[9]];
601 // Tetrahedral field
602 return n0.w[iw] * t1 * (2 * t1 - 1) + n1.w[iw] * t2 * (2 * t2 - 1) +
603 n2.w[iw] * t3 * (2 * t3 - 1) + n3.w[iw] * t4 * (2 * t4 - 1) +
604 4 * n4.w[iw] * t1 * t2 + 4 * n5.w[iw] * t1 * t3 +
605 4 * n6.w[iw] * t1 * t4 + 4 * n7.w[iw] * t2 * t3 +
606 4 * n8.w[iw] * t2 * t4 + 4 * n9.w[iw] * t3 * t4;
607}

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