17 const double x,
const double y,
const double z,
18 double& ex,
double& ey,
double& ez,
double& p,
Medium*& m,
int& status) {
25 <<
" Field map is not available for interpolation.\n";
32 if (!GetField(x, y, z, m_efields, ex, ey, ez, p, region)) {
37 if (region < 0 || region > (
int)m_media.size()) {
47 const double x,
const double y,
const double z,
48 double& ex,
double& ey,
double& ez,
Medium*& m,
int& status) {
54 const double x,
const double y,
const double z,
55 double& wx,
double& wy,
double& wz,
const std::string& ) {
58 if (!m_hasWfield)
return;
59 const double xx = x - m_wField_xOffset;
60 const double yy = y - m_wField_yOffset;
61 const double zz = z - m_wField_zOffset;
64 GetField(xx, yy, zz, m_wfields, wx, wy, wz, wp, region);
68 const double x,
const double y,
const double z,
69 const std::string& ) {
71 if (!m_hasWfield)
return 0.;
72 const double xx = x - m_wField_xOffset;
73 const double yy = y - m_wField_yOffset;
74 const double zz = z - m_wField_zOffset;
75 double wx = 0., wy = 0., wz = 0.;
78 if (!GetField(xx, yy, zz, m_wfields, wx, wy, wz, wp, region))
return 0.;
83 const double x,
const double y,
const double z,
const double t,
84 double& wx,
double& wy,
double& wz,
const std::string& ) {
87 if (m_wdtimes.empty())
return;
89 if (t < m_wdtimes.front() || t > m_wdtimes.back())
return;
91 const double xx = x - m_wField_xOffset;
92 const double yy = y - m_wField_yOffset;
93 const double zz = z - m_wField_zOffset;
95 const auto it1 = std::upper_bound(m_wdtimes.cbegin(), m_wdtimes.cend(), t);
96 const auto it0 = std::prev(it1);
98 const double dt = t - *it0;
101 const unsigned int i0 = it0 - m_wdtimes.cbegin();
102 double wx0 = 0., wy0 = 0., wz0 = 0.;
103 if (!GetField(xx, yy, zz, m_wdfields[i0], wx0, wy0, wz0, wp, region)) {
106 if (dt < Small || it1 == m_wdtimes.cend()) {
112 const unsigned int i1 = it1 - m_wdtimes.cbegin();
113 double wx1 = 0., wy1 = 0., wz1 = 0.;
114 if (!GetField(xx, yy, zz, m_wdfields[i1], wx1, wy1, wz1, wp, region)) {
117 const double f1 = dt / (*it1 - *it0);
118 const double f0 = 1. - f1;
119 wx = f0 * wx0 + f1 * wx1;
120 wy = f0 * wy0 + f1 * wy1;
121 wz = f0 * wz0 + f1 * wz1;
125 const double x,
const double y,
const double z,
const double t,
126 const std::string& ) {
128 if (m_wdtimes.empty())
return 0.;
130 if (t < m_wdtimes.front() || t > m_wdtimes.back())
return 0.;
132 const double xx = x - m_wField_xOffset;
133 const double yy = y - m_wField_yOffset;
134 const double zz = z - m_wField_zOffset;
136 const auto it1 = std::upper_bound(m_wdtimes.cbegin(), m_wdtimes.cend(), t);
137 const auto it0 = std::prev(it1);
139 const double dt = t - *it0;
141 const unsigned int i0 = it0 - m_wdtimes.cbegin();
142 double wp0 = 0., wx0 = 0., wy0 = 0., wz0 = 0.;
143 if (!GetField(xx, yy, zz, m_wdfields[i0], wx0, wy0, wz0, wp0, region)) {
146 if (dt < Small || it1 == m_wdtimes.cend())
return 0.;
148 const unsigned int i1 = it1 - m_wdtimes.cbegin();
149 double wp1 = 0., wx1 = 0., wy1 = 0., wz1 = 0.;
150 if (!GetField(xx, yy, zz, m_wdfields[i1], wx1, wy1, wz1, wp1, region)) {
153 const double f1 = dt / (*it1 - *it0);
154 const double f0 = 1. - f1;
155 return f0 * wp0 + f1 * wp1;
160 m_wField_xOffset = x;
161 m_wField_yOffset = y;
162 m_wField_zOffset = z;
166 const double z,
double& bx,
double& by,
167 double& bz,
int& status) {
175 if (!GetField(x, y, z, m_bfields, bx, by, bz, p, region)) {
189 <<
" Field map is not available for interpolation.\n";
193 unsigned int i, j, k;
194 bool xMirrored, yMirrored, zMirrored;
195 if (!
GetElement(x, y, z, i, j, k, xMirrored, yMirrored, zMirrored)) {
198 const int region = m_regions[i][j][k];
199 if (region < 0 || region > (
int)m_media.size())
return nullptr;
200 return m_media[region];
204 const unsigned int nz,
const double xmin,
205 const double xmax,
const double ymin,
206 const double ymax,
const double zmin,
209 if (nx == 0 || ny == 0 || nz == 0) {
211 <<
" Number of mesh elements must be positive.\n";
215 std::cerr <<
m_className <<
"::SetMesh: Invalid x range.\n";
217 }
else if (ymin >= ymax) {
218 std::cerr <<
m_className <<
"::SetMesh: Invalid y range.\n";
220 }
else if (zmin >= zmax) {
221 std::cerr <<
m_className <<
"::SetMesh: Invalid z range.\n";
233 m_dx = (m_xMax - m_xMin) / m_nX;
234 m_dy = (m_yMax - m_yMin) / m_nY;
235 m_dz = (m_zMax - m_zMin) / m_nZ;
240 const std::string& fmt,
241 const bool withP,
const bool withR,
242 const double scaleX,
const double scaleE,
243 const double scaleP) {
246 m_hasPotential = m_hasEfield =
false;
248 std::cerr <<
m_className <<
"::LoadElectricField:\n"
249 <<
" Mesh is not set. Call SetMesh first.\n";
254 Initialise(m_efields);
257 m_pMin = m_pMax = 0.;
262 if (!LoadData(fname, fmt, withP, withR, scaleX, scaleE, scaleP, m_efields)) {
267 if (withP) m_hasPotential =
true;
272 const std::string& fmt,
276 const double scaleP) {
279 std::cerr <<
m_className <<
"::LoadWeightingField:\n"
280 <<
" Mesh is not set. Call SetMesh first.\n";
285 Initialise(m_wfields);
286 if (m_regions.empty()) InitialiseRegions();
289 if (!LoadData(fname, fmt, withP,
false, scaleX, scaleE, scaleP, m_wfields)) {
296 const std::string& fmt,
297 const double t,
const bool withP,
298 const double scaleX,
const double scaleE,
299 const double scaleP) {
302 std::cerr <<
m_className <<
"::LoadWeightingField:\n"
303 <<
" Mesh is not set. Call SetMesh first.\n";
307 std::vector<std::vector<std::vector<Element> > > wfield;
309 if (m_regions.empty()) InitialiseRegions();
312 if (!LoadData(fname, fmt, withP,
false, scaleX, scaleE, scaleP, wfield)) {
315 if (m_wdtimes.empty() || t > m_wdtimes.back()) {
316 m_wdtimes.push_back(t);
317 m_wdfields.push_back(std::move(wfield));
319 const auto it = std::upper_bound(m_wdtimes.begin(), m_wdtimes.end(), t);
320 const auto n = std::distance(m_wdtimes.begin(), it);
321 m_wdtimes.insert(it, t);
322 m_wdfields.insert(m_wdfields.begin() + n, std::move(wfield));
328 const std::string& fmt,
330 const double scaleB) {
333 std::cerr <<
m_className <<
"::LoadMagneticField:\n"
334 <<
" Mesh is not set. Call SetMesh first.\n";
339 Initialise(m_bfields);
343 if (!LoadData(fname, fmt,
false,
false, scaleX, scaleB, 1., m_bfields)) {
350bool ComponentVoxel::LoadData(
const std::string& filename, std::string format,
351 const bool withPotential,
const bool withRegion,
352 const double scaleX,
const double scaleF,
const double scaleP,
353 std::vector<std::vector<std::vector<Element> > >& fields) {
356 std::cerr <<
m_className <<
"::LoadData: Mesh has not been set.\n";
360 unsigned int nValues = 0;
362 std::vector<std::vector<std::vector<bool> > > isSet(
364 std::vector<std::vector<bool> >(m_nY, std::vector<bool>(m_nZ,
false)));
366 std::ifstream infile(filename);
369 <<
" Could not open file " << filename <<
".\n";
373 std::transform(format.begin(), format.end(), format.begin(), toupper);
374 unsigned int fmt = 0;
375 if (format ==
"XY") {
377 }
else if (format ==
"XYZ") {
379 }
else if (format ==
"IJ") {
381 }
else if (format ==
"IJK") {
383 }
else if (format ==
"YXZ") {
387 <<
" Unknown format (" << format <<
").\n";
391 unsigned int nLines = 0;
394 while (std::getline(infile, line)) {
399 if (line.empty())
continue;
401 if (line[0] ==
'#')
continue;
402 if (line[0] ==
'/' && line[1] ==
'/')
continue;
411 std::istringstream data(line);
418 <<
" Error reading line " << nLines <<
".\n"
419 <<
" Cannot retrieve element coordinates.\n";
425 const double z = 0.5 * (m_zMin + m_zMax);
426 bool xMirrored, yMirrored, zMirrored;
427 if (!
GetElement(x, y, z, i, j, k, xMirrored, yMirrored, zMirrored)) {
429 <<
" Error reading line " << nLines <<
".\n"
430 <<
" Point is outside mesh.\n";
434 }
else if (fmt == 2) {
440 <<
" Error reading line " << nLines <<
".\n"
441 <<
" Cannot retrieve element coordinates.\n";
448 bool xMirrored, yMirrored, zMirrored;
449 if (!
GetElement(x, y, z, i, j, k, xMirrored, yMirrored, zMirrored)) {
451 <<
" Error reading line " << nLines <<
".\n"
452 <<
" Point is outside mesh.\n";
456 }
else if (fmt == 3) {
462 <<
" Error reading line " << nLines <<
".\n"
463 <<
" Cannot retrieve element index.\n";
467 }
else if (fmt == 4) {
472 <<
" Error reading line " << nLines <<
".\n"
473 <<
" Cannot retrieve element index.\n";
477 }
else if (fmt == 5) {
479 double x,
y,
z, temp;
480 data >>
y >>
x >> temp;
484 <<
" Error reading line " << nLines <<
".\n"
485 <<
" Cannot retrieve element coordinates.\n";
492 bool xMirrored, yMirrored, zMirrored;
493 if (!
GetElement(x, y, z, i, j, k, xMirrored, yMirrored, zMirrored)) {
495 <<
" Error reading line " << nLines <<
".\n"
496 <<
" Point is outside mesh.\n";
502 if (i >= m_nX || j >= m_nY || k >= m_nZ) {
504 <<
" Error reading line " << nLines <<
".\n"
505 <<
" Index (" << i <<
", " << j <<
", " << k
506 <<
") out of range.\n";
509 if (isSet[i][j][k]) {
511 <<
" Error reading line " << nLines <<
".\n"
512 <<
" Mesh element (" << i <<
", " << j <<
", " << k
513 <<
") has already been set.\n";
517 if (fmt == 1 || fmt == 3) {
521 }
else if (fmt == 5) {
523 data >> fy >> fx >> temp;
526 data >> fx >> fy >> fz;
530 <<
" Error reading line " << nLines <<
".\n"
531 <<
" Cannot read field values.\n";
542 <<
" Error reading line " << nLines <<
".\n"
543 <<
" Cannot read potential.\n";
548 if (m_pMin > m_pMax) {
553 if (v < m_pMin) m_pMin = v;
554 if (v > m_pMax) m_pMax = v;
561 <<
" Error reading line " << nLines <<
".\n"
562 <<
" Cannot read region.\n";
567 if (fmt == 1 || fmt == 3) {
569 for (
unsigned int kk = 0; kk < m_nZ; ++kk) {
570 fields[i][j][kk].fx = fx;
571 fields[i][j][kk].fy = fy;
572 fields[i][j][kk].fz = fz;
573 fields[i][j][kk].v = v;
574 if (withRegion) m_regions[i][j][kk] = region;
575 isSet[i][j][kk] =
true;
578 fields[i][j][k].fx = fx;
579 fields[i][j][k].fy = fy;
580 fields[i][j][k].fz = fz;
581 fields[i][j][k].v = v;
582 if (withRegion) m_regions[i][j][k] = region;
583 isSet[i][j][k] =
true;
587 if (bad)
return false;
589 <<
" Read " << nValues <<
" values from " << filename <<
".\n";
590 unsigned int nExpected = m_nX * m_nY;
591 if (fmt == 2 || fmt == 4 || fmt == 5) nExpected *= m_nZ;
592 if (nExpected != nValues) {
594 <<
" Expected " << nExpected <<
" values.\n";
600 double& xmax,
double& ymax,
double& zmax) {
629 double& xmin,
double& ymin,
double& zmin,
630 double& xmax,
double& ymax,
double& zmax) {
649 double& eymin,
double& eymax,
650 double& ezmin,
double& ezmax) {
652 std::cerr <<
m_className <<
"::GetElectricFieldRange:\n"
653 <<
" Field map is not ready for interpolation.\n";
657 exmin = exmax = m_efields[0][0][0].fx;
658 eymin = eymax = m_efields[0][0][0].fy;
659 ezmin = ezmax = m_efields[0][0][0].fz;
660 for (
unsigned int i = 0; i < m_nX; ++i) {
661 for (
unsigned int j = 0; j < m_nY; ++j) {
662 for (
unsigned int k = 0; k < m_nZ; ++k) {
663 const Element& element = m_efields[i][j][k];
664 if (element.fx < exmin) exmin = element.fx;
665 if (element.fx > exmax) exmax = element.fx;
666 if (element.fy < eymin) eymin = element.fy;
667 if (element.fy > eymax) eymax = element.fy;
668 if (element.fz < ezmin) ezmin = element.fz;
669 if (element.fz > ezmax) ezmax = element.fz;
680 <<
" Field map not yet initialised.\n";
684 if (m_media.empty()) {
685 std::cerr <<
m_className <<
"::PrintRegions: No regions defined.\n";
690 std::cout <<
" Index Medium\n";
691 const unsigned int nMedia = m_media.size();
692 for (
unsigned int i = 0; i < nMedia; ++i) {
693 const std::string name = m_media[i] ? m_media[i]->GetName() :
"none";
694 std::cout <<
" " << i <<
" " << name <<
"\n";
700 std::cerr <<
m_className <<
"::SetMedium: Null pointer.\n";
701 if (m_media.empty())
return;
703 if (i >= m_media.size()) m_media.resize(i + 1,
nullptr);
708 if (i >= m_media.size()) {
709 std::cerr <<
m_className <<
"::GetMedium: Index out of range.\n";
715bool ComponentVoxel::GetField(
716 const double xi,
const double yi,
const double zi,
717 const std::vector<std::vector<std::vector<Element> > >& field,
double& fx,
718 double& fy,
double& fz,
double& p,
int& region) {
720 std::cerr <<
m_className <<
"::GetField: Mesh is not set.\n";
726 bool xMirrored =
false;
729 if (x < m_xMin || x > m_xMax)
return false;
730 bool yMirrored =
false;
733 if (y < m_yMin || y > m_yMax)
return false;
734 bool zMirrored =
false;
737 if (z < m_zMin || z > m_zMax)
return false;
740 const double sx = (x - m_xMin) / m_dx;
741 const double sy = (y - m_yMin) / m_dy;
742 const double sz = (z - m_zMin) / m_dz;
743 unsigned int i =
static_cast<unsigned int>(sx);
744 unsigned int j =
static_cast<unsigned int>(sy);
745 unsigned int k =
static_cast<unsigned int>(sz);
746 if (i >= m_nX) i = m_nX - 1;
747 if (j >= m_nY) j = m_nY - 1;
748 if (k >= m_nZ) k = m_nZ - 1;
749 region = m_regions[i][j][k];
754 const double tx = sx - 0.5;
755 const double ty = sy - 0.5;
756 const double tz = sz - 0.5;
757 int i0 =
static_cast<int>(std::floor(tx));
758 int j0 =
static_cast<int>(std::floor(ty));
759 int k0 =
static_cast<int>(std::floor(tz));
763 unsigned int i1 = i0 + 1;
764 unsigned int j1 = j0 + 1;
765 unsigned int k1 = k0 + 1;
793 if (i1 >= m_nX) i1 = perx ? 0 : m_nX - 1;
794 if (j1 >= m_nY) j1 = pery ? 0 : m_nY - 1;
795 if (k1 >= m_nZ) k1 = perz ? 0 : m_nZ - 1;
796 const Element& n000 = field[i0][j0][k0];
797 const Element& n100 = field[i1][j0][k0];
798 const Element& n010 = field[i0][j1][k0];
799 const Element& n110 = field[i1][j1][k0];
800 const Element& n001 = field[i0][j0][k1];
801 const Element& n101 = field[i1][j0][k1];
802 const Element& n011 = field[i0][j1][k1];
803 const Element& n111 = field[i1][j1][k1];
805 const double ux = 1. - vx;
806 const double uy = 1. - vy;
807 const double uz = 1. - vz;
809 std::cout <<
m_className <<
"::GetField:\n Determining field at ("
810 << xi <<
", " << yi <<
", " << zi <<
").\n"
811 <<
" X: " << i0 <<
" (" << ux <<
") - "
812 << i1 <<
" (" << vx <<
").\n"
813 <<
" Y: " << j0 <<
" (" << uy <<
") - "
814 << j1 <<
" (" << vy <<
").\n"
815 <<
" Z: " << k0 <<
" (" << uz <<
") - "
816 << k1 <<
" (" << vz <<
").\n";
818 fx = ((n000.fx * ux + n100.fx * vx) * uy +
819 (n010.fx * ux + n110.fx * vx) * vy) *
821 ((n001.fx * ux + n101.fx * vx) * uy +
822 (n011.fx * ux + n111.fx * vx) * vy) *
824 fy = ((n000.fy * ux + n100.fy * vx) * uy +
825 (n010.fy * ux + n110.fy * vx) * vy) *
827 ((n001.fy * ux + n101.fy * vx) * uy +
828 (n011.fy * ux + n111.fy * vx) * vy) *
830 fz = ((n000.fz * ux + n100.fz * vx) * uy +
831 (n010.fz * ux + n110.fz * vx) * vy) *
833 ((n001.fz * ux + n101.fz * vx) * uy +
834 (n011.fz * ux + n111.fz * vx) * vy) *
836 p = ((n000.v * ux + n100.v * vx) * uy + (n010.v * ux + n110.v * vx) * vy) *
838 ((n001.v * ux + n101.v * vx) * uy + (n011.v * ux + n111.v * vx) * vy) *
841 const Element& element = field[i][j][k];
847 if (xMirrored) fx = -fx;
848 if (yMirrored) fy = -fy;
849 if (zMirrored) fz = -fz;
854 const double zi,
unsigned int& i,
855 unsigned int& j,
unsigned int& k,
856 bool& xMirrored,
bool& yMirrored,
857 bool& zMirrored)
const {
859 std::cerr <<
m_className <<
"::GetElement: Mesh is not set.\n";
867 if (x < m_xMin || x > m_xMax)
return false;
870 if (y < m_yMin || y > m_yMax)
return false;
873 if (z < m_zMin || z > m_zMax)
return false;
876 i = (
unsigned int)((x - m_xMin) / m_dx);
877 j = (
unsigned int)((y - m_yMin) / m_dy);
878 k = (
unsigned int)((z - m_zMin) / m_dz);
879 if (i >= m_nX) i = m_nX - 1;
880 if (j >= m_nY) j = m_nY - 1;
881 if (k >= m_nZ) k = m_nZ - 1;
886 const unsigned int k,
double& v,
double& ex,
887 double& ey,
double& ez)
const {
888 v = ex = ey = ez = 0.;
891 std::cerr <<
m_className <<
"::GetElement: Mesh not set.\n";
894 std::cerr <<
m_className <<
"::GetElement: Field map not set.\n";
897 if (i >= m_nX || j >= m_nY || k >= m_nZ) {
898 std::cerr <<
m_className <<
"::GetElement: Index out of range.\n";
901 const Element& element = m_efields[i][j][k];
909void ComponentVoxel::Reset() {
918 m_nX = m_nY = m_nZ = 0;
919 m_xMin = m_yMin = m_zMin = 0.;
920 m_xMax = m_yMax = m_zMax = 0.;
921 m_pMin = m_pMax = 0.;
925 m_hasPotential =
false;
931 m_wField_xOffset = 0.;
932 m_wField_yOffset = 0.;
933 m_wField_zOffset = 0.;
936void ComponentVoxel::UpdatePeriodicity() {
938 std::cerr <<
m_className <<
"::UpdatePeriodicity:\n"
939 <<
" Field map not available.\n";
944 for (
unsigned int i = 0; i < 3; ++i) {
946 std::cerr <<
m_className <<
"::UpdatePeriodicity:\n"
947 <<
" Both simple and mirror periodicity requested. Reset.\n";
953 std::cerr <<
m_className <<
"::UpdatePeriodicity:\n"
954 <<
" Axial symmetry is not supported. Reset.\n";
960 std::cerr <<
m_className <<
"::UpdatePeriodicity:\n"
961 <<
" Rotation symmetry is not supported. Reset.\n";
966double ComponentVoxel::Reduce(
const double xin,
const double xmin,
967 const double xmax,
const bool simplePeriodic,
968 const bool mirrorPeriodic,
bool& mirrored)
const {
971 const double lx = xmax - xmin;
972 if (simplePeriodic) {
973 x = xmin + fmod(x - xmin, lx);
974 if (x < xmin)
x += lx;
975 }
else if (mirrorPeriodic) {
976 double xNew = xmin + fmod(x - xmin, lx);
977 if (xNew < xmin) xNew += lx;
978 const int nx = int(floor(0.5 + (xNew - x) / lx));
979 if (nx != 2 * (nx / 2)) {
980 xNew = xmin + xmax - xNew;
988void ComponentVoxel::Initialise(
989 std::vector<std::vector<std::vector<Element> > >& fields) {
992 for (
unsigned int i = 0; i < m_nX; ++i) {
993 fields[i].resize(m_nY);
994 for (
unsigned int j = 0; j < m_nY; ++j) {
995 fields[i][j].resize(m_nZ);
996 for (
unsigned int k = 0; k < m_nZ; ++k) {
997 fields[i][j][k].fx = 0.;
998 fields[i][j][k].fy = 0.;
999 fields[i][j][k].fz = 0.;
1000 fields[i][j][k].v = 0.;
1006void ComponentVoxel::InitialiseRegions() {
1007 if (!m_hasMesh)
return;
1008 m_regions.resize(m_nX);
1009 for (
unsigned int i = 0; i < m_nX; ++i) {
1010 m_regions[i].resize(m_nY);
1011 for (
unsigned int j = 0; j < m_nY; ++j) {
1012 m_regions[i][j].assign(m_nZ, 0);
bool HasMagneticField() const override
Does the component have a non-zero magnetic field?
ComponentVoxel()
Constructor.
void MagneticField(const double x, const double y, const double z, double &bx, double &by, double &bz, int &status) override
void SetWeightingFieldOffset(const double x, const double y, const double z)
void PrintRegions() const
Print all regions.
bool LoadWeightingField(const std::string &filename, const std::string &format, const bool withPotential, const double scaleX=1., const double scaleE=1., const double scaleP=1.)
Import (prompt) weighting field from file.
bool GetBoundingBox(double &xmin, double &ymin, double &zmin, double &xmax, double &ymax, double &zmax) override
Get the bounding box coordinates.
bool GetElectricFieldRange(double &exmin, double &exmax, double &eymin, double &eymax, double &ezmin, double &ezmax)
Medium * GetMedium(const unsigned int i) const
Get the medium in region i.
void DelayedWeightingField(const double x, const double y, const double z, const double t, double &wx, double &wy, double &wz, const std::string &label) override
bool GetElement(const double xi, const double yi, const double zi, unsigned int &i, unsigned int &j, unsigned int &k, bool &xMirrored, bool &yMirrored, bool &zMirrored) const
Return the indices of the element at a given point.
bool GetVoltageRange(double &vmin, double &vmax) override
Calculate the voltage range [V].
bool GetElementaryCell(double &xmin, double &ymin, double &zmin, double &xmax, double &ymax, double &zmax) override
Get the coordinates of the elementary cell.
void SetMedium(const unsigned int i, Medium *m)
Set the medium in region i.
void WeightingField(const double x, const double y, const double z, double &wx, double &wy, double &wz, const std::string &label) override
double DelayedWeightingPotential(const double x, const double y, const double z, const double t, const std::string &label) override
void ElectricField(const double x, const double y, const double z, double &ex, double &ey, double &ez, double &v, Medium *&m, int &status) override
Calculate the drift field [V/cm] and potential [V] at (x, y, z).
void SetMesh(const unsigned int nx, const unsigned int ny, const unsigned int nz, const double xmin, const double xmax, const double ymin, const double ymax, const double zmin, const double zmax)
double WeightingPotential(const double x, const double y, const double z, const std::string &label) override
bool LoadElectricField(const std::string &filename, const std::string &format, const bool withPotential, const bool withRegion, const double scaleX=1., const double scaleE=1., const double scaleP=1.)
bool LoadMagneticField(const std::string &filename, const std::string &format, const double scaleX=1., const double scaleB=1.)
Import magnetic field values from a file.
std::array< bool, 3 > m_rotationSymmetric
Rotation symmetry around x-axis, y-axis, z-axis.
std::array< bool, 3 > m_mirrorPeriodic
Mirror periodicity in x, y, z.
bool m_debug
Switch on/off debugging messages.
Component()=delete
Default constructor.
std::array< bool, 3 > m_periodic
Simple periodicity in x, y, z.
virtual bool HasMagneticField() const
Does the component have a non-zero magnetic field?
std::string m_className
Class name.
virtual void MagneticField(const double x, const double y, const double z, double &bx, double &by, double &bz, int &status)
bool m_ready
Ready for use?
std::array< bool, 3 > m_axiallyPeriodic
Axial periodicity in x, y, z.
Abstract base class for media.
void ltrim(std::string &line)