28 return s.size() >= t.size() && s.substr(s.size() - t.size(), t.size()) == t;
32 std::istringstream iss(s);
51 std::ifstream fmplist;
52 fmplist.open(mplist.c_str(), std::ios::in);
55 std::cerr <<
" Could not open result file " << mplist
63 newMaterial.
medium =
nullptr;
65 fmplist >> newMaterial.
eps;
72 newMaterial.
medium =
nullptr;
73 newMaterial.
eps = newMaterial.
ohm = -1;
77 std::map<int, int> domain2material;
80 for (
int i = 0; i < d2msize; ++i) {
83 fmplist >> domain2material[domain];
89 fmesh.open(mesh.c_str(), std::ios::in);
92 std::cerr <<
" Could not open nodes file " << mesh <<
" for reading.\n";
97 std::getline(fmesh, line);
98 }
while (!
ends_with(line,
"# number of mesh points"));
102 std::cout <<
" Read " <<
nNodes <<
" nodes from file " << mesh <<
".\n";
104 std::getline(fmesh, line);
105 }
while (line !=
"# Mesh point coordinates");
106 double minx = 1e100, miny = 1e100, minz = 1e100, maxx = -1e100, maxy = -1e100,
108 for (
int i = 0; i <
nNodes; ++i) {
110 fmesh >> newNode.
x >> newNode.
y >> newNode.
z;
114 nodes.push_back(newNode);
115 minx = std::min(minx, newNode.
x);
116 maxx = std::max(maxx, newNode.
x);
117 miny = std::min(miny, newNode.
y);
118 maxy = std::max(maxy, newNode.
y);
119 minz = std::min(minz, newNode.
z);
120 maxz = std::max(maxz, newNode.
z);
122 std::cout << minx <<
" < x < " << maxx <<
"\n";
123 std::cout << miny <<
" < y < " << maxy <<
"\n";
124 std::cout << minz <<
" < z < " << maxz <<
"\n";
127 std::getline(fmesh, line);
128 }
while (line !=
"4 tet2 # type name");
130 std::getline(fmesh, line);
131 }
while (!
ends_with(line,
"# number of elements"));
135 std::cout <<
" Read " <<
nElements <<
" elements from file " << mesh
137 std::getline(fmesh, line);
140 int perm[10] = {0, 1, 2, 3, 4, 5, 7, 6, 8, 9};
144 for (
int j = 0; j < 10; ++j) {
145 fmesh >> newElement.
emap[perm[j]];
151 std::getline(fmesh, line);
152 }
while (line !=
"# Geometric entity indices");
156 elements[i].matmap = domain2material.count(domain) ? domain2material[domain]
161 std::map<Node, std::vector<int>,
nodeCmp> nodeIdx;
162 for (
int i = 0; i <
nNodes; ++i) {
163 nodeIdx[
nodes[i]].push_back(i);
165 std::cout <<
"Map size: " << nodeIdx.size() << std::endl;
167 std::ifstream ffield;
168 ffield.open(field.c_str(), std::ios::in);
171 std::cerr <<
" Could not open field potentials file " << field
172 <<
" for reading.\n";
176 std::getline(ffield, line);
177 }
while (line.substr(0, 81) !=
181 std::istringstream sline(line);
189 while (sline >> token) {
191 std::cout <<
" Reading data for weighting field " << token <<
".\n";
198 for (
int i = 0; i <
nNodes; ++i) {
200 ffield >> tmp.
x >> tmp.
y >> tmp.
z >> tmp.
v;
210 double closestDist = 1;
211 const unsigned int nIdx = nodeIdx[tmp].size();
213 for (
unsigned int k = 0; k < nIdx; ++k) {
214 int j = nodeIdx[tmp][k];
215 double dist = (tmp.
x -
nodes[j].x) * (tmp.
x -
nodes[j].x) +
218 if (dist < closestDist) {
225 std::cerr <<
" Could not match the node from field potentials file: "
226 << tmp.
x <<
" " << tmp.
y <<
" " << tmp.
z <<
"\n.";
255 std::cerr <<
m_className <<
"::SetWeightingField:\n";
256 std::cerr <<
" No valid field map is present.\n";
257 std::cerr <<
" Weighting field cannot be added.\n";
262 std::ifstream ffield;
263 ffield.open(field.c_str(), std::ios::in);
266 std::cerr <<
" Could not open field potentials file " << field
267 <<
" for reading.\n";
283 for (
int j = 0; j <
nNodes; ++j) {
287 std::cout <<
m_className <<
"::SetWeightingField:\n";
288 std::cout <<
" Replacing existing weighting field " << label <<
".\n";
292 std::map<Node, std::vector<int>,
nodeCmp> nodeIdx;
293 for (
int i = 0; i <
nNodes; ++i) {
294 nodeIdx[
nodes[i]].push_back(i);
296 std::cout <<
"Map size: " << nodeIdx.size() << std::endl;
300 std::getline(ffield, line);
304 for (
int i = 0; i <
nNodes; ++i) {
306 ffield >> tmp.
x >> tmp.
y >> tmp.
z >> tmp.
v;
311 double closestDist = 1;
312 const unsigned int nIdx = nodeIdx[tmp].size();
314 for (
unsigned int k = 0; k < nIdx; ++k) {
315 int j = nodeIdx[tmp][k];
316 double dist = (tmp.
x -
nodes[j].x) * (tmp.
x -
nodes[j].x) +
319 if (dist < closestDist) {
326 std::cerr <<
" Could not match the node from field potentials file: "
327 << tmp.
x <<
" " << tmp.
y <<
" " << tmp.
z <<
"\n.";
330 nodes[closest].w[iw] = tmp.
v;
337 const double z,
double& ex,
double& ey,
338 double& ez,
Medium*& m,
int& status) {
345 const double zin,
double& ex,
double& ey,
346 double& ez,
double& volt,
Medium*& m,
350 double x = xin, y = yin, z = zin;
353 bool xmirr, ymirr, zmirr;
354 double rcoordinate, rotation;
355 MapCoordinates(x, y, z, xmirr, ymirr, zmirr, rcoordinate, rotation);
358 ex = ey = ez = volt = 0.;
372 double t1, t2, t3, t4, jac[4][4], det;
373 const int imap =
FindElement13(x, y, z, t1, t2, t3, t4, jac, det);
377 std::cout <<
" Point (" << x <<
", " << y <<
", " << z
378 <<
" not in the mesh.\n";
385 PrintElement(
"ElectricField", x, y, z, t1, t2, t3, t4, imap, 10);
400 volt = n0.
v * t1 * (2 * t1 - 1) + n1.
v * t2 * (2 * t2 - 1) +
401 n2.
v * t3 * (2 * t3 - 1) + n3.
v * t4 * (2 * t4 - 1) +
402 4 * n4.
v * t1 * t2 + 4 * n5.
v * t1 * t3 + 4 * n6.
v * t1 * t4 +
403 4 * n7.
v * t2 * t3 + 4 * n8.
v * t2 * t4 + 4 * n9.
v * t3 * t4;
404 ex = -(n0.
v * (4 * t1 - 1) * jac[0][1] + n1.
v * (4 * t2 - 1) * jac[1][1] +
405 n2.
v * (4 * t3 - 1) * jac[2][1] + n3.
v * (4 * t4 - 1) * jac[3][1] +
406 n4.
v * (4 * t2 * jac[0][1] + 4 * t1 * jac[1][1]) +
407 n5.
v * (4 * t3 * jac[0][1] + 4 * t1 * jac[2][1]) +
408 n6.
v * (4 * t4 * jac[0][1] + 4 * t1 * jac[3][1]) +
409 n7.
v * (4 * t3 * jac[1][1] + 4 * t2 * jac[2][1]) +
410 n8.
v * (4 * t4 * jac[1][1] + 4 * t2 * jac[3][1]) +
411 n9.
v * (4 * t4 * jac[2][1] + 4 * t3 * jac[3][1])) /
413 ey = -(n0.
v * (4 * t1 - 1) * jac[0][2] + n1.
v * (4 * t2 - 1) * jac[1][2] +
414 n2.
v * (4 * t3 - 1) * jac[2][2] + n3.
v * (4 * t4 - 1) * jac[3][2] +
415 n4.
v * (4 * t2 * jac[0][2] + 4 * t1 * jac[1][2]) +
416 n5.
v * (4 * t3 * jac[0][2] + 4 * t1 * jac[2][2]) +
417 n6.
v * (4 * t4 * jac[0][2] + 4 * t1 * jac[3][2]) +
418 n7.
v * (4 * t3 * jac[1][2] + 4 * t2 * jac[2][2]) +
419 n8.
v * (4 * t4 * jac[1][2] + 4 * t2 * jac[3][2]) +
420 n9.
v * (4 * t4 * jac[2][2] + 4 * t3 * jac[3][2])) /
422 ez = -(n0.
v * (4 * t1 - 1) * jac[0][3] + n1.
v * (4 * t2 - 1) * jac[1][3] +
423 n2.
v * (4 * t3 - 1) * jac[2][3] + n3.
v * (4 * t4 - 1) * jac[3][3] +
424 n4.
v * (4 * t2 * jac[0][3] + 4 * t1 * jac[1][3]) +
425 n5.
v * (4 * t3 * jac[0][3] + 4 * t1 * jac[2][3]) +
426 n6.
v * (4 * t4 * jac[0][3] + 4 * t1 * jac[3][3]) +
427 n7.
v * (4 * t3 * jac[1][3] + 4 * t2 * jac[2][3]) +
428 n8.
v * (4 * t4 * jac[1][3] + 4 * t2 * jac[3][3]) +
429 n9.
v * (4 * t4 * jac[2][3] + 4 * t3 * jac[3][3])) /
433 UnmapFields(ex, ey, ez, x, y, z, xmirr, ymirr, zmirr, rcoordinate, rotation);
440 std::cout <<
" Material " << element.
matmap <<
", drift flag "
451 const double zin,
double& wx,
double& wy,
452 double& wz,
const std::string& label) {
477 double x = xin, y = yin, z = zin;
480 bool xmirr, ymirr, zmirr;
481 double rcoordinate, rotation;
482 MapCoordinates(x, y, z, xmirr, ymirr, zmirr, rcoordinate, rotation);
487 double t1, t2, t3, t4, jac[4][4], det;
488 const int imap =
FindElement13(x, y, z, t1, t2, t3, t4, jac, det);
490 if (imap < 0)
return;
493 PrintElement(
"WeightingField", x, y, z, t1, t2, t3, t4, imap, 10, iw);
508 wx = -(n0.
w[iw] * (4 * t1 - 1) * jac[0][1] +
509 n1.
w[iw] * (4 * t2 - 1) * jac[1][1] +
510 n2.
w[iw] * (4 * t3 - 1) * jac[2][1] +
511 n3.
w[iw] * (4 * t4 - 1) * jac[3][1] +
512 n4.
w[iw] * (4 * t2 * jac[0][1] + 4 * t1 * jac[1][1]) +
513 n5.
w[iw] * (4 * t3 * jac[0][1] + 4 * t1 * jac[2][1]) +
514 n6.
w[iw] * (4 * t4 * jac[0][1] + 4 * t1 * jac[3][1]) +
515 n7.
w[iw] * (4 * t3 * jac[1][1] + 4 * t2 * jac[2][1]) +
516 n8.
w[iw] * (4 * t4 * jac[1][1] + 4 * t2 * jac[3][1]) +
517 n9.
w[iw] * (4 * t4 * jac[2][1] + 4 * t3 * jac[3][1])) /
520 wy = -(n0.
w[iw] * (4 * t1 - 1) * jac[0][2] +
521 n1.
w[iw] * (4 * t2 - 1) * jac[1][2] +
522 n2.
w[iw] * (4 * t3 - 1) * jac[2][2] +
523 n3.
w[iw] * (4 * t4 - 1) * jac[3][2] +
524 n4.
w[iw] * (4 * t2 * jac[0][2] + 4 * t1 * jac[1][2]) +
525 n5.
w[iw] * (4 * t3 * jac[0][2] + 4 * t1 * jac[2][2]) +
526 n6.
w[iw] * (4 * t4 * jac[0][2] + 4 * t1 * jac[3][2]) +
527 n7.
w[iw] * (4 * t3 * jac[1][2] + 4 * t2 * jac[2][2]) +
528 n8.
w[iw] * (4 * t4 * jac[1][2] + 4 * t2 * jac[3][2]) +
529 n9.
w[iw] * (4 * t4 * jac[2][2] + 4 * t3 * jac[3][2])) /
532 wz = -(n0.
w[iw] * (4 * t1 - 1) * jac[0][3] +
533 n1.
w[iw] * (4 * t2 - 1) * jac[1][3] +
534 n2.
w[iw] * (4 * t3 - 1) * jac[2][3] +
535 n3.
w[iw] * (4 * t4 - 1) * jac[3][3] +
536 n4.
w[iw] * (4 * t2 * jac[0][3] + 4 * t1 * jac[1][3]) +
537 n5.
w[iw] * (4 * t3 * jac[0][3] + 4 * t1 * jac[2][3]) +
538 n6.
w[iw] * (4 * t4 * jac[0][3] + 4 * t1 * jac[3][3]) +
539 n7.
w[iw] * (4 * t3 * jac[1][3] + 4 * t2 * jac[2][3]) +
540 n8.
w[iw] * (4 * t4 * jac[1][3] + 4 * t2 * jac[3][3]) +
541 n9.
w[iw] * (4 * t4 * jac[2][3] + 4 * t3 * jac[3][3])) /
545 UnmapFields(wx, wy, wz, x, y, z, xmirr, ymirr, zmirr, rcoordinate, rotation);
550 const std::string& label) {
567 if (!found)
return 0.;
572 double x = xin, y = yin, z = zin;
575 bool xmirr, ymirr, zmirr;
576 double rcoordinate, rotation;
577 MapCoordinates(x, y, z, xmirr, ymirr, zmirr, rcoordinate, rotation);
582 double t1, t2, t3, t4, jac[4][4], det;
583 const int imap =
FindElement13(x, y, z, t1, t2, t3, t4, jac, det);
584 if (imap < 0)
return 0.;
587 PrintElement(
"WeightingPotential", x, y, z, t1, t2, t3, t4, imap, 10, iw);
602 return n0.
w[iw] * t1 * (2 * t1 - 1) + n1.
w[iw] * t2 * (2 * t2 - 1) +
603 n2.
w[iw] * t3 * (2 * t3 - 1) + n3.
w[iw] * t4 * (2 * t4 - 1) +
604 4 * n4.
w[iw] * t1 * t2 + 4 * n5.
w[iw] * t1 * t3 +
605 4 * n6.
w[iw] * t1 * t4 + 4 * n7.
w[iw] * t2 * t3 +
606 4 * n8.
w[iw] * t2 * t4 + 4 * n9.
w[iw] * t3 * t4;
613 double x = xin, y = yin, z = zin;
616 bool xmirr, ymirr, zmirr;
617 double rcoordinate, rotation;
618 MapCoordinates(x, y, z, xmirr, ymirr, zmirr, rcoordinate, rotation);
628 double t1, t2, t3, t4, jac[4][4], det;
629 const int imap =
FindElement13(x, y, z, t1, t2, t3, t4, jac, det);
633 std::cout <<
" Point (" << x <<
", " << y <<
", " << z
634 <<
") not in the mesh.\n";
642 std::cerr <<
" Point (" << x <<
", " << y
643 <<
") has out of range material number " << imap <<
".\n";
649 PrintElement(
"GetMedium", x, y, z, t1, t2, t3, t4, imap, 10);
657 if (i >=
elements.size())
return 0.;
668 ((n1.
y - n0.
y) * (n2.
z - n0.
z) - (n2.
y - n0.
y) * (n1.
z - n0.
z)) +
670 ((n1.
z - n0.
z) * (n2.
x - n0.
x) - (n2.
z - n0.
z) * (n1.
x - n0.
x)) +
671 (n3.
z - n0.
z) * ((n1.
x - n0.
x) * (n2.
y - n0.
y) -
672 (n3.
x - n0.
x) * (n1.
y - n0.
y))) /
688 for (
int j = 0; j < np - 1; ++j) {
690 for (
int k = j + 1; k < np; ++k) {
693 const double dx = nj.
x - nk.
x;
694 const double dy = nj.
y - nk.
y;
695 const double dz = nj.
z - nk.
z;
696 const double dist = sqrt(dx * dx + dy * dy + dz * dz);
700 if (dist < dmin) dmin = dist;
701 if (dist > dmax) dmax = dist;
bool m_ready
Ready for use?
std::string m_className
Class name.
bool m_debug
Switch on/off debugging messages.
Medium * GetMedium(const double x, const double y, const double z)
Get the medium at a given location (x, y, z).
void UpdatePeriodicity()
Verify periodicities.
void GetAspectRatio(const unsigned int i, double &dmin, double &dmax)
void ElectricField(const double x, const double y, const double z, double &ex, double &ey, double &ez, Medium *&m, int &status)
double GetElementVolume(const unsigned int i)
void WeightingField(const double x, const double y, const double z, double &wx, double &wy, double &wz, const std::string &label)
bool SetWeightingField(std::string file, std::string label)
double WeightingPotential(const double x, const double y, const double z, const std::string &label)
bool Initialise(std::string header="mesh.mphtxt", std::string mplist="dielectrics.dat", std::string field="field.txt")
Base class for components based on finite-element field maps.
std::vector< bool > wfieldsOk
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)
unsigned int m_nMaterials
void PrintElement(const std::string &header, const double x, const double y, const double z, const double t1, const double t2, const double t3, const double t4, const unsigned int i, const unsigned int n, const int iw=-1) const
std::vector< Material > materials
int FindElement13(const double x, const double y, const double z, double &t1, double &t2, double &t3, double &t4, double jac[4][4], double &det)
Find the element for a point in curved quadratic tetrahedra.
std::vector< Node > nodes
virtual void SetRange()
Calculate x, y, z, V and angular ranges.
std::vector< Element > elements
std::vector< std::string > wfields
void UnmapFields(double &ex, double &ey, double &ez, double &xpos, double &ypos, double &zpos, bool &xmirrored, bool &ymirrored, bool &zmirrored, double &rcoordinate, double &rotation) const
Move (ex, ey, ez) to global coordinates.
void PrintNotReady(const std::string &header) const
Abstract base class for media.
int readInt(std::string s)
bool ends_with(std::string s, std::string t)