24 m_hasPotential(false),
34 const double z,
double& ex,
double& ey,
35 double& ez,
double& p,
Medium*& m,
42 <<
" Field map is not available for interpolation.\n";
48 unsigned int i = 0, j = 0, k = 0;
49 bool xMirrored =
false, yMirrored =
false, zMirrored =
false;
50 if (!
GetElement(x, y, z, i, j, k, xMirrored, yMirrored, zMirrored)) {
56 const Element& element = m_efields[i][j][k];
60 if (xMirrored) ex = -ex;
61 if (yMirrored) ey = -ey;
62 if (zMirrored) ez = -ez;
65 const int region = m_regions[i][j][k];
66 if (region < 0 || region > (
int)m_media.size()) {
76 const double z,
double& ex,
double& ey,
77 double& ez,
Medium*& m,
int& status) {
84 const double z,
double& wx,
double& wy,
85 double& wz,
const std::string& ) {
89 double x1 = x - m_wField_xOffset;
90 double y1 = y - m_wField_yOffset;
91 double z1 = z - m_wField_zOffset;
104 double& bx,
double& by,
double& bz,
112 unsigned int i = 0, j = 0, k = 0;
113 bool xMirrored =
false, yMirrored =
false, zMirrored =
false;
114 if (!
GetElement(x, y, z, i, j, k, xMirrored, yMirrored, zMirrored)) {
120 const Element& element = m_bfields[i][j][k];
124 if (xMirrored) bx = -bx;
125 if (yMirrored) by = -by;
126 if (zMirrored) bz = -bz;
135 <<
" Field map is not available for interpolation.\n";
139 unsigned int i, j, k;
140 bool xMirrored, yMirrored, zMirrored;
141 if (!
GetElement(x, y, z, i, j, k, xMirrored, yMirrored, zMirrored)) {
144 const int region = m_regions[i][j][k];
145 if (region < 0 || region > (
int)m_media.size())
return NULL;
146 return m_media[region];
150 const unsigned int nz,
151 const double xmin,
const double xmax,
152 const double ymin,
const double ymax,
153 const double zmin,
const double zmax) {
156 if (nx == 0 || ny == 0 || nz == 0) {
158 <<
" Number of mesh elements must be positive.\n";
162 std::cerr <<
m_className <<
"::SetMesh:\n Invalid x range.\n";
164 }
else if (ymin >= ymax) {
165 std::cerr <<
m_className <<
"::SetMesh:\n Invalid y range.\n";
167 }
else if (zmin >= zmax) {
168 std::cerr <<
m_className <<
"::SetMesh:\n Invalid z range.\n";
184 const std::string& format,
185 const bool withPotential,
186 const bool withRegion,
189 const double scaleP) {
192 m_hasPotential = m_hasEfield =
false;
194 std::cerr <<
m_className <<
"::LoadElectricField:\n"
195 <<
" Mesh is not set. Call SetMesh first.\n";
200 m_efields.resize(m_nX);
201 m_regions.resize(m_nX);
202 for (
unsigned int i = 0; i < m_nX; ++i) {
203 m_efields[i].resize(m_nY);
204 m_regions[i].resize(m_nY);
205 for (
unsigned int j = 0; j < m_nY; ++j) {
206 m_efields[i][j].resize(m_nZ);
207 m_regions[i][j].resize(m_nZ);
208 for (
unsigned int k = 0; k < m_nZ; ++k) {
209 m_efields[i][j][k].fx = 0.;
210 m_efields[i][j][k].fy = 0.;
211 m_efields[i][j][k].fz = 0.;
212 m_efields[i][j][k].v = 0.;
213 m_regions[i][j][k] = 0;
218 m_pMin = m_pMax = 0.;
223 return LoadData(filename, format, withPotential, withRegion,
224 scaleX, scaleE, scaleP,
'e');
228 const std::string& format,
230 const double scaleB) {
234 std::cerr <<
m_className <<
"::LoadMagneticField:\n"
235 <<
" Mesh is not set. Call SetMesh first.\n";
240 m_bfields.resize(m_nX);
241 for (
unsigned int i = 0; i < m_nX; ++i) {
242 m_bfields[i].resize(m_nY);
243 for (
unsigned int j = 0; j < m_nY; ++j) {
244 m_bfields[i][j].resize(m_nZ);
245 for (
unsigned int k = 0; k < m_nZ; ++k) {
246 m_bfields[i][j][k].fx = 0.;
247 m_bfields[i][j][k].fy = 0.;
248 m_bfields[i][j][k].fz = 0.;
249 m_bfields[i][j][k].v = 0.;
254 return LoadData(filename, format,
false,
false, scaleX, scaleB, 1.,
'b');
257bool ComponentVoxel::LoadData(
const std::string& filename, std::string format,
258 const bool withPotential,
const bool withRegion,
259 const double scaleX,
const double scaleF,
260 const double scaleP,
const char field) {
263 std::cerr <<
m_className <<
"::LoadData:\n Mesh has not been set.\n";
267 unsigned int nValues = 0;
269 std::vector<std::vector<std::vector<bool> > > isSet(m_nX,
270 std::vector<std::vector<bool> >(m_nY, std::vector<bool>(m_nZ,
false)));
272 std::ifstream infile;
273 infile.open(filename.c_str(), std::ios::in);
276 <<
" Could not open file " << filename <<
".\n";
280 std::transform(format.begin(), format.end(), format.begin(), toupper);
281 unsigned int fmt = 0;
282 if (format ==
"XY") {
284 }
else if (format ==
"XYZ") {
286 }
else if (format ==
"IJ") {
288 }
else if (format ==
"IJK") {
290 }
else if (format ==
"YXZ") {
294 <<
" Unkown format (" << format <<
").\n";
298 unsigned int nLines = 0;
300 while (!infile.fail()) {
302 std::getline(infile, line);
305 line.erase(line.begin(),
306 std::find_if(line.begin(), line.end(),
307 not1(std::ptr_fun<int, int>(isspace))));
309 if (line.empty())
continue;
311 if (line[0] ==
'#')
continue;
312 if (line[0] ==
'/' && line[1] ==
'/')
continue;
321 std::istringstream data;
329 <<
" Error reading line " << nLines <<
".\n"
330 <<
" Cannot retrieve element coordinates.\n";
336 const double z = 0.5 * (m_zMin + m_zMax);
337 bool xMirrored, yMirrored, zMirrored;
338 if (!
GetElement(x, y, z, i, j, k, xMirrored, yMirrored, zMirrored)) {
340 <<
" Error reading line " << nLines <<
".\n"
341 <<
" Point is outside mesh.\n";
345 }
else if (fmt == 2) {
351 <<
" Error reading line " << nLines <<
".\n"
352 <<
" Cannot retrieve element coordinates.\n";
359 bool xMirrored, yMirrored, zMirrored;
360 if (!
GetElement(x, y, z, i, j, k, xMirrored, yMirrored, zMirrored)) {
362 <<
" Error reading line " << nLines <<
".\n"
363 <<
" Point is outside mesh.\n";
367 }
else if (fmt == 3) {
373 <<
" Error reading line " << nLines <<
".\n"
374 <<
" Cannot retrieve element index.\n";
378 }
else if (fmt == 4) {
383 <<
" Error reading line " << nLines <<
".\n"
384 <<
" Cannot retrieve element index.\n";
388 }
else if (fmt == 5) {
390 double x, y, z, temp;
391 data >> y >> x >> temp;
395 <<
" Error reading line " << nLines <<
".\n"
396 <<
" Cannot retrieve element coordinates.\n";
403 bool xMirrored, yMirrored, zMirrored;
404 if (!
GetElement(x, y, z, i, j, k, xMirrored, yMirrored, zMirrored)) {
406 <<
" Error reading line " << nLines <<
".\n"
407 <<
" Point is outside mesh.\n";
413 if (i >= m_nX || j >= m_nY || k >= m_nZ) {
415 <<
" Error reading line " << nLines <<
".\n"
416 <<
" Index (" << i <<
", " << j <<
", " << k
417 <<
") out of range.\n";
420 if (isSet[i][j][k]) {
422 <<
" Error reading line " << nLines <<
".\n"
423 <<
" Mesh element (" << i <<
", " << j <<
", " << k
424 <<
") has already been set.\n";
428 if (fmt == 1 || fmt == 3) {
432 }
else if (fmt == 5) {
434 data >> fy >> fx >> temp;
437 data >> fx >> fy >> fz;
441 <<
" Error reading line " << nLines <<
".\n"
442 <<
" Cannot read field values.\n";
453 <<
" Error reading line " << nLines <<
".\n"
454 <<
" Cannot read potential.\n";
459 if (m_pMin > m_pMax) {
464 if (v < m_pMin) m_pMin = v;
465 if (v > m_pMax) m_pMax = v;
472 <<
" Error reading line " << nLines <<
".\n"
473 <<
" Cannot read region.\n";
478 if (fmt == 1 || fmt == 3) {
480 for (
unsigned int kk = 0; kk < m_nZ; ++kk) {
482 m_efields[i][j][kk].fx = fx;
483 m_efields[i][j][kk].fy = fy;
484 m_efields[i][j][kk].fz = fz;
485 m_efields[i][j][kk].v = v;
486 m_regions[i][j][kk] = region;
487 }
else if (field ==
'b') {
488 m_bfields[i][j][kk].fx = fx;
489 m_bfields[i][j][kk].fy = fy;
490 m_bfields[i][j][kk].fz = fz;
492 isSet[i][j][kk] =
true;
496 m_efields[i][j][k].fx = fx;
497 m_efields[i][j][k].fy = fy;
498 m_efields[i][j][k].fz = fz;
499 m_efields[i][j][k].v = v;
500 m_regions[i][j][k] = region;
501 }
else if (field ==
'b') {
502 m_bfields[i][j][k].fx = fx;
503 m_bfields[i][j][k].fy = fy;
504 m_bfields[i][j][k].fz = fz;
506 isSet[i][j][k] =
true;
510 if (bad)
return false;
512 <<
" Read " << nValues <<
" values from " << filename <<
".\n";
513 unsigned int nExpected = m_nX * m_nY;
514 if (fmt == 2 || fmt == 4 || fmt == 5) nExpected *= m_nZ;
515 if (nExpected != nValues) {
517 <<
" Expected " << nExpected <<
" values.\n";
522 if (withPotential) m_hasPotential =
true;
523 }
else if (field ==
'b') {
530 double& xmax,
double& ymax,
double& zmax) {
568 double& eymin,
double& eymax,
569 double& ezmin,
double& ezmax) {
572 std::cerr <<
m_className <<
"::GetElectricFieldRange:\n";
573 std::cerr <<
" Field map not available.\n";
577 exmin = exmax = m_efields[0][0][0].fx;
578 eymin = eymax = m_efields[0][0][0].fy;
579 ezmin = ezmax = m_efields[0][0][0].fz;
580 for (
unsigned int i = 0; i < m_nX; ++i) {
581 for (
unsigned int j = 0; j < m_nY; ++j) {
582 for (
unsigned int k = 0; k < m_nZ; ++k) {
583 const Element& element = m_efields[i][j][k];
584 if (element.fx < exmin) exmin = element.fx;
585 if (element.fx > exmax) exmax = element.fx;
586 if (element.fy < eymin) eymin = element.fy;
587 if (element.fy > eymax) eymax = element.fy;
588 if (element.fz < ezmin) ezmin = element.fz;
589 if (element.fz > ezmax) ezmax = element.fz;
601 std::cerr <<
" Field map not yet initialised.\n";
605 if (m_media.empty()) {
606 std::cerr <<
m_className <<
"::PrintRegions:\n No regions defined.\n";
611 std::cout <<
" Index Medium\n";
612 const unsigned int nMedia = m_media.size();
613 for (
unsigned int i = 0; i < nMedia; ++i) {
614 const std::string name = m_media[i] ? m_media[i]->GetName() :
"none";
615 std::cout <<
" " << i <<
" " << name <<
"\n";
622 std::cerr <<
m_className <<
"::SetMedium:\n Null pointer.\n";
623 if (m_media.empty())
return;
625 if (i >= m_media.size()) m_media.resize(i + 1, NULL);
631 if (i > m_media.size()) {
632 std::cerr <<
m_className <<
"::GetMedium:\n Index out of range.\n";
639 const double zi,
unsigned int& i,
640 unsigned int& j,
unsigned int& k,
641 bool& xMirrored,
bool& yMirrored,
642 bool& zMirrored)
const {
645 std::cerr <<
m_className <<
"::GetElement:\n Mesh is not set.\n";
651 const double x = Reduce(xi, m_xMin, m_xMax,
m_xPeriodic,
653 if (x < m_xMin || x > m_xMax)
return false;
654 const double y = Reduce(yi, m_yMin, m_yMax,
m_yPeriodic,
656 if (y < m_yMin || y > m_yMax)
return false;
657 const double z = Reduce(zi, m_zMin, m_zMax,
m_zPeriodic,
659 if (z < m_zMin || z > m_zMax)
return false;
662 const double dx = (m_xMax - m_xMin) / m_nX;
663 const double dy = (m_yMax - m_yMin) / m_nY;
664 const double dz = (m_zMax - m_zMin) / m_nZ;
665 i = (
unsigned int)((x - m_xMin) / dx);
666 j = (
unsigned int)((y - m_yMin) / dy);
667 k = (
unsigned int)((z - m_zMin) / dz);
668 if (i >= m_nX) i = m_nX - 1;
669 if (j >= m_nY) j = m_nY - 1;
670 if (k >= m_nZ) k = m_nZ - 1;
675 const unsigned int k,
double& v,
double& ex,
676 double& ey,
double& ez)
const {
678 v = ex = ey = ez = 0.;
681 std::cerr <<
m_className <<
"::GetElement:\n Mesh not set.\n";
684 std::cerr <<
m_className <<
"::GetElement:\n Field map not set.\n";
687 if (i >= m_nX || j >= m_nY || k >= m_nZ) {
688 std::cerr <<
m_className <<
"::GetElement:\n Index out of range.\n";
691 const Element& element = m_efields[i][j][k];
699void ComponentVoxel::Reset() {
704 m_nX = m_nY = m_nZ = 0;
705 m_xMin = m_yMin = m_zMin = 0.;
706 m_xMax = m_yMax = m_zMax = 0.;
707 m_pMin = m_pMax = 0.;
711 m_hasPotential =
false;
717void ComponentVoxel::UpdatePeriodicity() {
720 std::cerr <<
m_className <<
"::UpdatePeriodicity:\n";
721 std::cerr <<
" Field map not available.\n";
727 std::cerr <<
m_className <<
"::UpdatePeriodicity:\n";
728 std::cerr <<
" Both simple and mirror periodicity\n";
729 std::cerr <<
" along x requested; reset.\n";
734 std::cerr <<
m_className <<
"::UpdatePeriodicity:\n";
735 std::cerr <<
" Both simple and mirror periodicity\n";
736 std::cerr <<
" along y requested; reset.\n";
741 std::cerr <<
m_className <<
"::UpdatePeriodicity:\n";
742 std::cerr <<
" Both simple and mirror periodicity\n";
743 std::cerr <<
" along z requested; reset.\n";
748 std::cerr <<
m_className <<
"::UpdatePeriodicity:\n";
749 std::cerr <<
" Axial symmetry is not supported; reset.\n";
754 std::cerr <<
m_className <<
"::UpdatePeriodicity:\n";
755 std::cerr <<
" Rotation symmetry is not supported; reset.\n";
760double ComponentVoxel::Reduce(
const double xin,
761 const double xmin,
const double xmax,
762 const bool simplePeriodic,
763 const bool mirrorPeriodic,
bool& mirrored)
const {
767 const double lx = xmax - xmin;
768 if (simplePeriodic) {
769 x = xmin + fmod(x - xmin, lx);
770 if (x < xmin) x += lx;
771 }
else if (mirrorPeriodic) {
772 double xNew = xmin + fmod(x - xmin, lx);
773 if (xNew < xmin) xNew += lx;
774 const int nx = int(floor(0.5 + (xNew - x) / lx));
775 if (nx != 2 * (nx / 2)) {
776 xNew = xmin + xmax - xNew;
Abstract base class for components.
bool m_zMirrorPeriodic
Mirror periodicity in z.
bool m_yAxiallyPeriodic
Axial periodicity in y.
virtual void MagneticField(const double x, const double y, const double z, double &bx, double &by, double &bz, int &status)
bool m_zRotationSymmetry
Rotation symmetry around z-axis.
bool m_yRotationSymmetry
Rotation symmetry around y-axis.
bool m_ready
Ready for use?
bool m_zAxiallyPeriodic
Axial periodicity in z.
bool m_xRotationSymmetry
Rotation symmetry around x-axis.
bool m_yPeriodic
Simple periodicity in y.
bool m_yMirrorPeriodic
Mirror periodicity in y.
bool m_xPeriodic
Simple periodicity in x.
bool m_zPeriodic
Simple periodicity in z.
std::string m_className
Class name.
bool m_xAxiallyPeriodic
Axial periodicity in x.
bool m_xMirrorPeriodic
Mirror periodicity in x.
ComponentVoxel()
Constructor.
void WeightingField(const double x, const double y, const double z, double &wx, double &wy, double &wz, const std::string &label)
void SetWeightingFieldOffset(const double x, const double y, const double z)
bool GetBoundingBox(double &xmin, double &ymin, double &zmin, double &xmax, double &ymax, double &zmax)
Get the bounding box coordinates.
void PrintRegions() const
Print all regions.
bool GetElectricFieldRange(double &exmin, double &exmax, double &eymin, double &eymax, double &ezmin, double &ezmax)
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)
Calculate the voltage range [V].
void SetMedium(const unsigned int i, Medium *m)
Set the medium in region i.
Medium * GetMedium(const double x, const double y, const double z)
Get the medium at a given location (x, y, z).
void ElectricField(const double x, const double y, const double z, double &ex, double &ey, double &ez, double &v, Medium *&m, int &status)
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)
void MagneticField(const double x, const double y, const double z, double &bx, double &by, double &bz, int &status)
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.
Abstract base class for media.