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

Base class for components based on finite-element field maps. More...

#include <ComponentFieldMap.hh>

+ Inheritance diagram for Garfield::ComponentFieldMap:

Classes

struct  Element
 
struct  Material
 
struct  Node
 

Public Member Functions

 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.
 
bool IsInBoundingBox (const double x, const double y, const double z) const
 
bool GetBoundingBox (double &xmin, double &ymin, double &zmin, double &xmax, double &ymax, double &zmax) override
 Get the bounding box coordinates.
 
bool GetVoltageRange (double &vmin, double &vmax) override
 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.
 
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.
 
void EnableCheckMapIndices ()
 
void DisableCheckMapIndices ()
 
void EnableDeleteBackgroundElements (const bool on=true)
 Option to eliminate mesh elements in conductors (default: on).
 
void EnableTetrahedralTreeForElementSearch (const bool on=true)
 
virtual MediumGetMedium (const double x, const double y, const double z)
 Get the medium at a given location (x, y, z).
 
- 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
 Calculate the drift field [V/cm] and potential [V] at (x, y, z).
 
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 DelayedWeightingField (const double x, const double y, const double z, const double t, double &wx, double &wy, double &wz, 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.
 
double IntegrateFluxCircle (const double xc, const double yc, const double r, const unsigned int nI=50)
 
double IntegrateFluxSphere (const double xc, const double yc, const double zc, const double r, const unsigned int nI=20)
 
double IntegrateFlux (const double x0, const double y0, const double z0, const double dx1, const double dy1, const double dz1, const double dx2, const double dy2, const double dz2, const unsigned int nU=20, const unsigned int nV=20)
 
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, const bool centre, double &rc)
 
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 Reset () override
 Reset the component.
 
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 Element &element, const unsigned int n, const int iw=-1) const
 
- Protected Member Functions inherited from Garfield::ComponentBase
virtual void Reset ()=0
 Reset the component.
 
virtual void UpdatePeriodicity ()=0
 Verify periodicities.
 

Protected Attributes

bool m_is3d = true
 
int nElements = -1
 
std::vector< Elementelements
 
int nNodes = -1
 
std::vector< Nodenodes
 
unsigned int m_nMaterials = 0
 
std::vector< Materialmaterials
 
int nWeightingFields = 0
 
std::vector< std::string > wfields
 
std::vector< bool > wfieldsOk
 
bool hasBoundingBox = false
 
std::array< double, 3 > m_minBoundingBox
 
std::array< double, 3 > m_maxBoundingBox
 
std::array< double, 3 > m_mapmin
 
std::array< double, 3 > m_mapmax
 
std::array< double, 3 > m_mapamin
 
std::array< double, 3 > m_mapamax
 
std::array< double, 3 > m_mapna
 
std::array< double, 3 > m_cells
 
double m_mapvmin
 
double m_mapvmax
 
std::array< bool, 3 > m_setang
 
bool m_deleteBackground = true
 
bool m_warning = false
 
unsigned int m_nWarnings = 0
 
- Protected Attributes inherited from Garfield::ComponentBase
std::string m_className = "ComponentBase"
 Class name.
 
GeometryBasem_geometry = nullptr
 Pointer to the geometry.
 
bool m_ready = false
 Ready for use?
 
bool m_activeTraps = false
 Does the component have traps?
 
bool m_hasVelocityMap = false
 Does the component have velocity maps?
 
std::array< bool, 3 > m_periodic = {{false, false, false}}
 Simple periodicity in x, y, z.
 
std::array< bool, 3 > m_mirrorPeriodic = {{false, false, false}}
 Mirror periodicity in x, y, z.
 
std::array< bool, 3 > m_axiallyPeriodic = {{false, false, false}}
 Axial periodicity in x, y, z.
 
std::array< bool, 3 > m_rotationSymmetric = {{false, false, false}}
 Rotation symmetry around x-axis, y-axis, z-axis.
 
double m_bx0 = 0.
 
double m_by0 = 0.
 
double m_bz0 = 0.
 
bool m_debug = false
 Switch on/off debugging messages.
 

Friends

class ViewFEMesh
 

Detailed Description

Base class for components based on finite-element field maps.

Definition at line 13 of file ComponentFieldMap.hh.

Constructor & Destructor Documentation

◆ ComponentFieldMap()

Garfield::ComponentFieldMap::ComponentFieldMap ( )

Constructor.

Definition at line 14 of file ComponentFieldMap.cc.

14 : ComponentBase() {
15 m_className = "ComponentFieldMap";
16}
ComponentBase()
Constructor.
Definition: ComponentBase.cc:9
std::string m_className
Class name.

◆ ~ComponentFieldMap()

Garfield::ComponentFieldMap::~ComponentFieldMap ( )
virtual

Destructor.

Definition at line 18 of file ComponentFieldMap.cc.

18 {
19 if (m_tetTree) delete m_tetTree;
20}

Member Function Documentation

◆ DisableCheckMapIndices()

void Garfield::ComponentFieldMap::DisableCheckMapIndices ( )
inline

Definition at line 72 of file ComponentFieldMap.hh.

72{ m_checkMultipleElement = false; }

◆ DriftMedium()

void Garfield::ComponentFieldMap::DriftMedium ( const unsigned int  imat)

Flag a field map material as a drift medium.

Definition at line 51 of file ComponentFieldMap.cc.

51 {
52 // Do not proceed if not properly initialised.
53 if (!m_ready) PrintNotReady("DriftMedium");
54
55 // Check value
56 if (imat >= m_nMaterials) {
57 std::cerr << m_className << "::DriftMedium: Index out of range.\n";
58 return;
59 }
60
61 // Make drift medium
62 materials[imat].driftmedium = true;
63}
bool m_ready
Ready for use?
std::vector< Material > materials
void PrintNotReady(const std::string &header) const

◆ EnableCheckMapIndices()

void Garfield::ComponentFieldMap::EnableCheckMapIndices ( )
inline

Definition at line 68 of file ComponentFieldMap.hh.

68 {
69 m_checkMultipleElement = true;
70 m_lastElement = -1;
71 }

◆ EnableDeleteBackgroundElements()

void Garfield::ComponentFieldMap::EnableDeleteBackgroundElements ( const bool  on = true)
inline

Option to eliminate mesh elements in conductors (default: on).

Definition at line 74 of file ComponentFieldMap.hh.

◆ EnableTetrahedralTreeForElementSearch()

void Garfield::ComponentFieldMap::EnableTetrahedralTreeForElementSearch ( const bool  on = true)
inline

Enable or disable the usage of the tetrahedral tree for searching the element in the mesh.

Definition at line 80 of file ComponentFieldMap.hh.

80 {
81 m_useTetrahedralTree = on;
82 }

◆ FindElement13()

int Garfield::ComponentFieldMap::FindElement13 ( const double  x,
const double  y,
const double  z,
double &  t1,
double &  t2,
double &  t3,
double &  t4,
double  jac[4][4],
double &  det 
)
protected

Find the element for a point in curved quadratic tetrahedra.

Definition at line 298 of file ComponentFieldMap.cc.

301 {
302 // Check if bounding boxes of elements have been computed
303 if (!m_cacheElemBoundingBoxes) {
304 std::cout << m_className << "::FindElement13:\n"
305 << " Caching the bounding boxes of all elements...";
306 CalculateElementBoundingBoxes();
307 std::cout << " done.\n";
308 m_cacheElemBoundingBoxes = true;
309 }
310
311 // Backup
312 double jacbak[4][4];
313 double detbak = 1.;
314 double t1bak = 0., t2bak = 0., t3bak = 0., t4bak = 0.;
315 int imapbak = -1;
316
317 // Initial values.
318 t1 = t2 = t3 = t4 = 0.;
319
320 // Check previously used element
321 if (m_lastElement > -1 && !m_checkMultipleElement) {
322 const Element& element = elements[m_lastElement];
323 if (Coordinates13(x, y, z, t1, t2, t3, t4, jac, det, element) == 0) {
324 if (t1 >= 0 && t1 <= +1 && t2 >= 0 && t2 <= +1 && t3 >= 0 && t3 <= +1 &&
325 t4 >= 0 && t4 <= +1) {
326 return m_lastElement;
327 }
328 }
329 }
330
331 // Tetra list in the block that contains the input 3D point.
332 std::vector<int> tetList;
333 if (m_useTetrahedralTree) {
334 if (!m_isTreeInitialized) {
335 if (!InitializeTetrahedralTree()) {
336 std::cerr << m_className << "::FindElement13:\n";
337 std::cerr << " Tetrahedral tree initialization failed.\n";
338 return -1;
339 }
340 }
341 tetList = m_tetTree->GetTetListInBlock(Vec3(x, y, z));
342 }
343 // Number of elements to scan.
344 // With tetra tree disabled, all elements are scanned.
345 const int numElemToSearch = m_useTetrahedralTree ? tetList.size() : nElements;
346 // Verify the count of volumes that contain the point.
347 int nfound = 0;
348 int imap = -1;
349
350 // Scan all elements
351 for (int i = 0; i < numElemToSearch; i++) {
352 const int idxToElemList = m_useTetrahedralTree ? tetList[i] : i;
353 const Element& element = elements[idxToElemList];
354 if (x < element.xmin || x > element.xmax || y < element.ymin ||
355 y > element.ymax || z < element.zmin || z > element.zmax)
356 continue;
357 if (Coordinates13(x, y, z, t1, t2, t3, t4, jac, det, element) != 0) {
358 continue;
359 }
360 if (t1 < 0 || t1 > 1 || t2 < 0 || t2 > 1 || t3 < 0 || t3 > 1 || t4 < 0 ||
361 t4 > 1) {
362 continue;
363 }
364 ++nfound;
365 imap = idxToElemList;
366 m_lastElement = idxToElemList;
367 if (m_debug) {
368 std::cout << m_className << "::FindElement13:\n";
369 std::cout << " Found matching element " << i << ".\n";
370 }
371 if (!m_checkMultipleElement) return idxToElemList;
372 for (int j = 0; j < 4; ++j) {
373 for (int k = 0; k < 4; ++k) jacbak[j][k] = jac[j][k];
374 }
375 detbak = det;
376 t1bak = t1;
377 t2bak = t2;
378 t3bak = t3;
379 t4bak = t4;
380 imapbak = imap;
381 if (m_debug) {
382 PrintElement("FindElement13", x, y, z, t1, t2, t3, t4, element, 10);
383 }
384 }
385
386 // In checking mode, verify the tetrahedron/triangle count.
387 if (m_checkMultipleElement) {
388 if (nfound < 1) {
389 if (m_debug) {
390 std::cout << m_className << "::FindElement13:\n";
391 std::cout << " No element matching point (" << x << ", " << y << ", "
392 << z << ") found.\n";
393 }
394 m_lastElement = -1;
395 return -1;
396 }
397 if (nfound > 1) {
398 std::cerr << m_className << "::FindElement13:\n";
399 std::cerr << " Found << " << nfound << " elements matching point ("
400 << x << ", " << y << ", " << z << ").\n";
401 }
402 if (nfound > 0) {
403 for (int j = 0; j < 4; ++j) {
404 for (int k = 0; k < 4; ++k) jac[j][k] = jacbak[j][k];
405 }
406 det = detbak;
407 t1 = t1bak;
408 t2 = t2bak;
409 t3 = t3bak;
410 t4 = t4bak;
411 imap = imapbak;
412 m_lastElement = imap;
413 return imap;
414 }
415 }
416
417 if (m_debug) {
418 std::cout << m_className << "::FindElement13:\n";
419 std::cout << " No element matching point (" << x << ", " << y << ", "
420 << z << ") found.\n";
421 }
422 return -1;
423}
bool m_debug
Switch on/off debugging messages.
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 Element &element, const unsigned int n, const int iw=-1) const
std::vector< Element > elements
std::vector< int > GetTetListInBlock(const Vec3 &point)

Referenced by Garfield::ComponentAnsys123::ElectricField(), Garfield::ComponentComsol::ElectricField(), Garfield::ComponentElmer::ElectricField(), Garfield::ComponentAnsys123::GetMedium(), Garfield::ComponentComsol::GetMedium(), Garfield::ComponentElmer::GetMedium(), Garfield::ComponentAnsys123::WeightingField(), Garfield::ComponentComsol::WeightingField(), Garfield::ComponentElmer::WeightingField(), Garfield::ComponentAnsys123::WeightingPotential(), Garfield::ComponentComsol::WeightingPotential(), and Garfield::ComponentElmer::WeightingPotential().

◆ FindElement5()

int Garfield::ComponentFieldMap::FindElement5 ( const double  x,
const double  y,
const double  z,
double &  t1,
double &  t2,
double &  t3,
double &  t4,
double  jac[4][4],
double &  det 
)
protected

Find the element for a point in curved quadratic quadrilaterals.

Definition at line 140 of file ComponentFieldMap.cc.

143 {
144 // Check if bounding boxes of elements have been computed
145 if (!m_cacheElemBoundingBoxes) {
146 std::cout << m_className << "::FindElement5:\n"
147 << " Caching the bounding boxes of all elements...";
148 CalculateElementBoundingBoxes();
149 std::cout << " done.\n";
150 m_cacheElemBoundingBoxes = true;
151 }
152
153 // Tetra list in the block that contains the input 3D point.
154 std::vector<int> tetList;
155 if (m_useTetrahedralTree) {
156 if (!m_isTreeInitialized) {
157 if (!InitializeTetrahedralTree()) {
158 std::cerr << m_className << "::FindElement5:\n";
159 std::cerr << " Tetrahedral tree initialization failed.\n";
160 return -1;
161 }
162 }
163 tetList = m_tetTree->GetTetListInBlock(Vec3(x, y, z));
164 }
165 // Backup
166 double jacbak[4][4], detbak = 1.;
167 double t1bak = 0., t2bak = 0., t3bak = 0., t4bak = 0.;
168 int imapbak = -1;
169
170 // Initial values.
171 t1 = t2 = t3 = t4 = 0;
172
173 // Check previously used element
174 if (m_lastElement > -1 && !m_checkMultipleElement) {
175 const Element& element = elements[m_lastElement];
176 if (element.degenerate) {
177 if (Coordinates3(x, y, z, t1, t2, t3, t4, jac, det, element) == 0) {
178 if (t1 >= 0 && t1 <= +1 && t2 >= 0 && t2 <= +1 && t3 >= 0 && t3 <= +1) {
179 return m_lastElement;
180 }
181 }
182 } else {
183 if (Coordinates5(x, y, z, t1, t2, t3, t4, jac, det, element) == 0) {
184 if (t1 >= -1 && t1 <= +1 && t2 >= -1 && t2 <= +1) return m_lastElement;
185 }
186 }
187 }
188
189 // Verify the count of volumes that contain the point.
190 int nfound = 0;
191 int imap = -1;
192
193 // Number of elements to scan.
194 // With tetra tree disabled, all elements are scanned.
195 const int numElemToSearch = m_useTetrahedralTree ? tetList.size() : nElements;
196 for (int i = 0; i < numElemToSearch; ++i) {
197 const int idxToElemList = m_useTetrahedralTree ? tetList[i] : i;
198 const Element& element = elements[idxToElemList];
199 if (x < element.xmin || x > element.xmax || y < element.ymin ||
200 y > element.ymax || z < element.zmin || z > element.zmax)
201 continue;
202 if (element.degenerate) {
203 // Degenerate element
204 if (Coordinates3(x, y, z, t1, t2, t3, t4, jac, det, element) != 0) {
205 continue;
206 }
207 if (t1 < 0 || t1 > 1 || t2 < 0 || t2 > 1 || t3 < 0 || t3 > 1) continue;
208 ++nfound;
209 imap = idxToElemList;
210 m_lastElement = idxToElemList;
211 if (m_debug) {
212 std::cout << m_className << "::FindElement5:\n";
213 std::cout << " Found matching degenerate element " << idxToElemList
214 << ".\n";
215 }
216 if (!m_checkMultipleElement) return idxToElemList;
217 for (int j = 0; j < 4; ++j) {
218 for (int k = 0; k < 4; ++k) jacbak[j][k] = jac[j][k];
219 }
220 detbak = det;
221 t1bak = t1;
222 t2bak = t2;
223 t3bak = t3;
224 t4bak = t4;
225 imapbak = imap;
226 if (m_debug) {
227 PrintElement("FindElement5", x, y, z, t1, t2, t3, t4, element, 6);
228 }
229 } else {
230 // Non-degenerate element
231 if (Coordinates5(x, y, z, t1, t2, t3, t4, jac, det, element) != 0) {
232 continue;
233 }
234 if (t1 < -1 || t1 > 1 || t2 < -1 || t2 > 1) continue;
235 ++nfound;
236 imap = idxToElemList;
237 m_lastElement = idxToElemList;
238 if (m_debug) {
239 std::cout << m_className << "::FindElement5:\n";
240 std::cout << " Found matching non-degenerate element "
241 << idxToElemList << ".\n";
242 }
243 if (!m_checkMultipleElement) return idxToElemList;
244 for (int j = 0; j < 4; ++j) {
245 for (int k = 0; k < 4; ++k) jacbak[j][k] = jac[j][k];
246 }
247 detbak = det;
248 t1bak = t1;
249 t2bak = t2;
250 t3bak = t3;
251 t4bak = t4;
252 imapbak = imap;
253 if (m_debug) {
254 PrintElement("FindElement5", x, y, z, t1, t2, t3, t4, element, 8);
255 }
256 }
257 }
258
259 // In checking mode, verify the tetrahedron/triangle count.
260 if (m_checkMultipleElement) {
261 if (nfound < 1) {
262 if (m_debug) {
263 std::cout << m_className << "::FindElement5:\n";
264 std::cout << " No element matching point (" << x << ", " << y
265 << ") found.\n";
266 }
267 m_lastElement = -1;
268 return -1;
269 }
270 if (nfound > 1) {
271 std::cout << m_className << "::FindElement5:\n";
272 std::cout << " Found " << nfound << " elements matching point (" << x
273 << ", " << y << ").\n";
274 }
275 if (nfound > 0) {
276 for (int j = 0; j < 4; ++j) {
277 for (int k = 0; k < 4; ++k) jac[j][k] = jacbak[j][k];
278 }
279 det = detbak;
280 t1 = t1bak;
281 t2 = t2bak;
282 t3 = t3bak;
283 t4 = t4bak;
284 imap = imapbak;
285 m_lastElement = imap;
286 return imap;
287 }
288 }
289
290 if (m_debug) {
291 std::cout << m_className << "::FindElement5:\n";
292 std::cout << " No element matching point (" << x << ", " << y
293 << ") found.\n";
294 }
295 return -1;
296}

Referenced by Garfield::ComponentAnsys121::ElectricField(), Garfield::ComponentAnsys121::GetMedium(), Garfield::ComponentAnsys121::WeightingField(), and Garfield::ComponentAnsys121::WeightingPotential().

◆ FindElementCube()

int Garfield::ComponentFieldMap::FindElementCube ( const double  x,
const double  y,
const double  z,
double &  t1,
double &  t2,
double &  t3,
TMatrixD *&  jac,
std::vector< TMatrixD * > &  dN 
)
protected

Find the element for a point in a cube.

Definition at line 425 of file ComponentFieldMap.cc.

428 {
429 int imap = -1;
430 if (m_lastElement >= 0) {
431 const Element& element = elements[m_lastElement];
432 const Node& n3 = nodes[element.emap[3]];
433 if (x >= n3.x && y >= n3.y && z >= n3.z) {
434 const Node& n0 = nodes[element.emap[0]];
435 const Node& n2 = nodes[element.emap[2]];
436 const Node& n7 = nodes[element.emap[7]];
437 if (x < n0.x && y < n2.y && z < n7.z) {
438 imap = m_lastElement;
439 }
440 }
441 }
442
443 // Default element loop
444 if (imap == -1) {
445 for (int i = 0; i < nElements; ++i) {
446 const Element& element = elements[i];
447 const Node& n3 = nodes[element.emap[3]];
448 if (x < n3.x || y < n3.y || z < n3.z) continue;
449 const Node& n0 = nodes[element.emap[0]];
450 const Node& n2 = nodes[element.emap[2]];
451 const Node& n7 = nodes[element.emap[7]];
452 if (x < n0.x && y < n2.y && z < n7.z) {
453 imap = i;
454 break;
455 }
456 }
457 }
458
459 if (imap < 0) {
460 if (m_debug) {
461 std::cout << m_className << "::FindElementCube:\n";
462 std::cout << " Point (" << x << "," << y << "," << z
463 << ") not in the mesh, it is background or PEC.\n";
464 const Node& first0 = nodes[elements.front().emap[0]];
465 const Node& first2 = nodes[elements.front().emap[2]];
466 const Node& first3 = nodes[elements.front().emap[3]];
467 const Node& first7 = nodes[elements.front().emap[7]];
468 std::cout << " First node (" << first3.x << "," << first3.y << ","
469 << first3.z << ") in the mesh.\n";
470 std::cout << " dx= " << (first0.x - first3.x)
471 << ", dy= " << (first2.y - first3.y)
472 << ", dz= " << (first7.z - first3.z) << "\n";
473 const Node& last0 = nodes[elements.back().emap[0]];
474 const Node& last2 = nodes[elements.back().emap[2]];
475 const Node& last3 = nodes[elements.back().emap[3]];
476 const Node& last5 = nodes[elements.back().emap[5]];
477 const Node& last7 = nodes[elements.back().emap[7]];
478 std::cout << " Last node (" << last5.x << "," << last5.y << ","
479 << last5.z << ") in the mesh.\n";
480 std::cout << " dx= " << (last0.x - last3.x)
481 << ", dy= " << (last2.y - last3.y)
482 << ", dz= " << (last7.z - last3.z) << "\n";
483 }
484 return -1;
485 }
486 CoordinatesCube(x, y, z, t1, t2, t3, jac, dN, elements[imap]);
487 if (m_debug) {
488 PrintElement("FindElementCube", x, y, z, t1, t2, t3, 0., elements[imap], 8);
489 }
490 return imap;
491}

◆ GetAspectRatio()

virtual void Garfield::ComponentFieldMap::GetAspectRatio ( const unsigned int  i,
double &  dmin,
double &  dmax 
)
protectedpure virtual

◆ GetBoundingBox()

bool Garfield::ComponentFieldMap::GetBoundingBox ( double &  xmin,
double &  ymin,
double &  zmin,
double &  xmax,
double &  ymax,
double &  zmax 
)
overridevirtual

Get the bounding box coordinates.

Reimplemented from Garfield::ComponentBase.

Definition at line 2060 of file ComponentFieldMap.cc.

2062 {
2063 if (!m_ready) return false;
2064
2065 xmin = m_minBoundingBox[0];
2066 xmax = m_maxBoundingBox[0];
2067 ymin = m_minBoundingBox[1];
2068 ymax = m_maxBoundingBox[1];
2069 zmin = m_minBoundingBox[2];
2070 zmax = m_maxBoundingBox[2];
2071 return true;
2072}
std::array< double, 3 > m_maxBoundingBox
std::array< double, 3 > m_minBoundingBox

◆ GetConductivity()

double Garfield::ComponentFieldMap::GetConductivity ( const unsigned int  imat) const

Return the conductivity of a field map material.

Definition at line 88 of file ComponentFieldMap.cc.

88 {
89 if (imat >= m_nMaterials) {
90 std::cerr << m_className << "::GetConductivity: Index out of range.\n";
91 return -1.;
92 }
93
94 return materials[imat].ohm;
95}

◆ GetElement()

bool Garfield::ComponentFieldMap::GetElement ( const unsigned int  i,
double &  vol,
double &  dmin,
double &  dmax 
)

Return the volume and aspect ratio of a mesh element.

Definition at line 127 of file ComponentFieldMap.cc.

128 {
129 if ((int)i >= nElements) {
130 std::cerr << m_className << "::GetElement:\n";
131 std::cerr << " Element index (" << i << ") out of range.\n";
132 return false;
133 }
134
135 vol = GetElementVolume(i);
136 GetAspectRatio(i, dmin, dmax);
137 return true;
138}
virtual double GetElementVolume(const unsigned int i)=0
virtual void GetAspectRatio(const unsigned int i, double &dmin, double &dmax)=0

◆ GetElementVolume()

virtual double Garfield::ComponentFieldMap::GetElementVolume ( const unsigned int  i)
protectedpure virtual

◆ GetMedium() [1/2]

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

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

Reimplemented from Garfield::ComponentBase.

Definition at line 26 of file ComponentBase.cc.

22 {
23 if (!m_geometry) return nullptr;
24 return m_geometry->GetMedium(x, y, z);
25}
GeometryBase * m_geometry
Pointer to the geometry.
virtual Medium * GetMedium(const double x, const double y, const double z) const =0
Retrieve the medium at a given point.

◆ GetMedium() [2/2]

Medium * Garfield::ComponentFieldMap::GetMedium ( const unsigned int  i) const

Return the Medium associated to a field map material.

Definition at line 117 of file ComponentFieldMap.cc.

117 {
118 if (imat >= m_nMaterials) {
119 std::cerr << m_className << "::GetMedium:\n"
120 << " Material index " << imat << " is out of range.\n";
121 return nullptr;
122 }
123
124 return materials[imat].medium;
125}

◆ GetNumberOfElements()

int Garfield::ComponentFieldMap::GetNumberOfElements ( ) const
inline

Return the number of mesh elements.

Definition at line 62 of file ComponentFieldMap.hh.

62{ return nElements; }

◆ GetNumberOfMaterials()

unsigned int Garfield::ComponentFieldMap::GetNumberOfMaterials ( ) const
inline

Return the number of materials in the field map.

Definition at line 48 of file ComponentFieldMap.hh.

48{ return m_nMaterials; }

◆ GetNumberOfMedia()

unsigned int Garfield::ComponentFieldMap::GetNumberOfMedia ( ) const
inline

Definition at line 59 of file ComponentFieldMap.hh.

59{ return m_nMaterials; }

◆ GetPermittivity()

double Garfield::ComponentFieldMap::GetPermittivity ( const unsigned int  imat) const

Return the permittivity of a field map material.

Definition at line 79 of file ComponentFieldMap.cc.

79 {
80 if (imat >= m_nMaterials) {
81 std::cerr << m_className << "::GetPermittivity: Index out of range.\n";
82 return -1.;
83 }
84
85 return materials[imat].eps;
86}

◆ GetVoltageRange()

bool Garfield::ComponentFieldMap::GetVoltageRange ( double &  vmin,
double &  vmax 
)
inlineoverridevirtual

Calculate the voltage range [V].

Implements Garfield::ComponentBase.

Definition at line 35 of file ComponentFieldMap.hh.

35 {
36 vmin = m_mapvmin;
37 vmax = m_mapvmax;
38 return true;
39 }

Referenced by Garfield::ViewFEMesh::Plot().

◆ IsInBoundingBox()

bool Garfield::ComponentFieldMap::IsInBoundingBox ( const double  x,
const double  y,
const double  z 
) const
inline

Definition at line 25 of file ComponentFieldMap.hh.

25 {
26 return x >= m_minBoundingBox[0] && x <= m_maxBoundingBox[0] &&
27 y >= m_minBoundingBox[1] && y <= m_maxBoundingBox[1] &&
28 z >= m_minBoundingBox[2] && y <= m_maxBoundingBox[2];
29 }

◆ MapCoordinates()

void Garfield::ComponentFieldMap::MapCoordinates ( double &  xpos,
double &  ypos,
double &  zpos,
bool &  xmirrored,
bool &  ymirrored,
bool &  zmirrored,
double &  rcoordinate,
double &  rotation 
) const
protected

Move (xpos, ypos, zpos) to field map coordinates.

Definition at line 2074 of file ComponentFieldMap.cc.

2077 {
2078 // Initial values
2079 rotation = 0;
2080
2081 // If chamber is periodic, reduce to the cell volume.
2082 xmirrored = false;
2083 double auxr, auxphi;
2084 if (m_periodic[0]) {
2085 xpos = m_mapmin[0] + fmod(xpos - m_mapmin[0], m_mapmax[0] - m_mapmin[0]);
2086 if (xpos < m_mapmin[0]) xpos += m_mapmax[0] - m_mapmin[0];
2087 } else if (m_mirrorPeriodic[0]) {
2088 double xnew =
2089 m_mapmin[0] + fmod(xpos - m_mapmin[0], m_mapmax[0] - m_mapmin[0]);
2090 if (xnew < m_mapmin[0]) xnew += m_mapmax[0] - m_mapmin[0];
2091 int nx = int(floor(0.5 + (xnew - xpos) / (m_mapmax[0] - m_mapmin[0])));
2092 if (nx != 2 * (nx / 2)) {
2093 xnew = m_mapmin[0] + m_mapmax[0] - xnew;
2094 xmirrored = true;
2095 }
2096 xpos = xnew;
2097 }
2098 if (m_axiallyPeriodic[0] && (zpos != 0 || ypos != 0)) {
2099 auxr = sqrt(zpos * zpos + ypos * ypos);
2100 auxphi = atan2(zpos, ypos);
2101 rotation = (m_mapamax[0] - m_mapamin[0]) *
2102 floor(0.5 +
2103 (auxphi - 0.5 * (m_mapamin[0] + m_mapamax[0])) /
2104 (m_mapamax[0] - m_mapamin[0]));
2105 if (auxphi - rotation < m_mapamin[0])
2106 rotation = rotation - (m_mapamax[0] - m_mapamin[0]);
2107 if (auxphi - rotation > m_mapamax[0])
2108 rotation = rotation + (m_mapamax[0] - m_mapamin[0]);
2109 auxphi = auxphi - rotation;
2110 ypos = auxr * cos(auxphi);
2111 zpos = auxr * sin(auxphi);
2112 }
2113
2114 ymirrored = false;
2115 if (m_periodic[1]) {
2116 ypos = m_mapmin[1] + fmod(ypos - m_mapmin[1], m_mapmax[1] - m_mapmin[1]);
2117 if (ypos < m_mapmin[1]) ypos += m_mapmax[1] - m_mapmin[1];
2118 } else if (m_mirrorPeriodic[1]) {
2119 double ynew =
2120 m_mapmin[1] + fmod(ypos - m_mapmin[1], m_mapmax[1] - m_mapmin[1]);
2121 if (ynew < m_mapmin[1]) ynew += m_mapmax[1] - m_mapmin[1];
2122 int ny = int(floor(0.5 + (ynew - ypos) / (m_mapmax[1] - m_mapmin[1])));
2123 if (ny != 2 * (ny / 2)) {
2124 ynew = m_mapmin[1] + m_mapmax[1] - ynew;
2125 ymirrored = true;
2126 }
2127 ypos = ynew;
2128 }
2129 if (m_axiallyPeriodic[1] && (xpos != 0 || zpos != 0)) {
2130 auxr = sqrt(xpos * xpos + zpos * zpos);
2131 auxphi = atan2(xpos, zpos);
2132 rotation = (m_mapamax[1] - m_mapamin[1]) *
2133 floor(0.5 +
2134 (auxphi - 0.5 * (m_mapamin[1] + m_mapamax[1])) /
2135 (m_mapamax[1] - m_mapamin[1]));
2136 if (auxphi - rotation < m_mapamin[1])
2137 rotation = rotation - (m_mapamax[1] - m_mapamin[1]);
2138 if (auxphi - rotation > m_mapamax[1])
2139 rotation = rotation + (m_mapamax[1] - m_mapamin[1]);
2140 auxphi = auxphi - rotation;
2141 zpos = auxr * cos(auxphi);
2142 xpos = auxr * sin(auxphi);
2143 }
2144
2145 zmirrored = false;
2146 if (m_periodic[2]) {
2147 zpos = m_mapmin[2] + fmod(zpos - m_mapmin[2], m_mapmax[2] - m_mapmin[2]);
2148 if (zpos < m_mapmin[2]) zpos += m_mapmax[2] - m_mapmin[2];
2149 } else if (m_mirrorPeriodic[2]) {
2150 double znew =
2151 m_mapmin[2] + fmod(zpos - m_mapmin[2], m_mapmax[2] - m_mapmin[2]);
2152 if (znew < m_mapmin[2]) znew += m_mapmax[2] - m_mapmin[2];
2153 int nz = int(floor(0.5 + (znew - zpos) / (m_mapmax[2] - m_mapmin[2])));
2154 if (nz != 2 * (nz / 2)) {
2155 znew = m_mapmin[2] + m_mapmax[2] - znew;
2156 zmirrored = true;
2157 }
2158 zpos = znew;
2159 }
2160 if (m_axiallyPeriodic[2] && (ypos != 0 || xpos != 0)) {
2161 auxr = sqrt(ypos * ypos + xpos * xpos);
2162 auxphi = atan2(ypos, xpos);
2163 rotation = (m_mapamax[2] - m_mapamin[2]) *
2164 floor(0.5 +
2165 (auxphi - 0.5 * (m_mapamin[2] + m_mapamax[2])) /
2166 (m_mapamax[2] - m_mapamin[2]));
2167 if (auxphi - rotation < m_mapamin[2])
2168 rotation = rotation - (m_mapamax[2] - m_mapamin[2]);
2169 if (auxphi - rotation > m_mapamax[2])
2170 rotation = rotation + (m_mapamax[2] - m_mapamin[2]);
2171 auxphi = auxphi - rotation;
2172 xpos = auxr * cos(auxphi);
2173 ypos = auxr * sin(auxphi);
2174 }
2175
2176 // If we have a rotationally symmetric field map, store coordinates.
2177 rcoordinate = 0;
2178 double zcoordinate = 0;
2179 if (m_rotationSymmetric[0]) {
2180 rcoordinate = sqrt(ypos * ypos + zpos * zpos);
2181 zcoordinate = xpos;
2182 } else if (m_rotationSymmetric[1]) {
2183 rcoordinate = sqrt(xpos * xpos + zpos * zpos);
2184 zcoordinate = ypos;
2185 } else if (m_rotationSymmetric[2]) {
2186 rcoordinate = sqrt(xpos * xpos + ypos * ypos);
2187 zcoordinate = zpos;
2188 }
2189
2192 xpos = rcoordinate;
2193 ypos = zcoordinate;
2194 zpos = 0;
2195 }
2196}
std::array< bool, 3 > m_periodic
Simple periodicity in x, y, z.
std::array< bool, 3 > m_rotationSymmetric
Rotation symmetry around x-axis, y-axis, z-axis.
std::array< bool, 3 > m_axiallyPeriodic
Axial periodicity in x, y, z.
std::array< bool, 3 > m_mirrorPeriodic
Mirror periodicity in x, y, z.
std::array< double, 3 > m_mapamin
std::array< double, 3 > m_mapmin
std::array< double, 3 > m_mapamax
std::array< double, 3 > m_mapmax
DoubleAc cos(const DoubleAc &f)
Definition: DoubleAc.cpp:432
DoubleAc sin(const DoubleAc &f)
Definition: DoubleAc.cpp:384
DoubleAc sqrt(const DoubleAc &f)
Definition: DoubleAc.cpp:314

Referenced by Garfield::ComponentCST::Coordinate2Index(), Garfield::ComponentAnsys121::ElectricField(), Garfield::ComponentAnsys123::ElectricField(), Garfield::ComponentComsol::ElectricField(), Garfield::ComponentElmer::ElectricField(), Garfield::ComponentAnsys121::GetMedium(), Garfield::ComponentAnsys123::GetMedium(), Garfield::ComponentComsol::GetMedium(), Garfield::ComponentElmer::GetMedium(), Garfield::ComponentAnsys121::WeightingField(), Garfield::ComponentAnsys123::WeightingField(), Garfield::ComponentComsol::WeightingField(), Garfield::ComponentElmer::WeightingField(), Garfield::ComponentAnsys121::WeightingPotential(), Garfield::ComponentAnsys123::WeightingPotential(), Garfield::ComponentComsol::WeightingPotential(), and Garfield::ComponentElmer::WeightingPotential().

◆ NotDriftMedium()

void Garfield::ComponentFieldMap::NotDriftMedium ( const unsigned int  imat)

Flag a field map materials as a non-drift medium.

Definition at line 65 of file ComponentFieldMap.cc.

65 {
66 // Do not proceed if not properly initialised.
67 if (!m_ready) PrintNotReady("NotDriftMedium");
68
69 // Check value
70 if (imat >= m_nMaterials) {
71 std::cerr << m_className << "::NotDriftMedium: Index out of range.\n";
72 return;
73 }
74
75 // Make drift medium
76 materials[imat].driftmedium = false;
77}

◆ PrintElement()

void Garfield::ComponentFieldMap::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 Element element,
const unsigned int  n,
const int  iw = -1 
) const
protected

Definition at line 2396 of file ComponentFieldMap.cc.

2401 {
2402 std::cout << m_className << "::" << header << ":\n"
2403 << " Global = (" << x << ", " << y << ", " << z << ")\n"
2404 << " Local = (" << t1 << ", " << t2 << ", " << t3 << ", " << t4
2405 << ")\n";
2406 if (element.degenerate) std::cout << " Element is degenerate.\n";
2407 std::cout << " Node x y z V\n";
2408 for (unsigned int ii = 0; ii < n; ++ii) {
2409 const Node& node = nodes[element.emap[ii]];
2410 const double v = iw < 0 ? node.v : node.w[iw];
2411 printf(" %-5d %12g %12g %12g %12g\n", element.emap[ii], node.x, node.y,
2412 node.z, v);
2413 }
2414}

Referenced by Garfield::ComponentAnsys121::ElectricField(), Garfield::ComponentAnsys123::ElectricField(), Garfield::ComponentComsol::ElectricField(), Garfield::ComponentElmer::ElectricField(), FindElement13(), FindElement5(), FindElementCube(), Garfield::ComponentAnsys121::GetMedium(), Garfield::ComponentAnsys123::GetMedium(), Garfield::ComponentComsol::GetMedium(), Garfield::ComponentElmer::GetMedium(), Garfield::ComponentAnsys121::WeightingField(), Garfield::ComponentAnsys123::WeightingField(), Garfield::ComponentComsol::WeightingField(), Garfield::ComponentElmer::WeightingField(), Garfield::ComponentAnsys121::WeightingPotential(), Garfield::ComponentAnsys123::WeightingPotential(), Garfield::ComponentComsol::WeightingPotential(), and Garfield::ComponentElmer::WeightingPotential().

◆ PrintMaterials()

void Garfield::ComponentFieldMap::PrintMaterials ( )

List all currently defined materials.

Definition at line 22 of file ComponentFieldMap.cc.

22 {
23 // Do not proceed if not properly initialised.
24 if (!m_ready) PrintNotReady("PrintMaterials");
25
26 if (materials.empty()) {
27 std::cerr << m_className << "::PrintMaterials:\n"
28 << " No materials are currently defined.\n";
29 return;
30 }
31
32 std::cout << m_className << "::PrintMaterials:\n"
33 << " Currently " << m_nMaterials << " materials are defined.\n"
34 << " Index Permittivity Resistivity Notes\n";
35 for (unsigned int i = 0; i < m_nMaterials; ++i) {
36 printf(" %5d %12g %12g", i, materials[i].eps, materials[i].ohm);
37 if (materials[i].medium) {
38 std::string name = materials[i].medium->GetName();
39 std::cout << " " << name;
40 if (materials[i].medium->IsDriftable()) std::cout << ", drift medium";
41 if (materials[i].medium->IsIonisable()) std::cout << ", ionisable";
42 }
43 if (materials[i].driftmedium) {
44 std::cout << " (drift medium)\n";
45 } else {
46 std::cout << "\n";
47 }
48 }
49}

Referenced by Garfield::ComponentCST::Initialise(), Garfield::ComponentAnsys121::Initialise(), and Garfield::ComponentAnsys123::Initialise().

◆ PrintNotReady()

◆ PrintRange()

void Garfield::ComponentFieldMap::PrintRange ( )

Show x, y, z, V and angular ranges.

Definition at line 2031 of file ComponentFieldMap.cc.

2031 {
2032 std::cout << m_className << "::PrintRange:\n";
2033 std::cout << " Dimensions of the elementary block\n";
2034 printf(" %15g < x < %-15g cm,\n", m_mapmin[0], m_mapmax[0]);
2035 printf(" %15g < y < %-15g cm,\n", m_mapmin[1], m_mapmax[1]);
2036 printf(" %15g < z < %-15g cm,\n", m_mapmin[2], m_mapmax[2]);
2037 printf(" %15g < V < %-15g V.\n", m_mapvmin, m_mapvmax);
2038
2039 std::cout << " Periodicities\n";
2040 const std::array<std::string, 3> axes = {{"x", "y", "z"}};
2041 for (unsigned int i = 0; i < 3; ++i) {
2042 std::cout << " " << axes[i] << ":";
2043 if (m_periodic[i]) {
2044 std::cout << " simple with length " << m_cells[i] << " cm";
2045 }
2046 if (m_mirrorPeriodic[i]) {
2047 std::cout << " mirror with length " << m_cells[i] << " cm";
2048 }
2049 if (m_axiallyPeriodic[i]) {
2050 std::cout << " axial " << int(0.5 + m_mapna[i]) << "-fold repetition";
2051 }
2052 if (m_rotationSymmetric[i]) std::cout << " rotational symmetry";
2053 if (!(m_periodic[i] || m_mirrorPeriodic[i] || m_axiallyPeriodic[i] ||
2055 std::cout << " none";
2056 std::cout << "\n";
2057 }
2058}
std::array< double, 3 > m_mapna
std::array< double, 3 > m_cells

Referenced by Garfield::ComponentCST::Coordinate2Index(), SetRange(), and UpdatePeriodicityCommon().

◆ PrintWarning()

◆ ReadDouble()

double Garfield::ComponentFieldMap::ReadDouble ( char *  token,
double  def,
bool &  error 
)
protected

◆ ReadInteger()

int Garfield::ComponentFieldMap::ReadInteger ( char *  token,
int  def,
bool &  error 
)
protected

◆ Reset()

void Garfield::ComponentFieldMap::Reset ( )
inlineoverrideprotectedvirtual

Reset the component.

Implements Garfield::ComponentBase.

Definition at line 157 of file ComponentFieldMap.hh.

157{};

◆ SetMedium()

void Garfield::ComponentFieldMap::SetMedium ( const unsigned int  imat,
Medium medium 
)

Associate a field map material with a Medium class.

Definition at line 97 of file ComponentFieldMap.cc.

97 {
98 if (imat >= m_nMaterials) {
99 std::cerr << m_className << "::SetMedium:\n";
100 std::cerr << " Material index " << imat << " is out of range.\n";
101 return;
102 }
103
104 if (!m) {
105 std::cerr << m_className << "::SetMedium: Null pointer.\n";
106 return;
107 }
108
109 if (m_debug) {
110 std::cout << m_className << "::SetMedium:\n Associated material " << imat
111 << " with medium " << m->GetName() << ".\n";
112 }
113
114 materials[imat].medium = m;
115}

Referenced by main().

◆ SetRange()

void Garfield::ComponentFieldMap::SetRange ( )
virtual

Calculate x, y, z, V and angular ranges.

Reimplemented in Garfield::ComponentCST.

Definition at line 1934 of file ComponentFieldMap.cc.

1934 {
1935 // Initial values
1936 m_mapmin.fill(0.);
1937 m_mapmax.fill(0.);
1938 m_mapamin.fill(0.);
1939 m_mapamax.fill(0.);
1940 m_mapvmin = m_mapvmax = 0.;
1941 m_setang.fill(false);
1942
1943 // Make sure the required data is available.
1944 if (!m_ready || nNodes < 1) {
1945 std::cerr << m_className << "::SetRange:\n";
1946 std::cerr << " Field map not yet set.\n";
1947 return;
1948 }
1949 if (nNodes < 1) {
1950 std::cerr << m_className << "::SetRange:\n";
1951 std::cerr << " Number of nodes < 1.\n";
1952 return;
1953 }
1954
1955 // Loop over the nodes.
1956 m_mapmin[0] = m_mapmax[0] = nodes[0].x;
1957 m_mapmin[1] = m_mapmax[1] = nodes[0].y;
1958 m_mapmin[2] = m_mapmax[2] = nodes[0].z;
1959 m_mapvmin = m_mapvmax = nodes[0].v;
1960
1961 for (const auto& node : nodes) {
1962 const std::array<double, 3> pos = {{node.x, node.y, node.z}};
1963 for (unsigned int i = 0; i < 3; ++i) {
1964 m_mapmin[i] = std::min(m_mapmin[i], pos[i]);
1965 m_mapmax[i] = std::max(m_mapmax[i], pos[i]);
1966 }
1967 m_mapvmin = std::min(m_mapvmin, node.v);
1968 m_mapvmax = std::max(m_mapvmax, node.v);
1969
1970 if (node.y != 0 || node.z != 0) {
1971 const double ang = atan2(node.z, node.y);
1972 if (m_setang[0]) {
1973 m_mapamin[0] = std::min(m_mapamin[0], ang);
1974 m_mapamax[0] = std::max(m_mapamax[0], ang);
1975 } else {
1976 m_mapamin[0] = m_mapamax[0] = ang;
1977 m_setang[0] = true;
1978 }
1979 }
1980
1981 if (node.z != 0 || node.x != 0) {
1982 const double ang = atan2(node.x, node.z);
1983 if (m_setang[1]) {
1984 m_mapamin[1] = std::min(m_mapamin[1], ang);
1985 m_mapamax[1] = std::max(m_mapamax[1], ang);
1986 } else {
1987 m_mapamin[1] = m_mapamax[1] = ang;
1988 m_setang[1] = true;
1989 }
1990 }
1991
1992 if (node.x != 0 || node.y != 0) {
1993 const double ang = atan2(node.y, node.x);
1994 if (m_setang[2]) {
1995 m_mapamin[2] = std::min(m_mapamin[2], ang);
1996 m_mapamax[2] = std::max(m_mapamax[2], ang);
1997 } else {
1998 m_mapamin[2] = m_mapamax[2] = ang;
1999 m_setang[2] = true;
2000 }
2001 }
2002 }
2003
2004 // Fix the angular ranges.
2005 for (unsigned int i = 0; i < 3; ++i) {
2006 if (m_mapamax[i] - m_mapamin[i] > Pi) {
2007 const double aux = m_mapamin[i];
2008 m_mapamin[i] = m_mapamax[i];
2009 m_mapamax[i] = aux + TwoPi;
2010 }
2011 }
2012
2013 // Set provisional cell dimensions.
2014 m_minBoundingBox[0] = m_mapmin[0];
2015 m_maxBoundingBox[0] = m_mapmax[0];
2016 m_minBoundingBox[1] = m_mapmin[1];
2017 m_maxBoundingBox[1] = m_mapmax[1];
2018 if (m_is3d) {
2019 m_minBoundingBox[2] = m_mapmin[2];
2020 m_maxBoundingBox[2] = m_mapmax[2];
2021 } else {
2022 m_mapmin[2] = m_minBoundingBox[2];
2023 m_mapmax[2] = m_maxBoundingBox[2];
2024 }
2025 hasBoundingBox = true;
2026
2027 // Display the range if requested.
2028 if (m_debug) PrintRange();
2029}
void PrintRange()
Show x, y, z, V and angular ranges.
std::array< bool, 3 > m_setang

Referenced by Garfield::ComponentElmer::Initialise(), Garfield::ComponentAnsys121::Initialise(), Garfield::ComponentAnsys123::Initialise(), and Garfield::ComponentComsol::Initialise().

◆ UnmapFields()

void Garfield::ComponentFieldMap::UnmapFields ( double &  ex,
double &  ey,
double &  ez,
double &  xpos,
double &  ypos,
double &  zpos,
bool &  xmirrored,
bool &  ymirrored,
bool &  zmirrored,
double &  rcoordinate,
double &  rotation 
) const
protected

Move (ex, ey, ez) to global coordinates.

Definition at line 2198 of file ComponentFieldMap.cc.

2202 {
2203 // Apply mirror imaging.
2204 if (xmirrored) ex = -ex;
2205 if (ymirrored) ey = -ey;
2206 if (zmirrored) ez = -ez;
2207
2208 // Rotate the field.
2209 double er, theta;
2210 if (m_axiallyPeriodic[0]) {
2211 er = sqrt(ey * ey + ez * ez);
2212 theta = atan2(ez, ey);
2213 theta += rotation;
2214 ey = er * cos(theta);
2215 ez = er * sin(theta);
2216 }
2217 if (m_axiallyPeriodic[1]) {
2218 er = sqrt(ez * ez + ex * ex);
2219 theta = atan2(ex, ez);
2220 theta += rotation;
2221 ez = er * cos(theta);
2222 ex = er * sin(theta);
2223 }
2224 if (m_axiallyPeriodic[2]) {
2225 er = sqrt(ex * ex + ey * ey);
2226 theta = atan2(ey, ex);
2227 theta += rotation;
2228 ex = er * cos(theta);
2229 ey = er * sin(theta);
2230 }
2231
2232 // Take care of symmetry.
2233 double eaxis;
2234 er = ex;
2235 eaxis = ey;
2236
2237 // Rotational symmetry
2238 if (m_rotationSymmetric[0]) {
2239 if (rcoordinate <= 0) {
2240 ex = eaxis;
2241 ey = 0;
2242 ez = 0;
2243 } else {
2244 ex = eaxis;
2245 ey = er * ypos / rcoordinate;
2246 ez = er * zpos / rcoordinate;
2247 }
2248 }
2249 if (m_rotationSymmetric[1]) {
2250 if (rcoordinate <= 0) {
2251 ex = 0;
2252 ey = eaxis;
2253 ez = 0;
2254 } else {
2255 ex = er * xpos / rcoordinate;
2256 ey = eaxis;
2257 ez = er * zpos / rcoordinate;
2258 }
2259 }
2260 if (m_rotationSymmetric[2]) {
2261 if (rcoordinate <= 0) {
2262 ex = 0;
2263 ey = 0;
2264 ez = eaxis;
2265 } else {
2266 ex = er * xpos / rcoordinate;
2267 ey = er * ypos / rcoordinate;
2268 ez = eaxis;
2269 }
2270 }
2271}

Referenced by Garfield::ComponentAnsys121::ElectricField(), Garfield::ComponentAnsys123::ElectricField(), Garfield::ComponentComsol::ElectricField(), Garfield::ComponentElmer::ElectricField(), Garfield::ComponentAnsys121::WeightingField(), Garfield::ComponentAnsys123::WeightingField(), Garfield::ComponentComsol::WeightingField(), and Garfield::ComponentElmer::WeightingField().

◆ UpdatePeriodicity2d()

void Garfield::ComponentFieldMap::UpdatePeriodicity2d ( )
protected

Definition at line 1905 of file ComponentFieldMap.cc.

1905 {
1906 // Check the required data is available.
1907 if (!m_ready) {
1908 std::cerr << m_className << "::UpdatePeriodicity2d:\n";
1909 std::cerr << " No valid field map available.\n";
1910 return;
1911 }
1912
1913 // No z-periodicity in 2d
1914 if (m_periodic[2] || m_mirrorPeriodic[2]) {
1915 std::cerr << m_className << "::UpdatePeriodicity2d:\n";
1916 std::cerr << " Simple or mirror periodicity along z\n";
1917 std::cerr << " requested for a 2d map; reset.\n";
1918 m_periodic[2] = false;
1919 m_mirrorPeriodic[2] = false;
1920 m_warning = true;
1921 }
1922
1923 // Only z-axial periodicity in 2d maps
1924 if (m_axiallyPeriodic[0] || m_axiallyPeriodic[1]) {
1925 std::cerr << m_className << "::UpdatePeriodicity2d:\n";
1926 std::cerr << " Axial symmetry has been requested \n";
1927 std::cerr << " around x or y for a 2D map; reset.\n";
1928 m_axiallyPeriodic[0] = false;
1929 m_axiallyPeriodic[1] = false;
1930 m_warning = true;
1931 }
1932}

Referenced by Garfield::ComponentAnsys121::UpdatePeriodicity(), and Garfield::ComponentCST::UpdatePeriodicity().

◆ UpdatePeriodicityCommon()

void Garfield::ComponentFieldMap::UpdatePeriodicityCommon ( )
protected

Definition at line 1753 of file ComponentFieldMap.cc.

1753 {
1754 // Check the required data is available.
1755 if (!m_ready) {
1756 std::cerr << m_className << "::UpdatePeriodicityCommon:\n";
1757 std::cerr << " No valid field map available.\n";
1758 return;
1759 }
1760
1761 for (unsigned int i = 0; i < 3; ++i) {
1762 // No regular and mirror periodicity at the same time.
1763 if (m_periodic[i] && m_mirrorPeriodic[i]) {
1764 std::cerr << m_className << "::UpdatePeriodicityCommon:\n"
1765 << " Both simple and mirror periodicity requested. Reset.\n";
1766 m_periodic[i] = false;
1767 m_mirrorPeriodic[i] = false;
1768 m_warning = true;
1769 }
1770 // In case of axial periodicity,
1771 // the range must be an integral part of two pi.
1772 if (m_axiallyPeriodic[i]) {
1773 if (m_mapamin[i] >= m_mapamax[i]) {
1774 m_mapna[i] = 0;
1775 } else {
1776 m_mapna[i] = TwoPi / (m_mapamax[i] - m_mapamin[i]);
1777 }
1778 if (fabs(m_mapna[i] - int(0.5 + m_mapna[i])) > 0.001 ||
1779 m_mapna[i] < 1.5) {
1780 std::cerr
1781 << m_className << "::UpdatePeriodicityCommon:\n"
1782 << " Axial symmetry has been requested but the map\n"
1783 << " does not cover an integral fraction of 2 pi. Reset.\n";
1784 m_axiallyPeriodic[i] = false;
1785 m_warning = true;
1786 }
1787 }
1788 }
1789
1790 // Not more than 1 rotational symmetry
1794 std::cerr << m_className << "::UpdatePeriodicityCommon:\n";
1795 std::cerr << " Only 1 rotational symmetry allowed; reset.\n";
1796 m_rotationSymmetric.fill(false);
1797 m_warning = true;
1798 }
1799
1800 // No rotational symmetry as well as axial periodicity
1802 m_rotationSymmetric[2]) &&
1804 std::cerr << m_className << "::UpdatePeriodicityCommon:\n";
1805 std::cerr << " Not allowed to combine rotational symmetry\n";
1806 std::cerr << " and axial periodicity; reset.\n";
1807 m_axiallyPeriodic.fill(false);
1808 m_rotationSymmetric.fill(false);
1809 m_warning = true;
1810 }
1811
1812 // In case of rotational symmetry, the x-range should not straddle 0.
1815 if (m_mapmin[0] * m_mapmax[0] < 0) {
1816 std::cerr << m_className << "::UpdatePeriodicityCommon:\n";
1817 std::cerr << " Rotational symmetry requested, \n";
1818 std::cerr << " but x-range straddles 0; reset.\n";
1819 m_rotationSymmetric.fill(false);
1820 m_warning = true;
1821 }
1822 }
1823
1824 // Recompute the cell ranges.
1825 for (unsigned int i = 0; i < 3; ++i) {
1826 m_minBoundingBox[i] = m_mapmin[i];
1827 m_maxBoundingBox[i] = m_mapmax[i];
1828 m_cells[i] = fabs(m_mapmax[i] - m_mapmin[i]);
1829 }
1830 if (m_rotationSymmetric[0]) {
1831 m_minBoundingBox[0] = m_mapmin[1];
1832 m_maxBoundingBox[0] = m_mapmax[1];
1833 m_minBoundingBox[1] = -std::max(fabs(m_mapmin[0]), fabs(m_mapmax[0]));
1834 m_maxBoundingBox[1] = +std::max(fabs(m_mapmin[0]), fabs(m_mapmax[0]));
1835 m_minBoundingBox[2] = -std::max(fabs(m_mapmin[0]), fabs(m_mapmax[0]));
1836 m_maxBoundingBox[2] = +std::max(fabs(m_mapmin[0]), fabs(m_mapmax[0]));
1837 } else if (m_rotationSymmetric[1]) {
1838 m_minBoundingBox[0] = -std::max(fabs(m_mapmin[0]), fabs(m_mapmax[0]));
1839 m_maxBoundingBox[0] = +std::max(fabs(m_mapmin[0]), fabs(m_mapmax[0]));
1840 m_minBoundingBox[1] = m_mapmin[1];
1841 m_maxBoundingBox[1] = m_mapmax[1];
1842 m_minBoundingBox[2] = -std::max(fabs(m_mapmin[0]), fabs(m_mapmax[0]));
1843 m_maxBoundingBox[2] = +std::max(fabs(m_mapmin[0]), fabs(m_mapmax[0]));
1844 } else if (m_rotationSymmetric[2]) {
1845 m_minBoundingBox[0] = -std::max(fabs(m_mapmin[0]), fabs(m_mapmax[0]));
1846 m_maxBoundingBox[0] = +std::max(fabs(m_mapmin[0]), fabs(m_mapmax[0]));
1847 m_minBoundingBox[1] = -std::max(fabs(m_mapmin[0]), fabs(m_mapmax[0]));
1848 m_maxBoundingBox[1] = +std::max(fabs(m_mapmin[0]), fabs(m_mapmax[0]));
1849 m_minBoundingBox[2] = m_mapmin[1];
1850 m_maxBoundingBox[2] = m_mapmax[1];
1851 }
1852
1853 if (m_axiallyPeriodic[0]) {
1854 m_minBoundingBox[1] =
1855 -std::max(std::max(fabs(m_mapmin[1]), fabs(m_mapmax[1])),
1856 std::max(fabs(m_mapmin[2]), fabs(m_mapmax[2])));
1857 m_maxBoundingBox[1] =
1858 +std::max(std::max(fabs(m_mapmin[1]), fabs(m_mapmax[1])),
1859 std::max(fabs(m_mapmin[2]), fabs(m_mapmax[2])));
1860 m_minBoundingBox[2] =
1861 -std::max(std::max(fabs(m_mapmin[1]), fabs(m_mapmax[1])),
1862 std::max(fabs(m_mapmin[2]), fabs(m_mapmax[2])));
1863 m_maxBoundingBox[2] =
1864 +std::max(std::max(fabs(m_mapmin[1]), fabs(m_mapmax[1])),
1865 std::max(fabs(m_mapmin[2]), fabs(m_mapmax[2])));
1866 } else if (m_axiallyPeriodic[1]) {
1867 m_minBoundingBox[0] =
1868 -std::max(std::max(fabs(m_mapmin[0]), fabs(m_mapmax[0])),
1869 std::max(fabs(m_mapmin[2]), fabs(m_mapmax[2])));
1870 m_maxBoundingBox[0] =
1871 +std::max(std::max(fabs(m_mapmin[0]), fabs(m_mapmax[0])),
1872 std::max(fabs(m_mapmin[2]), fabs(m_mapmax[2])));
1873 m_minBoundingBox[2] =
1874 -std::max(std::max(fabs(m_mapmin[0]), fabs(m_mapmax[0])),
1875 std::max(fabs(m_mapmin[2]), fabs(m_mapmax[2])));
1876 m_maxBoundingBox[2] =
1877 +std::max(std::max(fabs(m_mapmin[0]), fabs(m_mapmax[0])),
1878 std::max(fabs(m_mapmin[2]), fabs(m_mapmax[2])));
1879 } else if (m_axiallyPeriodic[2]) {
1880 m_minBoundingBox[0] =
1881 -std::max(std::max(fabs(m_mapmin[0]), fabs(m_mapmax[0])),
1882 std::max(fabs(m_mapmin[1]), fabs(m_mapmax[1])));
1883 m_maxBoundingBox[0] =
1884 +std::max(std::max(fabs(m_mapmin[0]), fabs(m_mapmax[0])),
1885 std::max(fabs(m_mapmin[1]), fabs(m_mapmax[1])));
1886 m_minBoundingBox[1] =
1887 -std::max(std::max(fabs(m_mapmin[0]), fabs(m_mapmax[0])),
1888 std::max(fabs(m_mapmin[1]), fabs(m_mapmax[1])));
1889 m_maxBoundingBox[1] =
1890 +std::max(std::max(fabs(m_mapmin[0]), fabs(m_mapmax[0])),
1891 std::max(fabs(m_mapmin[1]), fabs(m_mapmax[1])));
1892 }
1893
1894 for (unsigned int i = 0; i < 3; ++i) {
1895 if (m_periodic[i] || m_mirrorPeriodic[i]) {
1896 m_minBoundingBox[i] = -INFINITY;
1897 m_maxBoundingBox[i] = +INFINITY;
1898 }
1899 }
1900
1901 // Display the range if requested.
1902 if (m_debug) PrintRange();
1903}
DoubleAc fabs(const DoubleAc &f)
Definition: DoubleAc.h:615

Referenced by Garfield::ComponentAnsys121::UpdatePeriodicity(), Garfield::ComponentAnsys123::UpdatePeriodicity(), Garfield::ComponentComsol::UpdatePeriodicity(), Garfield::ComponentCST::UpdatePeriodicity(), and Garfield::ComponentElmer::UpdatePeriodicity().

Friends And Related Function Documentation

◆ ViewFEMesh

friend class ViewFEMesh
friend

Definition at line 84 of file ComponentFieldMap.hh.

Member Data Documentation

◆ elements

◆ hasBoundingBox

bool Garfield::ComponentFieldMap::hasBoundingBox = false
protected

Definition at line 132 of file ComponentFieldMap.hh.

Referenced by SetRange(), and Garfield::ComponentCST::SetRange().

◆ m_cells

std::array<double, 3> Garfield::ComponentFieldMap::m_cells
protected

Definition at line 142 of file ComponentFieldMap.hh.

Referenced by PrintRange(), and UpdatePeriodicityCommon().

◆ m_deleteBackground

bool Garfield::ComponentFieldMap::m_deleteBackground = true
protected

◆ m_is3d

bool Garfield::ComponentFieldMap::m_is3d = true
protected

◆ m_mapamax

std::array<double, 3> Garfield::ComponentFieldMap::m_mapamax
protected

Definition at line 140 of file ComponentFieldMap.hh.

Referenced by MapCoordinates(), SetRange(), and UpdatePeriodicityCommon().

◆ m_mapamin

std::array<double, 3> Garfield::ComponentFieldMap::m_mapamin
protected

Definition at line 139 of file ComponentFieldMap.hh.

Referenced by MapCoordinates(), SetRange(), and UpdatePeriodicityCommon().

◆ m_mapmax

std::array<double, 3> Garfield::ComponentFieldMap::m_mapmax
protected

◆ m_mapmin

std::array<double, 3> Garfield::ComponentFieldMap::m_mapmin
protected

◆ m_mapna

std::array<double, 3> Garfield::ComponentFieldMap::m_mapna
protected

Definition at line 141 of file ComponentFieldMap.hh.

Referenced by PrintRange(), and UpdatePeriodicityCommon().

◆ m_mapvmax

double Garfield::ComponentFieldMap::m_mapvmax
protected

◆ m_mapvmin

double Garfield::ComponentFieldMap::m_mapvmin
protected

◆ m_maxBoundingBox

◆ m_minBoundingBox

◆ m_nMaterials

◆ m_nWarnings

◆ m_setang

std::array<bool, 3> Garfield::ComponentFieldMap::m_setang
protected

Definition at line 146 of file ComponentFieldMap.hh.

Referenced by SetRange().

◆ m_warning

◆ materials

◆ nElements

◆ nNodes

◆ nodes

◆ nWeightingFields

◆ wfields

◆ wfieldsOk


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