16bool ReadHeader(FILE* f,
const int fileSize,
const bool debug,
17 int& nX,
int& nY,
int& nZ,
int& nNS,
18 int& nES,
int& nEM,
int& nMaterials) {
22 static constexpr int headerSize = 1000;
23 if (fileSize < headerSize) {
24 std::cerr <<
"ComponentCST::ReadHeader:\n"
25 <<
" Error. The file is extremely short and does not seem to "
26 <<
"contain a header or data." << std::endl;
29 char header[headerSize];
30 size_t result = fread(header,
sizeof(
char), headerSize, f);
31 if (result != headerSize) {
32 std::cerr <<
"ComponentCST::ReadHeader: Could not read the header.\n";
36 int nMeshX = 0, nMeshY = 0, nMeshZ = 0;
37 int nNx = 0, nNy = 0, nNz = 0;
38 int nEx = 0, nEy = 0, nEz = 0;
40 std::string fmt =
"mesh_nx=%d mesh_ny=%d mesh_nz=%d\n";
41 fmt +=
"mesh_xlines=%d mesh_ylines=%d mesh_zlines=%d\n";
42 fmt +=
"nodes_scalar=%d ";
43 fmt +=
"nodes_vector_x=%d nodes_vector_y=%d nodes_vector_z=%d\n";
44 fmt +=
"elements_scalar=%d elements_vector_x=%d ";
45 fmt +=
"elements_vector_y=%d elements_vector_z=%d\n";
46 fmt +=
"elements_material=%d\n";
47 fmt +=
"n_materials=%d\n";
48 int filled = std::sscanf(header, fmt.c_str(),
49 &nMeshX, &nMeshY, &nMeshZ, &nX, &nY, &nZ,
50 &nNS, &nNx, &nNy, &nNz, &nES, &nEx, &nEy, &nEz, &nEM, &nMaterials);
52 std::cerr <<
"ComponentCST::ReadHeader: File header is broken.\n";
55 if (fileSize < 1000 + (nX + nY + nZ) * 8 +
56 (nNS + nNx + nNy + nNz + nES + nEx + nEy + nEz) * 4 +
57 nEM * 1 + nMaterials * 20) {
58 std::cerr <<
"ComponentCST::ReadHeader: Unexpected file size.\n";
62 std::cout <<
"ComponentCST::ReadHeader:\n"
63 <<
" Mesh (nx): " << nMeshX <<
"\t Mesh (ny): " << nMeshY
64 <<
"\t Mesh (nz): " << nMeshZ << std::endl
65 <<
" Mesh (x_lines): " << nX <<
"\t Mesh (y_lines): " << nY
66 <<
"\t Mesh (z_lines): " << nZ << std::endl
67 <<
" Nodes (scalar): " << nNS <<
"\t Nodes (x): " << nNx
68 <<
"\t Nodes (y): " << nNy <<
"\t Nodes (z): " << nNz <<
"\n"
69 <<
" Field (scalar): " << nES <<
"\t Field (x): " << nEx
70 <<
"\t Field (y): " << nEy <<
"\t Field (z): " << nEz <<
"\n"
71 <<
" Elements: " << nEM <<
"\t Materials: " << nMaterials
88 std::string mplist, std::string prnsol,
98 std::ifstream fmplist(mplist);
106 bool readerror =
false;
107 while (fmplist.getline(line, size,
'\n')) {
110 char* token = strtok(line,
" ");
112 if (!token || strcmp(token,
" ") == 0 || strcmp(token,
"\n") == 0 ||
113 int(token[0]) == 10 ||
int(token[0]) == 13)
117 if (strcmp(token,
"Materials") == 0) {
118 token = strtok(
nullptr,
" ");
119 const int nMaterials =
ReadInteger(token, -1, readerror);
122 <<
" Error reading file " << mplist <<
" (line " << il
123 <<
")." << std::endl;
131 material.medium =
nullptr;
134 std::cout <<
m_className <<
"::Initialise:" << std::endl;
135 std::cout <<
" Number of materials: " << nMaterials <<
"\n";
137 }
else if (strcmp(token,
"Material") == 0) {
138 token = strtok(
nullptr,
" ");
141 std::cerr <<
m_className <<
"::Initialise:" << std::endl;
142 std::cerr <<
" Error reading file " << mplist <<
" (line " << il
146 }
else if (imat < 1 || imat > (
int)
m_materials.size()) {
148 <<
" Found out-of-range material index " << imat <<
"in\n"
149 <<
" material properties file " << mplist <<
".\n";
152 token = strtok(
nullptr,
" ");
154 if (strcmp(token,
"PERX") == 0) {
156 }
else if (strcmp(token,
"RSVX") == 0) {
160 <<
" Unknown material property flag " << token <<
"\n"
161 <<
" in material properties file " << mplist
162 <<
" (line " << il <<
").\n";
165 token = strtok(
nullptr,
" ");
168 }
else if (itype == 2) {
170 token = strtok(
nullptr,
" ");
171 if (strcmp(token,
"PERX") != 0) {
173 <<
" Unknown material property flag " << token <<
"\n"
174 <<
" in material file " << mplist <<
" (material "
178 token = strtok(
nullptr,
" ");
184 <<
" Error reading file " << mplist
185 <<
" (line " << il <<
")." << std::endl;
190 std::cout <<
m_className <<
"::Initialise:" << std::endl;
191 std::cout <<
" Read material properties for material "
192 << (imat - 1) <<
"" << std::endl;
194 std::cout <<
" eps = " <<
m_materials[imat - 1].eps
198 std::cout <<
" eps = " <<
m_materials[imat - 1].eps <<
""
213 <<
" Read properties of " <<
m_materials.size() <<
" materials\n"
214 <<
" from file " << mplist <<
"." << std::endl;
221 <<
" Unknown length unit " << unit <<
".\n";
226 std::cout <<
m_className <<
"::Initialise: Unit scaling factor = "
231 std::ifstream fnlist(nlist);
239 int xlines = 0, ylines = 0, zlines = 0;
242 while (fnlist.getline(line, size,
'\n')) {
245 char* token = strtok(line,
" ");
247 if (!token || strcmp(token,
" ") == 0 || strcmp(token,
"\n") == 0 ||
248 int(token[0]) == 10 ||
int(token[0]) == 13)
251 if (strcmp(token,
"xmax") == 0) {
252 token = strtok(
nullptr,
" ");
254 token = strtok(
nullptr,
" ");
255 token = strtok(
nullptr,
" ");
257 token = strtok(
nullptr,
" ");
258 token = strtok(
nullptr,
" ");
260 if (readerror)
break;
263 if (strcmp(token,
"x-lines\n") == 0 || strcmp(token,
"x-lines") == 0) {
267 <<
" Reading x-lines from file " << nlist <<
".\n";
271 if (strcmp(token,
"y-lines\n") == 0 || strcmp(token,
"y-lines") == 0) {
275 <<
" Reading y-lines from file " << nlist <<
".\n";
279 if (strcmp(token,
"z-lines\n") == 0 || strcmp(token,
"z-lines") == 0) {
283 <<
" Reading z-lines from file " << nlist <<
".\n";
289 m_xlines.push_back(line_tmp * funit);
290 else if (lines_type == 2)
291 m_ylines.push_back(line_tmp * funit);
292 else if (lines_type == 3)
293 m_zlines.push_back(line_tmp * funit);
295 std::cerr <<
m_className <<
"::Initialise:" << std::endl;
296 std::cerr <<
" Line type was not set in " << nlist <<
" (line " << il
297 <<
", token = " << token <<
")." << std::endl;
298 std::cerr <<
" Maybe it is in the wrong format" << std::endl;
299 std::cerr <<
" e.g. missing tailing space after x-lines." << std::endl;
303 if (readerror)
break;
308 <<
" Error reading file " << nlist
309 <<
" (line " << il <<
").\n";
316 if ((
unsigned)xlines == m_xlines.size() &&
317 (
unsigned)ylines == m_ylines.size() &&
318 (
unsigned)zlines == m_zlines.size()) {
319 std::cout <<
m_className <<
"::Initialise:" << std::endl;
320 std::cout <<
" Found in file " << nlist <<
"\n " << xlines
321 <<
" x-lines\n " << ylines <<
" y-lines\n " << zlines
322 <<
" z-lines" << std::endl;
324 std::cerr <<
m_className <<
"::Initialise:" << std::endl;
325 std::cerr <<
" There should be " << xlines <<
" x-lines, " << ylines
326 <<
" y-lines and " << zlines <<
" z-lines in file " << nlist
327 <<
" but I found :\n " << m_xlines.size() <<
" x-lines, "
328 << m_ylines.size() <<
" x-lines, " << m_zlines.size()
329 <<
" z-lines." << std::endl;
331 m_nx = m_xlines.size();
332 m_ny = m_ylines.size();
333 m_nz = m_zlines.size();
334 m_nNodes = m_nx * m_ny * m_nz;
335 m_nElements = (m_nx - 1) * (m_ny - 1) * (m_nz - 1);
338 std::cout <<
m_className <<
"::Initialise:" << std::endl;
339 std::cout <<
" Read " << m_nNodes <<
" nodes from file " << nlist <<
"."
343 std::ifstream felist(elist);
349 m_elementMaterial.resize(m_nElements);
351 while (felist.getline(line, size,
'\n')) {
354 char* token = strtok(line,
" ");
356 if (!token || strcmp(token,
" ") == 0 || strcmp(token,
"\n") == 0 ||
357 int(token[0]) == 10 ||
int(token[0]) == 13 ||
358 strcmp(token,
"LIST") == 0 || strcmp(token,
"ELEM") == 0)
362 token = strtok(
nullptr,
" ");
363 if (!token)
continue;
364 unsigned char imat = atoi(token);
366 std::vector<int> node_nb;
370 m_elementMaterial.at(ielem) = (imat - 1);
372 std::cerr <<
m_className <<
"::Initialise:" << std::endl;
373 std::cerr <<
" Error reading file " << elist <<
" (line " << il <<
")."
375 std::cerr <<
" The element index (" << ielem
376 <<
") is not in the expected range: 0 - " << m_nElements
383 std::cerr <<
m_className <<
"::Initialise:" << std::endl;
384 std::cerr <<
" Out-of-range material number on file " << elist
385 <<
" (line " << il <<
")." << std::endl;
386 std::cerr <<
" Element: " << ielem <<
", material: " << imat
391 std::cerr <<
m_className <<
"::Initialise:" << std::endl;
392 std::cerr <<
" Element " << ielem <<
" in element list " << elist
393 <<
" uses material " << imat <<
" which" << std::endl;
394 std::cerr <<
" has not been assigned a positive permittivity"
396 std::cerr <<
" in material list " << mplist <<
"." << std::endl;
403 std::cout <<
m_className <<
"::Initialise:" << std::endl;
404 std::cout <<
" Read " << m_nElements <<
" elements.\n";
407 m_potential.resize(m_nNodes);
408 std::ifstream fprnsol(prnsol);
417 while (fprnsol.getline(line, size,
'\n')) {
420 char* token = strtok(line,
" ");
422 if (!token || strcmp(token,
" ") == 0 || strcmp(token,
"\n") == 0 ||
423 int(token[0]) == 10 ||
int(token[0]) == 13 || strcmp(token,
"Max") == 0)
428 token = strtok(
nullptr,
" ");
429 double volt =
ReadDouble(token, -1, readerror);
432 m_potential.at(inode - 1) = volt;
435 std::cerr <<
m_className <<
"::Initialise:" << std::endl;
436 std::cerr <<
" Error reading file " << prnsol <<
" (line " << il
437 <<
")." << std::endl;
438 std::cerr <<
" The node index (" << inode - 1
439 <<
") is not in the expected range: 0 - " << m_nNodes
447 std::cout <<
m_className <<
"::Initialise:" << std::endl;
448 std::cout <<
" Read " << nread <<
"/" << m_nNodes
449 <<
" (expected) potentials from file " << prnsol <<
"."
452 if (nread != (
int)m_nNodes) {
453 std::cerr <<
m_className <<
"::Initialise:" << std::endl;
454 std::cerr <<
" Number of nodes read (" << nread <<
") on potential file "
455 << prnsol <<
" does not" << std::endl;
456 std::cerr <<
" match the node list (" << m_nNodes <<
").\n";
463 std::cerr <<
m_className <<
"::Initialise:" << std::endl;
464 std::cerr <<
" Field map could not be read and cannot be interpolated."
481 <<
" Unknown length unit " << unit <<
".\n";
486 std::cout <<
m_className <<
"::Initialise: Unit scaling factor = "
489 FILE* f = fopen(dataFile.c_str(),
"rb");
495 struct stat fileStatus;
496 stat(dataFile.c_str(), &fileStatus);
497 int fileSize = fileStatus.st_size;
499 int nLinesX = 0, nLinesY = 0, nLinesZ = 0;
500 int nNS = 0, nES = 0, nEM = 0;
502 if (!ReadHeader(f, fileSize,
m_debug, nLinesX, nLinesY, nLinesZ,
503 nNS, nES, nEM, nMaterials)) {
510 m_nNodes = m_nx * m_ny * m_nz;
511 m_nElements = (m_nx - 1) * (m_ny - 1) * (m_nz - 1);
513 m_xlines.resize(nLinesX);
514 m_ylines.resize(nLinesY);
515 m_zlines.resize(nLinesZ);
516 m_potential.resize(nNS);
517 m_elementMaterial.resize(nEM);
519 auto result = fread(m_xlines.data(),
sizeof(
double), m_xlines.size(), f);
520 if (result != m_xlines.size()) {
521 fputs(
"Reading error while reading xlines.", stderr);
523 }
else if (result == 0) {
524 fputs(
"No xlines are stored in the data file.", stderr);
527 result = fread(m_ylines.data(),
sizeof(
double), m_ylines.size(), f);
528 if (result != m_ylines.size()) {
529 fputs(
"Reading error while reading ylines", stderr);
531 }
else if (result == 0) {
532 fputs(
"No ylines are stored in the data file.", stderr);
535 result = fread(m_zlines.data(),
sizeof(
double), m_zlines.size(), f);
536 if (result != m_zlines.size()) {
537 fputs(
"Reading error while reading zlines", stderr);
539 }
else if (result == 0) {
540 fputs(
"No zlines are stored in the data file.", stderr);
543 result = fread(m_potential.data(),
sizeof(
float), m_potential.size(), f);
544 if (result != m_potential.size()) {
545 fputs(
"Reading error while reading nodes.", stderr);
547 }
else if (result == 0) {
548 fputs(
"No potentials are stored in the data file.", stderr);
551 fseek(f, nES *
sizeof(
float), SEEK_CUR);
553 result = fread(m_elementMaterial.data(),
sizeof(
unsigned char),
554 m_elementMaterial.size(), f);
555 if (result != m_elementMaterial.size()) {
556 fputs(
"Reading error while reading element material", stderr);
559 std::stringstream st;
565 for (
unsigned int i = 0; i <
m_materials.size(); i++) {
567 result = fread(&(
id),
sizeof(
float), 1, f);
569 fputs(
"Input error while reading material id.", stderr);
573 const unsigned int index = i;
574 unsigned int description_size = 0;
575 result = fread(&(description_size),
sizeof(
int), 1, f);
577 fputs(
"Input error while reading material description size.", stderr);
580 char* c =
new char[description_size];
581 result = fread(c,
sizeof(
char), description_size, f);
582 if (result != description_size) {
583 fputs(
"Input error while reading material description.", stderr);
586 std::string name = c;
587 st <<
" Read material: " << name;
588 if (name.compare(
"gas") == 0) {
589 st <<
" (considered as drift medium)";
596 result = fread(&(eps),
sizeof(
float), 1, f);
599 fputs(
"Reading error while reading eps.", stderr);
617 st <<
"\t id is: " <<
id << std::endl;
619 fseek(f, 2 *
sizeof(
float), SEEK_CUR);
623 std::sort(m_xlines.begin(), m_xlines.end());
624 std::sort(m_ylines.begin(), m_ylines.end());
625 std::sort(m_zlines.begin(), m_zlines.end());
627 std::transform(m_xlines.begin(), m_xlines.end(), m_xlines.begin(), [funit](
double x) { return x * funit;});
628 std::transform(m_ylines.begin(), m_ylines.end(), m_ylines.begin(), [funit](
double x) { return x * funit;});
629 std::transform(m_zlines.begin(), m_zlines.end(), m_zlines.begin(), [funit](
double x) { return x * funit;});
632 std::cout <<
m_className <<
"::Initialise" << std::endl;
633 std::cout <<
" x range: " << *(m_xlines.begin()) <<
" - "
634 << *(m_xlines.end() - 1) << std::endl;
635 std::cout <<
" y range: " << *(m_ylines.begin()) <<
" - "
636 << *(m_ylines.end() - 1) << std::endl;
637 std::cout <<
" z range: " << *(m_zlines.begin()) <<
" - "
638 << *(m_zlines.end() - 1) << std::endl;
644 std::cerr <<
m_className <<
"::Initialise:" << std::endl;
645 std::cerr <<
" Field map could not be read and cannot be interpolated."
657 std::vector<float> potentials(m_nNodes);
659 std::cerr <<
m_className <<
"::SetWeightingField:" << std::endl;
660 std::cerr <<
" No valid field map is present." << std::endl;
661 std::cerr <<
" Weighting field cannot be added." << std::endl;
666 std::ifstream fprnsol(prnsol);
672 auto it = m_weightingFields.find(label);
673 if (it != m_weightingFields.end()) {
674 std::cout <<
m_className <<
"::SetWeightingField:" << std::endl;
675 std::cout <<
" Replacing existing weighting field " << label <<
"."
683 std::cout <<
m_className <<
"::SetWeightingField:" << std::endl;
684 std::cout <<
" Reading weighting field from binary file:"
685 << prnsol << std::endl;
686 FILE* f = fopen(prnsol.c_str(),
"rb");
692 struct stat fileStatus;
693 stat(prnsol.c_str(), &fileStatus);
694 int fileSize = fileStatus.st_size;
696 int nLinesX = 0, nLinesY = 0, nLinesZ = 0;
697 int nES = 0, nEM = 0;
699 if (!ReadHeader(f, fileSize,
m_debug, nLinesX, nLinesY, nLinesZ,
700 nread, nES, nEM, nMaterials)) {
705 fseek(f, nLinesX *
sizeof(
double), SEEK_CUR);
706 fseek(f, nLinesY *
sizeof(
double), SEEK_CUR);
707 fseek(f, nLinesZ *
sizeof(
double), SEEK_CUR);
708 auto result = fread(potentials.data(),
sizeof(
float), potentials.size(), f);
709 if (result != potentials.size()) {
710 fputs(
"Reading error while reading nodes.", stderr);
712 }
else if (result == 0) {
713 fputs(
"No weighting potentials are stored in the data file.", stderr);
718 std::cout <<
m_className <<
"::SetWeightingField:" << std::endl;
719 std::cout <<
" Reading weighting field from text file:" << prnsol
722 const int size = 100;
728 bool readerror =
false;
729 while (fprnsol.getline(line, size,
'\n')) {
732 char* token = strtok(line,
" ");
734 if (!token || strcmp(token,
" ") == 0 || strcmp(token,
"\n") == 0 ||
735 int(token[0]) == 10 ||
int(token[0]) == 13 ||
736 strcmp(token,
"PRINT") == 0 || strcmp(token,
"*****") == 0 ||
737 strcmp(token,
"LOAD") == 0 || strcmp(token,
"TIME=") == 0 ||
738 strcmp(token,
"MAXIMUM") == 0 || strcmp(token,
"VALUE") == 0 ||
739 strcmp(token,
"NODE") == 0)
743 token = strtok(
nullptr,
" ");
744 double volt =
ReadDouble(token, -1, readerror);
746 potentials.at(inode - 1) = volt;
749 std::cerr <<
m_className <<
"::SetWeightingField:" << std::endl;
750 std::cerr <<
" Node number " << inode <<
" out of range."
752 std::cerr <<
" on potential file " << prnsol <<
" (line " << il
753 <<
")." << std::endl;
754 std::cerr <<
" Size of the potential vector is: "
755 << potentials.size() << std::endl;
763 std::cout <<
m_className <<
"::SetWeightingField:" << std::endl;
764 std::cout <<
" Read " << nread <<
"/" << m_nNodes
765 <<
" (expected) potentials from file " << prnsol <<
"."
768 if (nread != (
int)m_nNodes) {
769 std::cerr <<
m_className <<
"::SetWeightingField:" << std::endl;
770 std::cerr <<
" Number of nodes read (" << nread <<
")"
771 <<
" on potential file (" << prnsol <<
")" << std::endl;
772 std::cerr <<
" does not match the node list (" << m_nNodes <<
")."
777 std::cerr <<
m_className <<
"::SetWeightingField:" << std::endl;
778 std::cerr <<
" Field map could not be read "
779 <<
"and cannot be interpolated." << std::endl;
783 m_weightingFields[label] = potentials;
788 const double zShift) {
789 std::transform(m_xlines.begin(), m_xlines.end(), m_xlines.begin(), [xShift](
double x) { return x + xShift;});
790 std::transform(m_ylines.begin(), m_ylines.end(), m_ylines.begin(), [yShift](
double x) { return x + yShift;});
791 std::transform(m_zlines.begin(), m_zlines.end(), m_zlines.begin(), [zShift](
double x) { return x + zShift;});
795 std::cout <<
m_className <<
"::ShiftComponent:" << std::endl;
796 std::cout <<
" Shifted component in x-direction: " << xShift
797 <<
"\t y-direction: " << yShift <<
"\t z-direction: " << zShift
802 const double zin,
double& ex,
double& ey,
803 double& ez,
Medium*& m,
int& status) {
805 ElectricFieldBinary(xin, yin, zin, ex, ey, ez, volt, m, status);
809 const double zin,
double& ex,
double& ey,
810 double& ez,
double& volt,
Medium*& m,
812 ElectricFieldBinary(xin, yin, zin, ex, ey, ez, volt, m, status,
true);
816 const double zin,
double& wx,
double& wy,
817 double& wz,
const std::string& label) {
825 auto it = m_weightingFields.find(label);
826 if (it == m_weightingFields.end()) {
828 std::cerr <<
"No weighting field named " << label <<
" found!\n";
833 if (m_weightingFields[label].empty())
return;
836 double x = xin, y = yin, z = zin;
840 unsigned int i, j, k;
841 double pos[3] = {0., 0., 0.};
846 double rx = (pos[0] - m_xlines.at(i)) / (m_xlines.at(i + 1) - m_xlines.at(i));
847 double ry = (pos[1] - m_ylines.at(j)) / (m_ylines.at(j + 1) - m_ylines.at(j));
848 double rz = (pos[2] - m_zlines.at(k)) / (m_zlines.at(k + 1) - m_zlines.at(k));
850 float fwx = 0., fwy = 0., fwz = 0.;
851 if (!disableFieldComponent[0])
852 fwx = GetFieldComponent(i, j, k, rx, ry, rz,
'x', (*it).second);
853 if (!disableFieldComponent[1])
854 fwy = GetFieldComponent(i, j, k, rx, ry, rz,
'y', (*it).second);
855 if (!disableFieldComponent[2])
856 fwz = GetFieldComponent(i, j, k, rx, ry, rz,
'z', (*it).second);
858 if (m_elementMaterial.size() > 0 && doShaping) {
859 ShapeField(fwx, fwy, fwz, rx, ry, rz, i, j, k, (*it).second);
861 if (mirrored[0]) fwx *= -1.f;
862 if (mirrored[1]) fwy *= -1.f;
863 if (mirrored[2]) fwz *= -1.f;
866 if (!disableFieldComponent[0]) wx = fwx;
867 if (!disableFieldComponent[1]) wy = fwy;
868 if (!disableFieldComponent[2]) wz = fwz;
874 const std::string& label) {
879 auto it = m_weightingFields.find(label);
880 if (it == m_weightingFields.end()) {
882 std::cerr <<
"No weighting field named " << label <<
" found!\n";
887 if (m_weightingFields[label].empty())
return 0.;
890 double x = xin, y = yin, z = zin;
894 unsigned int i, j, k;
895 double pos[3] = {0., 0., 0.};
899 double rx = (pos[0] - m_xlines.at(i)) /
900 (m_xlines.at(i + 1) - m_xlines.at(i));
901 double ry = (pos[1] - m_ylines.at(j)) /
902 (m_ylines.at(j + 1) - m_ylines.at(j));
903 double rz = (pos[2] - m_zlines.at(k)) /
904 (m_zlines.at(k + 1) - m_zlines.at(k));
906 double potential =
GetPotential(i, j, k, rx, ry, rz, (*it).second);
909 std::cout <<
m_className <<
"::WeightingPotential:" << std::endl;
910 std::cout <<
" Global: (" << x <<
"," << y <<
"," << z <<
"),"
912 std::cout <<
" Local: (" << rx <<
"," << ry <<
"," << rz
913 <<
") in element with indexes: i=" << i <<
", j=" << j
914 <<
", k=" << k << std::endl;
915 std::cout <<
" Node xyzV:" << std::endl;
916 std::cout <<
"Node 0 position: " << Index2Node(i + 1, j, k)
917 <<
"\t potential: " << ((*it).second).at(Index2Node(i + 1, j, k))
918 <<
"Node 1 position: " << Index2Node(i + 1, j + 1, k)
920 << ((*it).second).at(Index2Node(i + 1, j + 1, k))
921 <<
"Node 2 position: " << Index2Node(i, j + 1, k)
922 <<
"\t potential: " << ((*it).second).at(Index2Node(i, j + 1, k))
923 <<
"Node 3 position: " << Index2Node(i, j, k)
924 <<
"\t potential: " << ((*it).second).at(Index2Node(i, j, k))
925 <<
"Node 4 position: " << Index2Node(i + 1, j, k + 1)
927 << ((*it).second).at(Index2Node(i + 1, j, k + 1))
928 <<
"Node 5 position: " << Index2Node(i + 1, j + 1, k + 1)
930 << ((*it).second).at(Index2Node(i + 1, j + 1, k + 1))
931 <<
"Node 6 position: " << Index2Node(i, j + 1, k + 1)
933 << ((*it).second).at(Index2Node(i, j + 1, k + 1))
934 <<
"Node 7 position: " << Index2Node(i, j, k + 1)
935 <<
"\t potential: " << ((*it).second).at(Index2Node(i, j, k))
942 unsigned int& n_z)
const {
943 n_x = m_xlines.size();
944 n_y = m_ylines.size();
945 n_z = m_zlines.size();
949 std::vector<size_t>& nodes)
const {
950 if (element >= m_nElements || element >= m_elementMaterial.size()) {
951 std::cerr <<
m_className <<
"::GetElement: Index out of range.\n";
954 mat = m_elementMaterial[element];
957 unsigned int i0 = 0, j0 = 0, k0 = 0;
958 Element2Index(element, i0, j0, k0);
959 const auto i1 = i0 + 1;
960 const auto j1 = j0 + 1;
961 const auto k1 = k0 + 1;
962 nodes.push_back(Index2Node(i0, j0, k0));
963 nodes.push_back(Index2Node(i1, j0, k0));
964 nodes.push_back(Index2Node(i0, j1, k0));
965 nodes.push_back(Index2Node(i1, j1, k0));
966 nodes.push_back(Index2Node(i0, j0, k1));
967 nodes.push_back(Index2Node(i1, j0, k1));
968 nodes.push_back(Index2Node(i0, j1, k1));
969 nodes.push_back(Index2Node(i1, j1, k1));
974 double& x,
double& y,
double& z)
const {
975 if (node >= m_nNodes) {
976 std::cerr <<
m_className <<
"::GetNode: Index out of range.\n";
979 unsigned int i = 0, j = 0, k = 0;
980 Node2Index(node, i, j, k);
988 double& xmax,
double& ymin,
989 double& ymax,
double& zmin,
990 double& zmax)
const {
991 unsigned int i, j, k;
992 Element2Index(element, i, j, k);
993 xmin = m_xlines.at(i);
994 xmax = m_xlines.at(i + 1);
995 ymin = m_ylines.at(j);
996 ymax = m_ylines.at(j + 1);
997 zmin = m_zlines.at(k);
998 zmax = m_zlines.at(k + 1);
1003 unsigned int i, j, k;
1007 <<
" Position (" << x <<
", " << y <<
", " << z <<
"):\n"
1008 <<
" Indices are: x: " << i <<
"/" << m_xlines.size()
1009 <<
"\t y: " << j <<
"/" << m_ylines.size()
1010 <<
"\t z: " << k <<
"/" << m_zlines.size() << std::endl;
1012 std::cout <<
" Element index: " << element << std::endl
1013 <<
" Material index: "
1014 << (int)m_elementMaterial.at(element) << std::endl;
1027 m_mapvmin = *std::min_element(m_potential.begin(), m_potential.end());
1028 m_mapvmax = *std::max_element(m_potential.begin(), m_potential.end());
1046 if (fabs(zmax - zmin) <= 0.) {
1047 std::cerr <<
m_className <<
"::SetRangeZ:" << std::endl;
1048 std::cerr <<
" Zero range is not permitted." << std::endl;
1056 const double z,
unsigned int& i,
1057 unsigned int& j,
unsigned int& k)
const {
1058 bool mirrored[3] = {
false,
false,
false};
1059 double pos[3] = {0., 0., 0.};
1065 const double zin,
unsigned int& i,
1066 unsigned int& j,
unsigned int& k,
1067 double* pos,
bool* mirrored)
const {
1072 double rcoordinate = 0.;
1073 double rotation = 0.;
1075 mirrored[0], mirrored[1], mirrored[2], rcoordinate, rotation);
1078 std::lower_bound(m_xlines.begin(), m_xlines.end(), pos[0]);
1080 std::lower_bound(m_ylines.begin(), m_ylines.end(), pos[1]);
1082 std::lower_bound(m_zlines.begin(), m_zlines.end(), pos[2]);
1083 if (it_x == m_xlines.end() || it_y == m_ylines.end() ||
1084 it_z == m_zlines.end() || pos[0] < m_xlines.at(0) ||
1085 pos[1] < m_ylines.at(0) ||
1086 pos[2] < m_zlines.at(0)) {
1088 std::cerr <<
m_className <<
"::ElectricFieldBinary:" << std::endl;
1089 std::cerr <<
" Could not find the given coordinate!" << std::endl;
1090 std::cerr <<
" You ask for the following position: " << xin <<
", "
1091 << yin <<
", " << zin << std::endl;
1092 std::cerr <<
" The mapped position is: " << pos[0] <<
", "
1093 << pos[1] <<
", " << pos[2]
1104 if (it_x == m_xlines.begin())
1107 i = std::distance(m_xlines.begin(), it_x - 1);
1108 if (it_y == m_ylines.begin())
1111 j = std::distance(m_ylines.begin(), it_y - 1);
1112 if (it_z == m_zlines.begin())
1115 k = std::distance(m_zlines.begin(), it_z - 1);
1120 const unsigned int k)
const {
1121 if (i > m_nx - 2 || j > m_ny - 2 || k > m_nz - 2) {
1122 throw "ComponentCST::Index2Element: Error. Element indices out of bounds.";
1124 return i + j * (m_nx - 1) + k * (m_nx - 1) * (m_ny - 1);
1128 double& dmax)
const {
1129 if (element >= m_nElements) {
1133 unsigned int i, j, k;
1134 Element2Index(element, i, j, k);
1135 const double dx = fabs(m_xlines.at(i + 1) - m_xlines.at(i));
1136 const double dy = fabs(m_ylines.at(j + 1) - m_ylines.at(j));
1137 const double dz = fabs(m_zlines.at(k + 1) - m_zlines.at(k));
1138 dmin = std::min({dx, dy, dz});
1139 dmax = std::max({dx, dy, dz});
1143 if (element >= m_nElements)
return 0.;
1144 unsigned int i, j, k;
1145 Element2Index(element, i, j, k);
1146 const double dx = fabs(m_xlines.at(i + 1) - m_xlines.at(i));
1147 const double dy = fabs(m_ylines.at(j + 1) - m_ylines.at(j));
1148 const double dz = fabs(m_zlines.at(k + 1) - m_zlines.at(k));
1149 return dx * dy * dz;
1152void ComponentCST::ElectricFieldBinary(
const double xin,
const double yin,
1153 const double zin,
double& ex,
double& ey,
1154 double& ez,
double& volt,
Medium*& m,
1155 int& status,
bool calculatePotential)
const {
1157 double x = xin, y = yin, z = zin;
1162 unsigned int i, j, k;
1163 double pos[3] = {0., 0., 0.};
1167 double rx = (pos[0] - m_xlines.at(i)) / (m_xlines.at(i + 1) - m_xlines.at(i));
1168 double ry = (pos[1] - m_ylines.at(j)) / (m_ylines.at(j + 1) - m_ylines.at(j));
1169 double rz = (pos[2] - m_zlines.at(k)) / (m_zlines.at(k + 1) - m_zlines.at(k));
1171 float fex = GetFieldComponent(i, j, k, rx, ry, rz,
'x', m_potential);
1172 float fey = GetFieldComponent(i, j, k, rx, ry, rz,
'y', m_potential);
1173 float fez = GetFieldComponent(i, j, k, rx, ry, rz,
'z', m_potential);
1175 if (m_elementMaterial.size() > 0 && doShaping) {
1176 ShapeField(fex, fey, fez, rx, ry, rz, i, j, k, m_potential);
1178 if (mirrored[0]) fex *= -1.f;
1179 if (mirrored[1]) fey *= -1.f;
1180 if (mirrored[2]) fez *= -1.f;
1182 std::cout <<
m_className <<
"::ElectricFieldBinary:" << std::endl;
1183 std::cout <<
" Found position (" <<
x <<
", " <<
y <<
", " <<
z
1184 <<
"): " << std::endl;
1185 std::cout <<
" Indices are: x: " << i <<
"/" << m_xlines.size()
1186 <<
"\t y: " << j <<
"/" << m_ylines.size() <<
"\t z: " << k <<
"/"
1187 << m_zlines.size() << std::endl;
1188 if (i != 0 && j != 0 && k != 0) {
1189 std::cout <<
" index: " << i <<
"\t x before: " << m_xlines.at(i - 1)
1190 <<
"\t x behind: " << m_xlines.at(i) <<
"\t r = " << rx
1191 <<
"\n index: " << j <<
"\t y before: " << m_ylines.at(j - 1)
1192 <<
"\t y behind: " << m_ylines.at(j) <<
"\t r = " << ry
1193 <<
"\n index: " << k <<
"\t z before: " << m_zlines.at(k - 1)
1194 <<
"\t z behind: " << m_zlines.at(k) <<
"\t r = " << rz
1197 std::cout <<
" Electric field is: " << fex <<
", " << fey <<
", " << fez
1198 <<
"): " << std::endl;
1202 const auto imat = m_elementMaterial.at(
Index2Element(i, j, k));
1211 if (!disableFieldComponent[0]) ex = fex;
1212 if (!disableFieldComponent[1]) ey = fey;
1213 if (!disableFieldComponent[2]) ez = fez;
1214 if (calculatePotential)
1218float ComponentCST::GetFieldComponent(
1219 const unsigned int i,
const unsigned int j,
const unsigned int k,
1220 const double rx,
const double ry,
const double rz,
1221 const char component,
const std::vector<float>& potentials)
const {
1223 if (component ==
'x') {
1224 const float dv1 = potentials.at(Index2Node(i + 1, j, k)) -
1225 potentials.at(Index2Node(i, j, k));
1226 const float dv2 = potentials.at(Index2Node(i + 1, j + 1, k)) -
1227 potentials.at(Index2Node(i, j + 1, k));
1228 const float dv3 = potentials.at(Index2Node(i + 1, j + 1, k + 1)) -
1229 potentials.at(Index2Node(i, j + 1, k + 1));
1230 const float dv4 = potentials.at(Index2Node(i + 1, j, k + 1)) -
1231 potentials.at(Index2Node(i, j, k + 1));
1233 const float dv11 = dv1 + (dv4 - dv1) * rz;
1234 const float dv21 = dv2 + (dv3 - dv2) * rz;
1235 const float dv = dv11 + (dv21 - dv11) * ry;
1236 e = -1 * dv / (m_xlines.at(i + 1) - m_xlines.at(i));
1238 if (component ==
'y') {
1239 const float dv1 = potentials.at(Index2Node(i, j + 1, k)) -
1240 potentials.at(Index2Node(i, j, k));
1241 const float dv2 = potentials.at(Index2Node(i, j + 1, k + 1)) -
1242 potentials.at(Index2Node(i, j, k + 1));
1243 const float dv3 = potentials.at(Index2Node(i + 1, j + 1, k + 1)) -
1244 potentials.at(Index2Node(i + 1, j, k + 1));
1245 const float dv4 = potentials.at(Index2Node(i + 1, j + 1, k)) -
1246 potentials.at(Index2Node(i + 1, j, k));
1248 const float dv11 = dv1 + (dv4 - dv1) * rx;
1249 const float dv21 = dv2 + (dv3 - dv2) * rx;
1250 const float dv = dv11 + (dv21 - dv11) * rz;
1251 e = -1 * dv / (m_ylines.at(j + 1) - m_ylines.at(j));
1253 if (component ==
'z') {
1254 const float dv1 = potentials.at(Index2Node(i, j, k + 1)) -
1255 potentials.at(Index2Node(i, j, k));
1256 const float dv2 = potentials.at(Index2Node(i + 1, j, k + 1)) -
1257 potentials.at(Index2Node(i + 1, j, k));
1258 const float dv3 = potentials.at(Index2Node(i + 1, j + 1, k + 1)) -
1259 potentials.at(Index2Node(i + 1, j + 1, k));
1260 const float dv4 = potentials.at(Index2Node(i, j + 1, k + 1)) -
1261 potentials.at(Index2Node(i, j + 1, k));
1263 const float dv11 = dv1 + (dv4 - dv1) * ry;
1264 const float dv21 = dv2 + (dv3 - dv2) * ry;
1265 const float dv = dv11 + (dv21 - dv11) * rx;
1266 e = -1 * dv / (m_zlines.at(k + 1) - m_zlines.at(k));
1271float ComponentCST::GetPotential(
1272 const unsigned int i,
const unsigned int j,
const unsigned int k,
1273 const double rx,
const double ry,
const double rz,
1274 const std::vector<float>& potentials)
const {
1275 double t1 = rx * 2. - 1;
1276 double t2 = ry * 2. - 1;
1277 double t3 = rz * 2. - 1;
1278 return (potentials.at(Index2Node(i + 1, j, k)) * (1 - t1) * (1 - t2) *
1280 potentials.at(Index2Node(i + 1, j + 1, k)) * (1 + t1) * (1 - t2) *
1282 potentials.at(Index2Node(i, j + 1, k)) * (1 + t1) * (1 + t2) *
1284 potentials.at(Index2Node(i, j, k)) * (1 - t1) * (1 + t2) * (1 - t3) +
1285 potentials.at(Index2Node(i + 1, j, k + 1)) * (1 - t1) * (1 - t2) *
1287 potentials.at(Index2Node(i + 1, j + 1, k + 1)) * (1 + t1) *
1288 (1 - t2) * (1 + t3) +
1289 potentials.at(Index2Node(i, j + 1, k + 1)) * (1 + t1) * (1 + t2) *
1291 potentials.at(Index2Node(i, j, k + 1)) * (1 - t1) * (1 + t2) *
1296void ComponentCST::ShapeField(
float& ex,
float& ey,
float& ez,
1297 const double rx,
const double ry,
const double rz,
1298 const unsigned int i,
const unsigned int j,
const unsigned int k,
1299 const std::vector<float>& potentials)
const {
1301 const auto m1 = m_elementMaterial.at(
Index2Element(i, j, k));
1302 const auto imax = m_xlines.size() - 2;
1303 if ((i == 0 && rx >= 0.5) || (i == imax && rx < 0.5) || (i > 0 && i < imax)) {
1305 const auto m2 = m_elementMaterial.at(
Index2Element(i + 1, j, k));
1308 GetFieldComponent(i + 1, j, k, 0.5, ry, rz,
'x', potentials);
1310 (rx - 0.5) * (ex_next - ex) *
1311 (m_xlines.at(i + 1) - m_xlines.at(i)) /
1312 (m_xlines.at(i + 2) - m_xlines.at(i + 1));
1315 const auto m2 = m_elementMaterial.at(
Index2Element(i - 1, j, k));
1318 GetFieldComponent(i - 1, j, k, 0.5, ry, rz,
'x', potentials);
1320 (rx + 0.5) * (ex - ex_before) *
1321 (m_xlines.at(i) - m_xlines.at(i - 1)) /
1322 (m_xlines.at(i + 1) - m_xlines.at(i));
1327 const auto jmax = m_ylines.size() - 2;
1328 if ((j == 0 && ry >= 0.5) || (j == jmax && ry < 0.5) || (j > 0 && j < jmax)) {
1330 const auto m2 = m_elementMaterial.at(
Index2Element(i, j + 1, k));
1333 GetFieldComponent(i, j + 1, k, rx, 0.5, rz,
'y', potentials);
1335 (ry - 0.5) * (ey_next - ey) *
1336 (m_ylines.at(j + 1) - m_ylines.at(j)) /
1337 (m_ylines.at(j + 2) - m_ylines.at(j + 1));
1340 const auto m2 = m_elementMaterial.at(
Index2Element(i, j - 1, k));
1343 GetFieldComponent(i, j - 1, k, rx, 0.5, rz,
'y', potentials);
1345 (ry + 0.5) * (ey - ey_next) *
1346 (m_ylines.at(j) - m_ylines.at(j - 1)) /
1347 (m_ylines.at(j + 1) - m_ylines.at(j));
1351 const auto kmax = m_zlines.size() - 2;
1352 if ((k == 0 && rz >= 0.5) || (k == kmax && rz < 0.5) || (k > 0 && k < kmax)) {
1354 const auto m2 = m_elementMaterial.at(
Index2Element(i, j, k + 1));
1357 GetFieldComponent(i, j, k + 1, rx, ry, 0.5,
'z', potentials);
1359 (rz - 0.5) * (ez_next - ez) *
1360 (m_zlines.at(k + 1) - m_zlines.at(k)) /
1361 (m_zlines.at(k + 2) - m_zlines.at(k + 1));
1364 const auto m2 = m_elementMaterial.at(
Index2Element(i, j, k - 1));
1367 GetFieldComponent(i, j, k - 1, rx, ry, 0.5,
'z', potentials);
1369 (rz + 0.5) * (ez - ez_next) *
1370 (m_zlines.at(k) - m_zlines.at(k - 1)) /
1371 (m_zlines.at(k + 1) - m_zlines.at(k));
1377void ComponentCST::Element2Index(
const size_t element,
1378 unsigned int& i,
unsigned int& j,
unsigned int& k)
const {
1379 const auto nx = m_xlines.size() - 1;
1380 const auto ny = m_ylines.size() - 1;
1381 const auto nxy = nx * ny;
1383 const auto tmp = element - k * nxy;
1388int ComponentCST::Index2Node(
const unsigned int i,
const unsigned int j,
1389 const unsigned int k)
const {
1390 if (i > m_nx - 1 || j > m_ny - 1 || k > m_nz - 1) {
1391 throw "ComponentCST::Index2Node: Error. Node indices out of bounds.";
1393 return i + j * m_nx + k * m_nx * m_ny;
1396void ComponentCST::Node2Index(
const size_t node,
1397 unsigned int& i,
unsigned int& j,
unsigned int& k)
const {
1399 const auto nx = m_xlines.size();
1400 const auto ny = m_ylines.size();
1401 const auto nxy = nx * ny;
1403 const auto tmp = node - k * nxy;
double GetPotential(int ele, Point3D *localP)
bool Coordinate2Index(const double x, const double y, const double z, unsigned int &i, unsigned int &j, unsigned int &k) const
bool GetElement(const size_t i, size_t &mat, bool &drift, std::vector< size_t > &nodes) const override
Return the material and node indices of a mesh element.
void ElectricField(const double x, const double y, const double z, double &ex, double &ey, double &ez, Medium *&m, int &status) override
void WeightingField(const double x, const double y, const double z, double &wx, double &wy, double &wz, const std::string &label) override
bool Initialise(std::string elist, std::string nlist, std::string mplist, std::string prnsol, std::string unit="cm")
bool GetNode(const size_t i, double &x, double &y, double &z) const override
Medium * GetMedium(const double x, const double y, const double z) override
Get the medium at a given location (x, y, z).
void GetElementBoundaries(unsigned int element, double &xmin, double &xmax, double &ymin, double &ymax, double &zmin, double &zmax) const
void GetNumberOfMeshLines(unsigned int &nx, unsigned int &ny, unsigned int &nz) const
double GetElementVolume(const size_t i) const override
bool SetWeightingField(std::string prnsol, std::string label, bool isBinary=true)
double WeightingPotential(const double x, const double y, const double z, const std::string &label) override
void ShiftComponent(const double xShift, const double yShift, const double zShift)
void GetAspectRatio(const size_t i, double &dmin, double &dmax) const override
void SetRangeZ(const double zmin, const double zmax)
ComponentCST()
Constructor.
int Index2Element(const unsigned int i, const unsigned int j, const unsigned int k) const
void PrintMaterials()
List all currently defined materials.
bool SetDefaultDriftMedium()
Find lowest epsilon, check for eps = 0, set default drift media flags.
static double ReadDouble(char *token, double def, bool &error)
void MapCoordinates(double &xpos, double &ypos, double &zpos, bool &xmirrored, bool &ymirrored, bool &zmirrored, double &rcoordinate, double &rotation) const
Move (xpos, ypos, zpos) to field map coordinates.
void PrintWarning(const std::string &header)
std::array< double, 3 > m_maxBoundingBox
std::array< double, 3 > m_mapmin
std::array< double, 3 > m_minBoundingBox
static double ScalingFactor(std::string unit)
void UpdatePeriodicity() override
Verify periodicities.
static int ReadInteger(char *token, int def, bool &error)
std::vector< Material > m_materials
ComponentFieldMap()=delete
Default constructor.
void PrintCouldNotOpen(const std::string &header, const std::string &filename) const
std::array< double, 3 > m_mapmax
void Reset() override
Reset the component.
bool m_debug
Switch on/off debugging messages.
std::string m_className
Class name.
bool m_ready
Ready for use?
Abstract base class for media.
bool IsDriftable() const
Is charge carrier transport enabled in this medium?