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

Component for importing and interpolating two-dimensional ANSYS field maps. More...

#include <ComponentAnsys123.hh>

+ Inheritance diagram for Garfield::ComponentAnsys123:

Public Member Functions

 ComponentAnsys123 ()
 
 ~ComponentAnsys123 ()
 
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 elist="ELIST.lis", std::string nlist="NLIST.lis", std::string mplist="MPLIST.lis", std::string prnsol="PRNSOL.lis", std::string unit="cm")
 
bool SetWeightingField (std::string prnsol, 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 two-dimensional ANSYS field maps.

Definition at line 10 of file ComponentAnsys123.hh.

Constructor & Destructor Documentation

◆ ComponentAnsys123()

Garfield::ComponentAnsys123::ComponentAnsys123 ( )

Definition at line 10 of file ComponentAnsys123.cc.

11
12 m_className = "ComponentAnsys123";
13}
std::string m_className
Class name.

◆ ~ComponentAnsys123()

Garfield::ComponentAnsys123::~ComponentAnsys123 ( )
inline

Definition at line 16 of file ComponentAnsys123.hh.

16{}

Member Function Documentation

◆ ElectricField() [1/2]

void Garfield::ComponentAnsys123::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 796 of file ComponentAnsys123.cc.

799 {
800
801 // Copy the coordinates
802 double x = xin, y = yin, z = zin;
803
804 // Map the coordinates onto field map coordinates
805 bool xmirr, ymirr, zmirr;
806 double rcoordinate, rotation;
807 MapCoordinates(x, y, z, xmirr, ymirr, zmirr, rcoordinate, rotation);
808
809 // Initial values
810 ex = ey = ez = volt = 0.;
811 status = 0;
812 m = NULL;
813
814 // Do not proceed if not properly initialised.
815 if (!m_ready) {
816 status = -10;
817 PrintNotReady("ElectricField");
818 return;
819 }
820
821 if (m_warning) PrintWarning("ElectricField");
822
823 // Find the element that contains this point
824 double t1, t2, t3, t4, jac[4][4], det;
825 const int imap = FindElement13(x, y, z, t1, t2, t3, t4, jac, det);
826 if (imap < 0) {
827 if (m_debug) {
828 std::cerr << m_className << "::ElectricField:\n";
829 std::cerr << " Point (" << x << ", " << y << ", " << z
830 << ") not in the mesh.\n";
831 }
832 status = -6;
833 return;
834 }
835
836 if (m_debug) {
837 PrintElement("ElectricField", x, y, z, t1, t2, t3, t4, imap, 10);
838 }
839
840 const Element& element = elements[imap];
841 const Node& n0 = nodes[element.emap[0]];
842 const Node& n1 = nodes[element.emap[1]];
843 const Node& n2 = nodes[element.emap[2]];
844 const Node& n3 = nodes[element.emap[3]];
845 const Node& n4 = nodes[element.emap[4]];
846 const Node& n5 = nodes[element.emap[5]];
847 const Node& n6 = nodes[element.emap[6]];
848 const Node& n7 = nodes[element.emap[7]];
849 const Node& n8 = nodes[element.emap[8]];
850 const Node& n9 = nodes[element.emap[9]];
851 // Tetrahedral field
852 const double invdet = 1. / det;
853 volt = n0.v * t1 * (2 * t1 - 1) + n1.v * t2 * (2 * t2 - 1) +
854 n2.v * t3 * (2 * t3 - 1) + n3.v * t4 * (2 * t4 - 1) +
855 4 * n4.v * t1 * t2 + 4 * n5.v * t1 * t3 + 4 * n6.v * t1 * t4 +
856 4 * n7.v * t2 * t3 + 4 * n8.v * t2 * t4 + 4 * n9.v * t3 * t4;
857
858 ex = -(n0.v * (4 * t1 - 1) * jac[0][1] + n1.v * (4 * t2 - 1) * jac[1][1] +
859 n2.v * (4 * t3 - 1) * jac[2][1] + n3.v * (4 * t4 - 1) * jac[3][1] +
860 n4.v * (4 * t2 * jac[0][1] + 4 * t1 * jac[1][1]) +
861 n5.v * (4 * t3 * jac[0][1] + 4 * t1 * jac[2][1]) +
862 n6.v * (4 * t4 * jac[0][1] + 4 * t1 * jac[3][1]) +
863 n7.v * (4 * t3 * jac[1][1] + 4 * t2 * jac[2][1]) +
864 n8.v * (4 * t4 * jac[1][1] + 4 * t2 * jac[3][1]) +
865 n9.v * (4 * t4 * jac[2][1] + 4 * t3 * jac[3][1])) * invdet;
866
867 ey = -(n0.v * (4 * t1 - 1) * jac[0][2] + n1.v * (4 * t2 - 1) * jac[1][2] +
868 n2.v * (4 * t3 - 1) * jac[2][2] + n3.v * (4 * t4 - 1) * jac[3][2] +
869 n4.v * (4 * t2 * jac[0][2] + 4 * t1 * jac[1][2]) +
870 n5.v * (4 * t3 * jac[0][2] + 4 * t1 * jac[2][2]) +
871 n6.v * (4 * t4 * jac[0][2] + 4 * t1 * jac[3][2]) +
872 n7.v * (4 * t3 * jac[1][2] + 4 * t2 * jac[2][2]) +
873 n8.v * (4 * t4 * jac[1][2] + 4 * t2 * jac[3][2]) +
874 n9.v * (4 * t4 * jac[2][2] + 4 * t3 * jac[3][2])) * invdet;
875
876 ez = -(n0.v * (4 * t1 - 1) * jac[0][3] + n1.v * (4 * t2 - 1) * jac[1][3] +
877 n2.v * (4 * t3 - 1) * jac[2][3] + n3.v * (4 * t4 - 1) * jac[3][3] +
878 n4.v * (4 * t2 * jac[0][3] + 4 * t1 * jac[1][3]) +
879 n5.v * (4 * t3 * jac[0][3] + 4 * t1 * jac[2][3]) +
880 n6.v * (4 * t4 * jac[0][3] + 4 * t1 * jac[3][3]) +
881 n7.v * (4 * t3 * jac[1][3] + 4 * t2 * jac[2][3]) +
882 n8.v * (4 * t4 * jac[1][3] + 4 * t2 * jac[3][3]) +
883 n9.v * (4 * t4 * jac[2][3] + 4 * t3 * jac[3][3])) * invdet;
884
885 // Transform field to global coordinates
886 UnmapFields(ex, ey, ez, x, y, z, xmirr, ymirr, zmirr, rcoordinate, rotation);
887
888 // Drift medium?
889 if (m_debug) {
890 std::cout << m_className << "::ElectricField:\n";
891 std::cout << " Material " << element.matmap << ", drift flag "
892 << materials[element.matmap].driftmedium << ".\n";
893 }
894 m = materials[element.matmap].medium;
895 status = -5;
896 if (materials[element.matmap].driftmedium) {
897 if (m && m->IsDriftable()) status = 0;
898 }
899}
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::ComponentAnsys123::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 788 of file ComponentAnsys123.cc.

790 {
791
792 double v = 0.;
793 ElectricField(x, y, z, ex, ey, ez, v, m, status);
794}
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::ComponentAnsys123::GetAspectRatio ( const unsigned int  i,
double &  dmin,
double &  dmax 
)
protectedvirtual

Implements Garfield::ComponentFieldMap.

Definition at line 1124 of file ComponentAnsys123.cc.

1125 {
1126
1127 if (i >= elements.size()) {
1128 dmin = dmax = 0.;
1129 return;
1130 }
1131
1132 const Element& element = elements[i];
1133 const int np = 4;
1134 // Loop over all pairs of vertices.
1135 for (int j = 0; j < np - 1; ++j) {
1136 const Node& nj = nodes[element.emap[j]];
1137 for (int k = j + 1; k < np; ++k) {
1138 const Node& nk = nodes[element.emap[k]];
1139 // Compute distance.
1140 const double dx = nj.x - nk.x;
1141 const double dy = nj.y - nk.y;
1142 const double dz = nj.z - nk.z;
1143 const double dist = sqrt(dx * dx + dy * dy + dz * dz);
1144 if (k == 1) {
1145 dmin = dmax = dist;
1146 } else {
1147 if (dist < dmin) dmin = dist;
1148 if (dist > dmax) dmax = dist;
1149 }
1150 }
1151 }
1152}
DoubleAc sqrt(const DoubleAc &f)
Definition: DoubleAc.cpp:314

◆ GetElementVolume()

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

Implements Garfield::ComponentFieldMap.

Definition at line 1105 of file ComponentAnsys123.cc.

1105 {
1106
1107 if (i >= elements.size()) return 0.;
1108 const Element& element = elements[i];
1109 const Node& n0 = nodes[element.emap[0]];
1110 const Node& n1 = nodes[element.emap[1]];
1111 const Node& n2 = nodes[element.emap[2]];
1112 const Node& n3 = nodes[element.emap[3]];
1113 const double vol =
1114 fabs((n3.x - n0.x) *
1115 ((n1.y - n0.y) * (n2.z - n0.z) - (n2.y - n0.y) * (n1.z - n0.z)) +
1116 (n3.y - n0.y) *
1117 ((n1.z - n0.z) * (n2.x - n0.x) - (n2.z - n0.z) * (n1.x - n0.x)) +
1118 (n3.z - n0.z) * ((n1.x - n0.x) * (n2.y - n0.y) -
1119 (n3.x - n0.x) * (n1.y - n0.y))) /
1120 6.;
1121 return vol;
1122}
DoubleAc fabs(const DoubleAc &f)
Definition: DoubleAc.h:615

◆ GetMedium()

Medium * Garfield::ComponentAnsys123::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 1057 of file ComponentAnsys123.cc.

1058 {
1059
1060 // Copy the coordinates.
1061 double x = xin, y = yin, z = zin;
1062
1063 // Map the coordinates onto field map coordinates.
1064 bool xmirr, ymirr, zmirr;
1065 double rcoordinate, rotation;
1066 MapCoordinates(x, y, z, xmirr, ymirr, zmirr, rcoordinate, rotation);
1067
1068 // Do not proceed if not properly initialised.
1069 if (!m_ready) {
1070 std::cerr << m_className << "::GetMedium:\n";
1071 std::cerr << " Field map not available for interpolation.\n";
1072 return NULL;
1073 }
1074 if (m_warning) PrintWarning("GetMedium");
1075
1076 // Find the element that contains this point.
1077 double t1, t2, t3, t4, jac[4][4], det;
1078 const int imap = FindElement13(x, y, z, t1, t2, t3, t4, jac, det);
1079 if (imap < 0) {
1080 if (m_debug) {
1081 std::cerr << m_className << "::GetMedium:\n";
1082 std::cerr << " Point (" << x << ", " << y << ", " << z
1083 << ") not in the mesh.\n";
1084 }
1085 return NULL;
1086 }
1087 const Element& element = elements[imap];
1088 if (element.matmap >= m_nMaterials) {
1089 if (m_debug) {
1090 std::cerr << m_className << "::GetMedium:\n";
1091 std::cerr << " Point (" << x << ", " << y << ", " << z << ")"
1092 << " has out of range material number " << imap << ".\n";
1093 }
1094 return NULL;
1095 }
1096
1097 if (m_debug) {
1098 PrintElement("GetMedium", x, y, z, t1, t2, t3, t4, imap, 10);
1099 }
1100
1101 // Assign a medium.
1102 return materials[element.matmap].medium;
1103}

◆ Initialise()

bool Garfield::ComponentAnsys123::Initialise ( std::string  elist = "ELIST.lis",
std::string  nlist = "NLIST.lis",
std::string  mplist = "MPLIST.lis",
std::string  prnsol = "PRNSOL.lis",
std::string  unit = "cm" 
)

Definition at line 15 of file ComponentAnsys123.cc.

17 {
18
19 m_ready = false;
20 m_warning = false;
21 m_nWarnings = 10;
22 // Keep track of the success.
23 bool ok = true;
24
25 // Buffer for reading
26 const int size = 100;
27 char line[size];
28
29 // Open the material list.
30 std::ifstream fmplist;
31 fmplist.open(mplist.c_str(), std::ios::in);
32 if (fmplist.fail()) {
33 std::cerr << m_className << "::Initialise:\n";
34 std::cerr << " Could not open material file " << mplist
35 << " for reading.\n",
36 std::cerr << " The file perhaps does not exist.\n";
37 return false;
38 }
39
40 // Read the material list.
41 m_nMaterials = 0;
42 long il = 0;
43 unsigned int icurrmat = 0;
44 bool readerror = false;
45 while (fmplist.getline(line, size, '\n')) {
46 il++;
47 // Skip page feed
48 if (strcmp(line, "1") == 0) {
49 fmplist.getline(line, size, '\n');
50 il++;
51 fmplist.getline(line, size, '\n');
52 il++;
53 fmplist.getline(line, size, '\n');
54 il++;
55 fmplist.getline(line, size, '\n');
56 il++;
57 fmplist.getline(line, size, '\n');
58 il++;
59 continue;
60 }
61 // Split the line in tokens
62 char* token = NULL;
63 token = strtok(line, " ");
64 // Skip blank lines and headers
65 if (!token || strcmp(token, " ") == 0 || strcmp(token, "\n") == 0 ||
66 strcmp(token, "TEMPERATURE") == 0 || strcmp(token, "PROPERTY=") == 0 ||
67 int(token[0]) == 10 || int(token[0]) == 13)
68 continue;
69 // Read number of materials,
70 // ensure it does not exceed the maximum and initialise the list
71 if (strcmp(token, "LIST") == 0) {
72 token = strtok(NULL, " ");
73 token = strtok(NULL, " ");
74 token = strtok(NULL, " ");
75 token = strtok(NULL, " ");
76 m_nMaterials = ReadInteger(token, -1, readerror);
77 if (readerror) {
78 std::cerr << m_className << "::Initialise:\n";
79 std::cerr << " Error reading file " << mplist << " (line " << il
80 << ").\n";
81 fmplist.close();
82 ok = false;
83 return false;
84 }
85 materials.resize(m_nMaterials);
86 for (unsigned int i = 0; i < m_nMaterials; ++i) {
87 materials[i].ohm = -1;
88 materials[i].eps = -1;
89 materials[i].medium = NULL;
90 }
91 if (m_debug) {
92 std::cout << m_className << "::Initialise:\n";
93 std::cout << " Number of materials: " << m_nMaterials << "\n";
94 }
95 } else if (strcmp(token, "MATERIAL") == 0) {
96 // Version 12 format: read material number
97 token = strtok(NULL, " ");
98 token = strtok(NULL, " ");
99 const int imat = ReadInteger(token, -1, readerror);
100 if (readerror || imat < 0) {
101 std::cerr << m_className << "::Initialise:\n";
102 std::cerr << " Error reading file " << mplist << " (line " << il
103 << ").\n";
104 fmplist.close();
105 ok = false;
106 return false;
107 }
108 icurrmat = imat;
109 } else if (strcmp(token, "TEMP") == 0) {
110 // Version 12 format: read property tag and value
111 token = strtok(NULL, " ");
112 int itype = 0;
113 if (strncmp(token, "PERX", 4) == 0) {
114 itype = 1;
115 } else if (strncmp(token, "RSVX", 4) == 0) {
116 itype = 2;
117 } else {
118 std::cerr << m_className << "::Initialise:\n";
119 std::cerr << " Found unknown material property flag " << token
120 << "\n";
121 std::cerr << " on material properties file " << mplist << " (line "
122 << il << ").\n";
123 ok = false;
124 }
125 fmplist.getline(line, size, '\n');
126 il++;
127 token = NULL;
128 token = strtok(line, " ");
129 if (icurrmat < 1 || icurrmat > m_nMaterials) {
130 std::cerr << m_className << "::Initialise:\n";
131 std::cerr << " Found out-of-range current material index "
132 << icurrmat << "\n";
133 std::cerr << " in material properties file " << mplist << ".\n";
134 ok = false;
135 readerror = false;
136 } else if (itype == 1) {
137 materials[icurrmat - 1].eps = ReadDouble(token, -1, readerror);
138 } else if (itype == 2) {
139 materials[icurrmat - 1].ohm = ReadDouble(token, -1, readerror);
140 }
141 if (readerror) {
142 std::cerr << m_className << "::Initialise:\n";
143 std::cerr << " Error reading file " << mplist << " line " << il
144 << ").\n";
145 fmplist.close();
146 ok = false;
147 return false;
148 }
149 } else if (strcmp(token, "PROPERTY") == 0) {
150 // Version 11 format
151 token = strtok(NULL, " ");
152 token = strtok(NULL, " ");
153 int itype = 0;
154 if (strcmp(token, "PERX") == 0) {
155 itype = 1;
156 } else if (strcmp(token, "RSVX") == 0) {
157 itype = 2;
158 } else {
159 std::cerr << m_className << "::Initialise:\n";
160 std::cerr << " Found unknown material property flag " << token
161 << "\n";
162 std::cerr << " on material properties file " << mplist << " (line "
163 << il << ").\n";
164 ok = false;
165 }
166 token = strtok(NULL, " ");
167 token = strtok(NULL, " ");
168 int imat = ReadInteger(token, -1, readerror);
169 if (readerror) {
170 std::cerr << m_className << "::Initialise:\n";
171 std::cerr << " Error reading file " << mplist << " (line " << il
172 << ").\n";
173 fmplist.close();
174 ok = false;
175 return false;
176 } else if (imat < 1 || imat > (int)m_nMaterials) {
177 std::cerr << m_className << "::Initialise:\n";
178 std::cerr << " Found out-of-range material index " << imat << "\n";
179 std::cerr << " in material properties file " << mplist << ".\n";
180 ok = false;
181 } else {
182 fmplist.getline(line, size, '\n');
183 il++;
184 fmplist.getline(line, size, '\n');
185 il++;
186 token = NULL;
187 token = strtok(line, " ");
188 token = strtok(NULL, " ");
189 if (itype == 1) {
190 materials[imat - 1].eps = ReadDouble(token, -1, readerror);
191 } else if (itype == 2) {
192 materials[imat - 1].ohm = ReadDouble(token, -1, readerror);
193 }
194 if (readerror) {
195 std::cerr << m_className << "::Initialise:\n";
196 std::cerr << " Error reading file " << mplist << " (line " << il
197 << ").\n";
198 fmplist.close();
199 ok = false;
200 return false;
201 }
202 }
203 }
204 }
205
206 // Close the file
207 fmplist.close();
208
209 // Find the lowest epsilon, check for eps = 0, set default drift media
210 double epsmin = -1;
211 unsigned int iepsmin = 0;
212 for (unsigned int imat = 0; imat < m_nMaterials; ++imat) {
213 if (materials[imat].eps < 0) continue;
214 if (materials[imat].eps == 0) {
215 std::cerr << m_className << "::Initialise:\n";
216 std::cerr << " Material " << imat
217 << " has been assigned a permittivity\n";
218 std::cerr << " equal to zero in " << mplist << ".\n";
219 ok = false;
220 } else if (epsmin < 0. || epsmin > materials[imat].eps) {
221 epsmin = materials[imat].eps;
222 iepsmin = imat;
223 }
224 }
225
226 if (epsmin < 0.) {
227 std::cerr << m_className << "::Initialise:\n";
228 std::cerr << " No material with positive permittivity found \n";
229 std::cerr << " in material list " << mplist << ".\n";
230 ok = false;
231 } else {
232 for (unsigned int imat = 0; imat < m_nMaterials; ++imat) {
233 if (imat == iepsmin) {
234 materials[imat].driftmedium = true;
235 } else {
236 materials[imat].driftmedium = false;
237 }
238 }
239 }
240
241 // Tell how many lines read
242 std::cout << m_className << "::Initialise:\n";
243 std::cout << " Read properties of " << m_nMaterials
244 << " materials from file " << mplist << ".\n";
245 if (m_debug) PrintMaterials();
246
247 // Open the element list
248 std::ifstream felist;
249 felist.open(elist.c_str(), std::ios::in);
250 if (felist.fail()) {
251 std::cerr << m_className << "::Initialise:\n";
252 std::cerr << " Could not open element file " << elist
253 << " for reading.\n";
254 std::cerr << " The file perhaps does not exist.\n";
255 return false;
256 }
257
258 // Read the element list
259 elements.clear();
260 nElements = 0;
261 Element newElement;
262 int nbackground = 0;
263 il = 0;
264 int highestnode = 0;
265 while (felist.getline(line, size, '\n')) {
266 il++;
267 // Skip page feed
268 if (strcmp(line, "1") == 0) {
269 felist.getline(line, size, '\n');
270 il++;
271 felist.getline(line, size, '\n');
272 il++;
273 felist.getline(line, size, '\n');
274 il++;
275 felist.getline(line, size, '\n');
276 il++;
277 felist.getline(line, size, '\n');
278 il++;
279 continue;
280 }
281 // Split the line in tokens
282 char* token = NULL;
283 // Split into tokens
284 token = strtok(line, " ");
285 // Skip blank lines and headers
286 if (!token || strcmp(token, " ") == 0 || strcmp(token, "\n") == 0 ||
287 int(token[0]) == 10 || int(token[0]) == 13 ||
288 strcmp(token, "LIST") == 0 || strcmp(token, "ELEM") == 0) {
289 continue;
290 }
291 // Read the element
292 int ielem = ReadInteger(token, -1, readerror);
293 token = strtok(NULL, " ");
294 int imat = ReadInteger(token, -1, readerror);
295 token = strtok(NULL, " ");
296 token = strtok(NULL, " ");
297 token = strtok(NULL, " ");
298 token = strtok(NULL, " ");
299 token = strtok(NULL, " ");
300 int in0 = ReadInteger(token, -1, readerror);
301 token = strtok(NULL, " ");
302 int in1 = ReadInteger(token, -1, readerror);
303 token = strtok(NULL, " ");
304 int in2 = ReadInteger(token, -1, readerror);
305 token = strtok(NULL, " ");
306 int in3 = ReadInteger(token, -1, readerror);
307 token = strtok(NULL, " ");
308 int in4 = ReadInteger(token, -1, readerror);
309 token = strtok(NULL, " ");
310 int in5 = ReadInteger(token, -1, readerror);
311 token = strtok(NULL, " ");
312 int in6 = ReadInteger(token, -1, readerror);
313 token = strtok(NULL, " ");
314 int in7 = ReadInteger(token, -1, readerror);
315 if (!felist.getline(line, size, '\n')) {
316 std::cerr << m_className << "::Initialise:\n";
317 std::cerr << " Error reading element " << ielem << ".\n";
318 ok = false;
319 break;
320 }
321 ++il;
322 token = NULL;
323 token = strtok(line, " ");
324 int in8 = ReadInteger(token, -1, readerror);
325 token = strtok(NULL, " ");
326 int in9 = ReadInteger(token, -1, readerror);
327
328 // Check synchronisation
329 if (readerror) {
330 std::cerr << m_className << "::Initialise:\n";
331 std::cerr << " Error reading file " << elist << " (line " << il
332 << ").\n";
333 felist.close();
334 ok = false;
335 return false;
336 } else if (ielem - 1 != nElements + nbackground) {
337 std::cerr << m_className << "::Initialise:\n";
338 std::cerr << " Synchronisation lost on file " << elist << " (line "
339 << il << ").\n";
340 std::cerr << " Element: " << ielem << " (expected " << nElements
341 << "), material: " << imat << ",\n";
342 std::cerr << " nodes: (" << in0 << ", " << in1 << ", " << in2 << ", "
343 << in3 << ", " << in4 << ", " << in5 << ", " << in6 << ", "
344 << in7 << ", " << in8 << ", " << in9 << ")\n";
345 ok = false;
346 }
347
348 // Check the material number and ensure that epsilon is non-negative
349 if (imat < 1 || imat > (int)m_nMaterials) {
350 std::cerr << m_className << "::Initialise:\n";
351 std::cerr << " Out-of-range material number on file " << elist
352 << " (line " << il << ").\n";
353 std::cerr << " Element: " << ielem << ", material: " << imat << ",\n";
354 std::cerr << " nodes: (" << in0 << ", " << in1 << ", " << in2 << ", "
355 << in3 << ", " << in4 << ", " << in5 << ", " << in6 << ", "
356 << in7 << ", " << in8 << ", " << in9 << ")\n";
357 ok = false;
358 }
359 if (materials[imat - 1].eps < 0) {
360 std::cerr << m_className << "::Initialise:\n";
361 std::cerr << " Element " << ielem << " in element list " << elist
362 << "\n";
363 std::cerr << " uses material " << imat
364 << " which has not been assigned\n";
365 std::cerr << " a positive permittivity in material list " << mplist
366 << ".\n";
367 ok = false;
368 }
369
370 // Check the node numbers
371 if (in0 < 1 || in1 < 1 || in2 < 1 || in3 < 1 || in4 < 1 || in5 < 1 ||
372 in6 < 1 || in7 < 1 || in8 < 1 || in9 < 1) {
373 std::cerr << m_className << "::Initialise:\n";
374 std::cerr << " Found a node number < 1 on file " << elist << " (line "
375 << il << ").\n";
376 std::cerr << " Element: " << ielem << ", material: " << imat << ",\n";
377 std::cerr << " nodes: (" << in0 << ", " << in1 << ", " << in2 << ", "
378 << in3 << ", " << in4 << ", " << in5 << ", " << in6 << ", "
379 << in7 << ", " << in8 << ", " << in9 << ")\n";
380 ok = false;
381 }
382 if (in0 > highestnode) highestnode = in0;
383 if (in1 > highestnode) highestnode = in1;
384 if (in2 > highestnode) highestnode = in2;
385 if (in3 > highestnode) highestnode = in3;
386 if (in4 > highestnode) highestnode = in4;
387 if (in5 > highestnode) highestnode = in5;
388 if (in6 > highestnode) highestnode = in6;
389 if (in7 > highestnode) highestnode = in7;
390 if (in8 > highestnode) highestnode = in8;
391 if (in9 > highestnode) highestnode = in9;
392
393 // Skip quadrilaterals which are background.
394 if (m_deleteBackground && materials[imat - 1].ohm == 0) {
395 nbackground++;
396 continue;
397 }
398
399 // These elements must not be degenerate.
400 if (in0 == in1 || in0 == in2 || in0 == in3 || in0 == in4 || in0 == in5 ||
401 in0 == in6 || in0 == in7 || in0 == in8 || in0 == in9 || in1 == in2 ||
402 in1 == in3 || in1 == in4 || in1 == in5 || in1 == in6 || in1 == in7 ||
403 in1 == in8 || in1 == in9 || in2 == in3 || in2 == in4 || in2 == in5 ||
404 in2 == in6 || in2 == in7 || in2 == in8 || in2 == in9 || in3 == in4 ||
405 in3 == in5 || in3 == in6 || in3 == in7 || in3 == in8 || in3 == in9 ||
406 in4 == in5 || in4 == in6 || in4 == in7 || in4 == in8 || in4 == in9 ||
407 in5 == in6 || in5 == in7 || in5 == in8 || in5 == in9 || in6 == in7 ||
408 in6 == in8 || in6 == in9 || in7 == in8 || in7 == in9 || in8 == in9) {
409 std::cerr << m_className << "::Initialise:\n";
410 std::cerr << " Element " << ielem << " of file " << elist
411 << " is degenerate,\n";
412 std::cerr << " no such elements allowed in this type of map.\n";
413 ok = false;
414 }
415
416 newElement.degenerate = false;
417
418 // Store the material reference
419 newElement.matmap = imat - 1;
420
421 // Node references
422 newElement.emap[0] = in0 - 1;
423 newElement.emap[1] = in1 - 1;
424 newElement.emap[2] = in2 - 1;
425 newElement.emap[3] = in3 - 1;
426 newElement.emap[4] = in4 - 1;
427 newElement.emap[7] = in5 - 1;
428 newElement.emap[5] = in6 - 1;
429 newElement.emap[6] = in7 - 1;
430 newElement.emap[8] = in8 - 1;
431 newElement.emap[9] = in9 - 1;
432 elements.push_back(newElement);
433 nElements++;
434 }
435 // Close the file
436 felist.close();
437
438 // Tell how many lines read.
439 std::cout << m_className << "::Initialise:\n";
440 std::cout << " Read " << nElements << " elements from file " << elist
441 << ",\n";
442 std::cout << " highest node number: " << highestnode << ",\n";
443 std::cout << " background elements skipped: " << nbackground << "\n";
444 // Check the value of the unit
445 double funit;
446 if (strcmp(unit.c_str(), "mum") == 0 || strcmp(unit.c_str(), "micron") == 0 ||
447 strcmp(unit.c_str(), "micrometer") == 0) {
448 funit = 0.0001;
449 } else if (strcmp(unit.c_str(), "mm") == 0 ||
450 strcmp(unit.c_str(), "millimeter") == 0) {
451 funit = 0.1;
452 } else if (strcmp(unit.c_str(), "cm") == 0 ||
453 strcmp(unit.c_str(), "centimeter") == 0) {
454 funit = 1.0;
455 } else if (strcmp(unit.c_str(), "m") == 0 ||
456 strcmp(unit.c_str(), "meter") == 0) {
457 funit = 100.0;
458 } else {
459 std::cerr << m_className << "::Initialise:\n";
460 std::cerr << " Unknown length unit " << unit << ".\n";
461 ok = false;
462 funit = 1.0;
463 }
464 if (m_debug) {
465 std::cout << m_className << ":Initialise:\n";
466 std::cout << " Unit scaling factor = " << funit << ".\n";
467 }
468
469 // Open the node list
470 std::ifstream fnlist;
471 fnlist.open(nlist.c_str(), std::ios::in);
472 if (fnlist.fail()) {
473 std::cerr << m_className << "::Initialise:\n";
474 std::cerr << " Could not open nodes file " << nlist << " for reading.\n";
475 std::cerr << " The file perhaps does not exist.\n";
476 return false;
477 }
478
479 // Read the node list
480 nodes.clear();
481 nNodes = 0;
482 Node newNode;
483 newNode.w.clear();
484 il = 0;
485 while (fnlist.getline(line, size, '\n')) {
486 il++;
487 // Skip page feed
488 if (strcmp(line, "1") == 0) {
489 fnlist.getline(line, size, '\n');
490 il++;
491 fnlist.getline(line, size, '\n');
492 il++;
493 fnlist.getline(line, size, '\n');
494 il++;
495 fnlist.getline(line, size, '\n');
496 il++;
497 fnlist.getline(line, size, '\n');
498 il++;
499 continue;
500 }
501 // Split the line in tokens
502 char* token = NULL;
503 token = strtok(line, " ");
504 // Skip blank lines and headers
505 if (!token || strcmp(token, " ") == 0 || strcmp(token, "\n") == 0 ||
506 int(token[0]) == 10 || int(token[0]) == 13 ||
507 strcmp(token, "LIST") == 0 || strcmp(token, "NODE") == 0)
508 continue;
509 // Read the element
510 int inode = ReadInteger(token, -1, readerror);
511 token = strtok(NULL, " ");
512 double xnode = ReadDouble(token, -1, readerror);
513 token = strtok(NULL, " ");
514 double ynode = ReadDouble(token, -1, readerror);
515 token = strtok(NULL, " ");
516 double znode = ReadDouble(token, -1, readerror);
517 // Check syntax
518 if (readerror) {
519 std::cerr << m_className << "::Initialise:\n";
520 std::cerr << " Error reading file " << nlist << " (line " << il
521 << ").\n";
522 fnlist.close();
523 ok = false;
524 return false;
525 }
526 // Check synchronisation
527 if (inode - 1 != nNodes) {
528 std::cerr << m_className << "::Initialise:\n";
529 std::cerr << " Synchronisation lost on file " << nlist << " (line "
530 << il << ").\n";
531 std::cerr << " Node: " << inode << " (expected " << nNodes
532 << "), (x,y,z) = (" << xnode << ", " << ynode << ", " << znode
533 << ")\n";
534 ok = false;
535 }
536 // Store the point coordinates
537 newNode.x = xnode * funit;
538 newNode.y = ynode * funit;
539 newNode.z = znode * funit;
540 nodes.push_back(newNode);
541 nNodes++;
542 }
543 // Close the file
544 fnlist.close();
545 // Tell how many lines read
546 std::cout << m_className << "::Initialise:\n";
547 std::cout << " Read " << nNodes << " nodes from file " << nlist << ".\n";
548 // Check number of nodes
549 if (nNodes != highestnode) {
550 std::cerr << m_className << "::Initialise:\n";
551 std::cerr << " Number of nodes read (" << nNodes << ") on " << nlist
552 << "\n";
553 std::cerr << " does not match element list (" << highestnode << ").\n";
554 ok = false;
555 }
556
557 // Open the voltage list
558 std::ifstream fprnsol;
559 fprnsol.open(prnsol.c_str(), std::ios::in);
560 if (fprnsol.fail()) {
561 std::cerr << m_className << "::Initialise:\n";
562 std::cerr << " Could not open potential file " << prnsol
563 << " for reading.\n";
564 std::cerr << " The file perhaps does not exist.\n";
565 return false;
566 }
567
568 // Read the voltage list
569 il = 0;
570 int nread = 0;
571 while (fprnsol.getline(line, size, '\n')) {
572 il++;
573 // Skip page feed
574 if (strcmp(line, "1") == 0) {
575 fprnsol.getline(line, size, '\n');
576 il++;
577 fprnsol.getline(line, size, '\n');
578 il++;
579 fprnsol.getline(line, size, '\n');
580 il++;
581 fprnsol.getline(line, size, '\n');
582 il++;
583 fprnsol.getline(line, size, '\n');
584 il++;
585 continue;
586 }
587 // Split the line in tokens
588 char* token = NULL;
589 token = strtok(line, " ");
590 // Skip blank lines and headers
591 if (!token || strcmp(token, " ") == 0 || strcmp(token, "\n") == 0 ||
592 int(token[0]) == 10 || int(token[0]) == 13 ||
593 strcmp(token, "PRINT") == 0 || strcmp(token, "*****") == 0 ||
594 strcmp(token, "LOAD") == 0 || strcmp(token, "TIME=") == 0 ||
595 strcmp(token, "MAXIMUM") == 0 || strcmp(token, "VALUE") == 0 ||
596 strcmp(token, "NODE") == 0)
597 continue;
598 // Read the element
599 int inode = ReadInteger(token, -1, readerror);
600 token = strtok(NULL, " ");
601 double volt = ReadDouble(token, -1, readerror);
602 // Check syntax
603 if (readerror) {
604 std::cerr << m_className << "::Initialise:\n";
605 std::cerr << " Error reading file " << prnsol << " (line << " << il
606 << ").\n";
607 fprnsol.close();
608 ok = false;
609 return false;
610 }
611 // Check node number and store if OK
612 if (inode < 1 || inode > highestnode) {
613 std::cerr << m_className << "::Initialise:\n";
614 std::cerr << " Node number " << inode << " out of range\n";
615 std::cerr << " on potential file " << prnsol << " (line " << il
616 << ").\n";
617 ok = false;
618 } else {
619 nodes[inode - 1].v = volt;
620 nread++;
621 }
622 }
623 // Close the file
624 fprnsol.close();
625 // Tell how many lines read
626 std::cout << m_className << "::Initialise:\n";
627 std::cout << " Read " << nread << " potentials from file " << prnsol
628 << ".\n";
629 // Check number of nodes
630 if (nread != nNodes) {
631 std::cerr << m_className << "::Initialise:\n";
632 std::cerr << " Number of nodes read (" << nread << ") on potential file "
633 << prnsol << "\n";
634 std::cerr << " does not match the node list (" << nNodes << ").\n";
635 ok = false;
636 }
637
638 // Set the ready flag
639 if (ok) {
640 m_ready = true;
641 } else {
642 std::cerr << m_className << "::Initialise:\n";
643 std::cerr
644 << " Field map could not be read and can not be interpolated.\n";
645 return false;
646 }
647
648 // Remove weighting fields (if any).
649 wfields.clear();
650 wfieldsOk.clear();
652
653 // Establish the ranges
654 SetRange();
656 return true;
657}
void UpdatePeriodicity()
Verify periodicities.
void PrintMaterials()
List all currently defined materials.
double ReadDouble(char *token, double def, bool &error)
int ReadInteger(char *token, int def, bool &error)
virtual void SetRange()
Calculate x, y, z, V and angular ranges.
std::vector< std::string > wfields

◆ IsInBoundingBox()

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

◆ SetWeightingField()

bool Garfield::ComponentAnsys123::SetWeightingField ( std::string  prnsol,
std::string  label 
)

Definition at line 659 of file ComponentAnsys123.cc.

660 {
661
662 if (!m_ready) {
663 PrintNotReady("SetWeightingField");
664 std::cerr << " Weighting field cannot be added.\n";
665 return false;
666 }
667
668 // Open the voltage list.
669 std::ifstream fprnsol;
670 fprnsol.open(prnsol.c_str(), std::ios::in);
671 if (fprnsol.fail()) {
672 std::cerr << m_className << "::SetWeightingField:\n";
673 std::cerr << " Could not open potential file " << prnsol
674 << " for reading.\n";
675 std::cerr << " The file perhaps does not exist.\n";
676 return false;
677 }
678
679 // Check if a weighting field with the same label already exists.
680 int iw = nWeightingFields;
681 for (int i = nWeightingFields; i--;) {
682 if (wfields[i] == label) {
683 iw = i;
684 break;
685 }
686 }
687 if (iw == nWeightingFields) {
691 for (int j = nNodes; j--;) {
692 nodes[j].w.resize(nWeightingFields);
693 }
694 } else {
695 std::cout << m_className << "::SetWeightingField:\n";
696 std::cout << " Replacing existing weighting field " << label << ".\n";
697 }
698 wfields[iw] = label;
699 wfieldsOk[iw] = false;
700
701 // Buffer for reading
702 const int size = 100;
703 char line[size];
704
705 bool ok = true;
706 // Read the voltage list.
707 int il = 0;
708 int nread = 0;
709 bool readerror = false;
710
711 while (fprnsol.getline(line, size, '\n')) {
712 il++;
713 // Skip page feed
714 if (strcmp(line, "1") == 0) {
715 fprnsol.getline(line, size, '\n');
716 il++;
717 fprnsol.getline(line, size, '\n');
718 il++;
719 fprnsol.getline(line, size, '\n');
720 il++;
721 fprnsol.getline(line, size, '\n');
722 il++;
723 fprnsol.getline(line, size, '\n');
724 il++;
725 continue;
726 }
727 // Split the line in tokens.
728 char* token = NULL;
729 token = strtok(line, " ");
730 // Skip blank lines and headers.
731 if (!token || strcmp(token, " ") == 0 || strcmp(token, "\n") == 0 ||
732 int(token[0]) == 10 || int(token[0]) == 13 ||
733 strcmp(token, "PRINT") == 0 || strcmp(token, "*****") == 0 ||
734 strcmp(token, "LOAD") == 0 || strcmp(token, "TIME=") == 0 ||
735 strcmp(token, "MAXIMUM") == 0 || strcmp(token, "VALUE") == 0 ||
736 strcmp(token, "NODE") == 0)
737 continue;
738 // Read the element.
739 int inode = ReadInteger(token, -1, readerror);
740 token = strtok(NULL, " ");
741 double volt = ReadDouble(token, -1, readerror);
742 // Check the syntax.
743 if (readerror) {
744 std::cerr << m_className << "::SetWeightingField:\n";
745 std::cerr << " Error reading file " << prnsol.c_str() << " (line "
746 << il << ").\n";
747 fprnsol.close();
748 return false;
749 }
750 // Check node number and store if OK.
751 if (inode < 1 || inode > nNodes) {
752 std::cerr << m_className << "::SetWeightingField:\n";
753 std::cerr << " Node number " << inode << " out of range\n";
754 std::cerr << " on potential file " << prnsol.c_str() << " (line " << il
755 << ").\n";
756 ok = false;
757 } else {
758 nodes[inode - 1].w[iw] = volt;
759 nread++;
760 }
761 }
762 // Close the file.
763 fprnsol.close();
764
765 std::cout << m_className << "::SetWeightingField:\n";
766 std::cout << " Read " << nread << " potentials from file "
767 << prnsol.c_str() << ".\n";
768 // Check the number of nodes.
769 if (nread != nNodes) {
770 std::cerr << m_className << "::SetWeightingField:\n";
771 std::cerr << " Number of nodes read (" << nread << ") "
772 << " on potential file " << prnsol.c_str() << "\n";
773 std::cerr << " does not match the node list (" << nNodes << ").\n";
774 ok = false;
775 }
776
777 // Set the ready flag.
778 wfieldsOk[iw] = ok;
779 if (!ok) {
780 std::cerr << m_className << "::SetWeightingField:\n";
781 std::cerr << " Field map could not be read "
782 << "and cannot be interpolated.\n";
783 return false;
784 }
785 return true;
786}

◆ UpdatePeriodicity()

void Garfield::ComponentAnsys123::UpdatePeriodicity ( )
inlineprotectedvirtual

Verify periodicities.

Implements Garfield::ComponentFieldMap.

Definition at line 49 of file ComponentAnsys123.hh.

Referenced by Initialise().

◆ WeightingField()

void Garfield::ComponentAnsys123::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 901 of file ComponentAnsys123.cc.

903 {
904
905 // Initial values
906 wx = wy = wz = 0;
907
908 // Do not proceed if not properly initialised.
909 if (!m_ready) return;
910
911 // Look for the label.
912 int iw = 0;
913 bool found = false;
914 for (int i = nWeightingFields; i--;) {
915 if (wfields[i] == label) {
916 iw = i;
917 found = true;
918 break;
919 }
920 }
921
922 // Do not proceed if the requested weighting field does not exist.
923 if (!found) return;
924 // Check if the weighting field is properly initialised.
925 if (!wfieldsOk[iw]) return;
926
927 // Copy the coordinates.
928 double x = xin, y = yin, z = zin;
929
930 // Map the coordinates onto field map coordinates
931 bool xmirr, ymirr, zmirr;
932 double rcoordinate, rotation;
933 MapCoordinates(x, y, z, xmirr, ymirr, zmirr, rcoordinate, rotation);
934
935 if (m_warning) PrintWarning("WeightingField");
936
937 // Find the element that contains this point.
938 double t1, t2, t3, t4, jac[4][4], det;
939 const int imap = FindElement13(x, y, z, t1, t2, t3, t4, jac, det);
940 // Check if the point is in the mesh.
941 if (imap < 0) return;
942
943 if (m_debug) {
944 PrintElement("WeightingField", x, y, z, t1, t2, t3, t4, imap, 10, iw);
945 }
946
947 const Element& element = elements[imap];
948 const Node& n0 = nodes[element.emap[0]];
949 const Node& n1 = nodes[element.emap[1]];
950 const Node& n2 = nodes[element.emap[2]];
951 const Node& n3 = nodes[element.emap[3]];
952 const Node& n4 = nodes[element.emap[4]];
953 const Node& n5 = nodes[element.emap[5]];
954 const Node& n6 = nodes[element.emap[6]];
955 const Node& n7 = nodes[element.emap[7]];
956 const Node& n8 = nodes[element.emap[8]];
957 const Node& n9 = nodes[element.emap[9]];
958 // Tetrahedral field
959 const double invdet = 1. / det;
960 wx = -(n0.w[iw] * (4 * t1 - 1) * jac[0][1] +
961 n1.w[iw] * (4 * t2 - 1) * jac[1][1] +
962 n2.w[iw] * (4 * t3 - 1) * jac[2][1] +
963 n3.w[iw] * (4 * t4 - 1) * jac[3][1] +
964 n4.w[iw] * (4 * t2 * jac[0][1] + 4 * t1 * jac[1][1]) +
965 n5.w[iw] * (4 * t3 * jac[0][1] + 4 * t1 * jac[2][1]) +
966 n6.w[iw] * (4 * t4 * jac[0][1] + 4 * t1 * jac[3][1]) +
967 n7.w[iw] * (4 * t3 * jac[1][1] + 4 * t2 * jac[2][1]) +
968 n8.w[iw] * (4 * t4 * jac[1][1] + 4 * t2 * jac[3][1]) +
969 n9.w[iw] * (4 * t4 * jac[2][1] + 4 * t3 * jac[3][1])) * invdet;
970
971 wy = -(n0.w[iw] * (4 * t1 - 1) * jac[0][2] +
972 n1.w[iw] * (4 * t2 - 1) * jac[1][2] +
973 n2.w[iw] * (4 * t3 - 1) * jac[2][2] +
974 n3.w[iw] * (4 * t4 - 1) * jac[3][2] +
975 n4.w[iw] * (4 * t2 * jac[0][2] + 4 * t1 * jac[1][2]) +
976 n5.w[iw] * (4 * t3 * jac[0][2] + 4 * t1 * jac[2][2]) +
977 n6.w[iw] * (4 * t4 * jac[0][2] + 4 * t1 * jac[3][2]) +
978 n7.w[iw] * (4 * t3 * jac[1][2] + 4 * t2 * jac[2][2]) +
979 n8.w[iw] * (4 * t4 * jac[1][2] + 4 * t2 * jac[3][2]) +
980 n9.w[iw] * (4 * t4 * jac[2][2] + 4 * t3 * jac[3][2])) * invdet;
981
982 wz = -(n0.w[iw] * (4 * t1 - 1) * jac[0][3] +
983 n1.w[iw] * (4 * t2 - 1) * jac[1][3] +
984 n2.w[iw] * (4 * t3 - 1) * jac[2][3] +
985 n3.w[iw] * (4 * t4 - 1) * jac[3][3] +
986 n4.w[iw] * (4 * t2 * jac[0][3] + 4 * t1 * jac[1][3]) +
987 n5.w[iw] * (4 * t3 * jac[0][3] + 4 * t1 * jac[2][3]) +
988 n6.w[iw] * (4 * t4 * jac[0][3] + 4 * t1 * jac[3][3]) +
989 n7.w[iw] * (4 * t3 * jac[1][3] + 4 * t2 * jac[2][3]) +
990 n8.w[iw] * (4 * t4 * jac[1][3] + 4 * t2 * jac[3][3]) +
991 n9.w[iw] * (4 * t4 * jac[2][3] + 4 * t3 * jac[3][3])) * invdet;
992
993 // Transform field to global coordinates
994 UnmapFields(wx, wy, wz, x, y, z, xmirr, ymirr, zmirr, rcoordinate, rotation);
995}

◆ WeightingPotential()

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

Implements Garfield::ComponentFieldMap.

Definition at line 997 of file ComponentAnsys123.cc.

999 {
1000
1001 // Do not proceed if not properly initialised.
1002 if (!m_ready) return 0.;
1003
1004 // Look for the label.
1005 int iw = 0;
1006 bool found = false;
1007 for (int i = nWeightingFields; i--;) {
1008 if (wfields[i] == label) {
1009 iw = i;
1010 found = true;
1011 break;
1012 }
1013 }
1014
1015 // Do not proceed if the requested weighting field does not exist.
1016 if (!found) return 0.;
1017 // Check if the weighting field is properly initialised.
1018 if (!wfieldsOk[iw]) return 0.;
1019
1020 // Copy the coordinates.
1021 double x = xin, y = yin, z = zin;
1022
1023 // Map the coordinates onto field map coordinates.
1024 bool xmirr, ymirr, zmirr;
1025 double rcoordinate, rotation;
1026 MapCoordinates(x, y, z, xmirr, ymirr, zmirr, rcoordinate, rotation);
1027
1028 if (m_warning) PrintWarning("WeightingPotential");
1029
1030 // Find the element that contains this point.
1031 double t1, t2, t3, t4, jac[4][4], det;
1032 const int imap = FindElement13(x, y, z, t1, t2, t3, t4, jac, det);
1033 if (imap < 0) return 0.;
1034
1035 if (m_debug) {
1036 PrintElement("WeightingPotential", x, y, z, t1, t2, t3, t4, imap, 10, iw);
1037 }
1038
1039 const Element& element = elements[imap];
1040 const Node& n0 = nodes[element.emap[0]];
1041 const Node& n1 = nodes[element.emap[1]];
1042 const Node& n2 = nodes[element.emap[2]];
1043 const Node& n3 = nodes[element.emap[3]];
1044 const Node& n4 = nodes[element.emap[4]];
1045 const Node& n5 = nodes[element.emap[5]];
1046 const Node& n6 = nodes[element.emap[6]];
1047 const Node& n7 = nodes[element.emap[7]];
1048 const Node& n8 = nodes[element.emap[8]];
1049 const Node& n9 = nodes[element.emap[9]];
1050 return n0.w[iw] * t1 * (2 * t1 - 1) + n1.w[iw] * t2 * (2 * t2 - 1) +
1051 n2.w[iw] * t3 * (2 * t3 - 1) + n3.w[iw] * t4 * (2 * t4 - 1) +
1052 4 * n4.w[iw] * t1 * t2 + 4 * n5.w[iw] * t1 * t3 +
1053 4 * n6.w[iw] * t1 * t4 + 4 * n7.w[iw] * t2 * t3 +
1054 4 * n8.w[iw] * t2 * t4 + 4 * n9.w[iw] * t3 * t4;
1055}

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