19 const double z,
double& ex,
20 double& ey,
double& ez,
Medium*& m,
36 const bool opt =
false;
40 status = Field(x, y, z, ex, ey, ez, v, opt);
54 const double z,
double& ex,
55 double& ey,
double& ez,
double& v,
59 ex = ey = ez = v = 0.;
71 const bool opt =
true;
74 status = Field(x, y, z, ex, ey, ez, v, opt);
93 std::cerr <<
" Unable to return voltage range.\n";
94 std::cerr <<
" Cell could not be setup.\n";
105 const double z,
double& wx,
106 double& wy,
double& wz,
107 const std::string label) {
111 if (nReadout <= 0)
return;
113 if (!PrepareSignals()) {
114 std::cerr <<
m_className <<
"::WeightingField::\n";
115 std::cerr <<
" Unable to calculate weighting fields.\n";
120 if (label.empty())
return;
122 for (
int i = nReadout; i--;) {
123 if (readout[i] == label) {
128 if (index < 0)
return;
131 Wfield(x, y, z, wx, wy, wz, volt, index,
false);
137 const std::string label) {
141 if (nReadout <= 0)
return volt;
143 if (!PrepareSignals()) {
144 std::cerr <<
m_className <<
"::WeightingPotential::\n";
145 std::cerr <<
" Unable to calculate weighting fields.\n";
150 if (label.empty())
return volt;
152 for (
int i = nReadout; i--;) {
153 if (readout[i] == label) {
158 if (index < 0)
return volt;
160 double wx = 0., wy = 0., wz = 0.;
161 Wfield(x, y, z, wx, wy, wz, volt, index,
true);
166 double& x1,
double& y1,
174 if (!cellset)
return false;
185 double x1,
double y1,
double z1,
186 double& xc,
double& yc,
double& zc) {
192 if (nWires <= 0)
return false;
194 const double dx = x1 - x0;
195 const double dy = y1 - y0;
196 const double d2 = dx * dx + dy * dy;
198 if (d2 < Small)
return false;
201 if ((perx &&
fabs(dx) >= sx) || (pery &&
fabs(dy) >= sy)) {
203 std::cerr <<
" Particle crossed more than one period.\n";
211 const double xm = 0.5 * (x0 + x1);
212 const double ym = 0.5 * (y0 + y1);
214 for (
int i = nWires; i--;) {
215 double xw = w[i].x, yw = w[i].y;
217 xw += sx * int(round((xm - xw) / sx));
220 yw += sy * int(round((ym - yw) / sy));
223 const double xIn0 = dx * (xw - x0) + dy * (yw - y0);
225 if (xIn0 < 0.)
continue;
226 const double xIn1 = -(dx * (xw - x1) + dy * (yw - y1));
228 if (xIn1 < 0.)
continue;
230 const double dw02 =
pow(xw - x0, 2) +
pow(yw - y0, 2);
231 const double dw12 =
pow(xw - x1, 2) +
pow(yw - y1, 2);
232 if (xIn1 * xIn1 * dw02 > xIn0 * xIn0 * dw12) {
233 dMin2 = dw02 - xIn0 * xIn0 / d2;
235 dMin2 = dw12 - xIn1 * xIn1 / d2;
238 const double r2 = 0.25 * w[i].d * w[i].d;
242 const double p = -xIn0 / d2;
243 const double q = (dw02 - r2) / d2;
244 const double t1 = -p +
sqrt(p * p - q);
245 const double t2 = -p -
sqrt(p * p - q);
246 const double t = std::min(t1, t2);
249 zc = z0 + t * (z1 - z0);
257 double& xw,
double& yw,
261 double x0 = xin, y0 = yin;
262 int nX = 0, nY = 0, nPhi = 0;
264 nX = int(round(xin / sx));
268 Cartesian2Polar(xin, yin, x0, y0);
269 nPhi = int(round((Pi * y0) / (sy * 180.)));
270 y0 -= 180. * sy * nPhi / Pi;
271 Polar2Cartesian(x0, y0, x0, y0);
273 nY = int(round(yin / sy));
278 if (perx && ynplan[0] && x0 <= coplan[0]) x0 += sx;
279 if (perx && ynplan[1] && x0 >= coplan[1]) x0 -= sx;
280 if (pery && ynplan[2] && y0 <= coplan[2]) y0 += sy;
281 if (pery && ynplan[3] && y0 >= coplan[3]) y0 -= sy;
283 for (
int i = 0; i < nWires; i++) {
284 const double xwc = w[i].x;
285 const double yxc = w[i].y;
286 const double r =
sqrt(
pow(xwc - x0, 2) +
pow(yxc - y0, 2));
287 const double rTrap = 0.5 * w[i].d * w[i].nTrap;
292 if (perx && ynplan[0] && x0 <= coplan[0]) x0 -= sx;
293 if (perx && ynplan[1] && x0 >= coplan[1]) x0 += sx;
294 if (pery && ynplan[2] && y0 <= coplan[2]) y0 -= sy;
295 if (pery && ynplan[3] && y0 >= coplan[3]) y0 += sy;
298 Cartesian2Polar(xw, yw, rhow, phiw);
299 phiw += 180. * sy * nPhi / Pi;
300 Polar2Cartesian(rhow, phiw, xw, yw);
304 if (perx) xw += sx * nX;
307 std::cout <<
" (" << xin <<
", " << yin <<
", " << zin <<
")"
308 <<
" within trap radius of wire " << i <<
".\n";
318 const double diameter,
319 const double voltage,
320 const std::string label,
321 const double length,
const double tension,
322 double rho,
const int ntrap) {
325 if (diameter <= 0.) {
327 std::cerr <<
" Unphysical wire diameter.\n";
333 std::cerr <<
" Unphysical wire tension.\n";
339 std::cerr <<
" Unphysical wire density.\n";
345 std::cerr <<
" Unphysical wire length.\n";
351 std::cerr <<
" Number of trap radii must be > 0.\n";
358 newWire.d = diameter;
361 newWire.type = label;
364 newWire.nTrap = ntrap;
366 w.push_back(newWire);
376 const std::string label) {
381 std::cerr <<
" Unphysical tube dimension.\n";
385 if (nEdges < 3 && nEdges != 0) {
387 std::cerr <<
" Unphysical number of tube edges (" << nEdges <<
")\n";
394 std::cout <<
" Warning: Existing tube settings will be overwritten.\n";
407 planes[4].type = label;
416 const std::string lab) {
418 if (ynplan[0] && ynplan[1]) {
420 std::cerr <<
" There are already two x planes defined.\n";
428 planes[1].type = lab;
434 planes[0].type = lab;
444 const std::string lab) {
446 if (ynplan[2] && ynplan[3]) {
448 std::cerr <<
" There are already two y planes defined.\n";
456 planes[3].type = lab;
462 planes[2].type = lab;
472 const double x,
const double smin,
474 const std::string label,
477 if (!ynplan[0] && !ynplan[1]) {
478 std::cerr <<
m_className <<
"::AddStripOnPlaneX:\n";
479 std::cerr <<
" There are no planes at constant x defined.\n";
483 if (direction !=
'y' && direction !=
'Y' && direction !=
'z' &&
485 std::cerr <<
m_className <<
"::AddStripOnPlaneX:\n";
486 std::cerr <<
" Invalid direction (" << direction <<
").\n";
487 std::cerr <<
" Only strips in y or z direction are possible.\n";
491 if (
fabs(smax - smin) < Small) {
492 std::cerr <<
m_className <<
"::AddStripOnPlaneX:\n";
493 std::cerr <<
" Strip width must be greater than zero.\n";
498 newStrip.type = label;
500 newStrip.smin = std::min(smin, smax);
501 newStrip.smax = std::max(smin, smax);
510 const double d0 =
fabs(coplan[0] - x);
511 const double d1 =
fabs(coplan[1] - x);
512 if (d1 < d0) iplane = 1;
515 if (direction ==
'y' || direction ==
'Y') {
516 planes[iplane].nStrips1++;
517 planes[iplane].strips1.push_back(newStrip);
519 planes[iplane].nStrips2++;
520 planes[iplane].strips2.push_back(newStrip);
525 const double y,
const double smin,
527 const std::string label,
530 if (!ynplan[2] && !ynplan[3]) {
531 std::cerr <<
m_className <<
"::AddStripOnPlaneY:\n";
532 std::cerr <<
" There are no planes at constant y defined.\n";
536 if (direction !=
'x' && direction !=
'X' && direction !=
'z' &&
538 std::cerr <<
m_className <<
"::AddStripOnPlaneY:\n";
539 std::cerr <<
" Invalid direction (" << direction <<
").\n";
540 std::cerr <<
" Only strips in x or z direction are possible.\n";
544 if (
fabs(smax - smin) < Small) {
545 std::cerr <<
m_className <<
"::AddStripOnPlaneY:\n";
546 std::cerr <<
" Strip width must be greater than zero.\n";
551 newStrip.type = label;
553 newStrip.smin = std::min(smin, smax);
554 newStrip.smax = std::max(smin, smax);
563 const double d2 =
fabs(coplan[2] - y);
564 const double d3 =
fabs(coplan[3] - y);
565 if (d3 < d2) iplane = 3;
568 if (direction ==
'x' || direction ==
'X') {
569 planes[iplane].nStrips1++;
570 planes[iplane].strips1.push_back(newStrip);
572 planes[iplane].nStrips2++;
573 planes[iplane].strips2.push_back(newStrip);
580 std::cerr <<
m_className <<
"::SetPeriodicityX:\n";
581 std::cerr <<
" Periodic length must be greater than zero.\n";
593 std::cerr <<
m_className <<
"::SetPeriodicityY:\n";
594 std::cerr <<
" Periodic length must be greater than zero.\n";
625void ComponentAnalyticField::UpdatePeriodicity() {
634 std::cerr <<
m_className <<
"::UpdatePeriodicity:\n";
635 std::cerr <<
" Periodicity in x direction was enabled"
636 <<
" but periodic length is not set.\n";
650 std::cerr <<
m_className <<
"::UpdatePeriodicity:\n";
651 std::cerr <<
" Periodicity in y direction was enabled"
652 <<
" but periodic length is not set.\n";
662 std::cerr <<
m_className <<
"::UpdatePeriodicity:\n";
663 std::cerr <<
" Periodicity in z is not possible.\n";
667 std::cerr <<
m_className <<
"::UpdatePeriodicity:\n";
668 std::cerr <<
" Mirror periodicity is not possible.\n";
672 std::cerr <<
m_className <<
"::UpdatePeriodicity:\n";
673 std::cerr <<
" Axial periodicity is not possible.\n";
677 std::cerr <<
m_className <<
"::UpdatePeriodicity:\n";
678 std::cerr <<
" Rotation symmetry is not possible.\n";
683 const double z,
const double q) {
690 newCharge.e = q / FourPiEpsilon0;
691 ch3d.push_back(newCharge);
707 std::cout <<
" No charges present.\n";
710 std::cout <<
" x [cm] y [cm] z [cm] charge [fC]\n";
711 for (
int i = 0; i < n3d; ++i) {
712 std::cout <<
" " << std::setw(9) << ch3d[i].x <<
" " << std::setw(9)
713 << ch3d[i].y <<
" " << std::setw(9) << ch3d[i].z <<
" "
714 << std::setw(11) << ch3d[i].e * FourPiEpsilon0 <<
"\n";
720 if (ynplan[0] && ynplan[1]) {
722 }
else if (ynplan[0] || ynplan[1]) {
730 if (ynplan[2] && ynplan[3]) {
732 }
else if (ynplan[2] || ynplan[3]) {
739 double& diameter,
double& voltage,
740 std::string& label,
double& length,
741 double& charge,
int& ntrap) {
743 if (i < 0 || i >= nWires) {
745 std::cerr <<
" Wire index is out of range.\n";
761 std::string& label) {
763 if (i < 0 || i >= 2 || (i == 1 && !ynplan[1])) {
765 std::cerr <<
" Plane index is out of range.\n";
771 label = planes[i].type;
776 std::string& label) {
778 if (i < 0 || i >= 2 || (i == 1 && !ynplan[3])) {
780 std::cerr <<
" Plane index is out of range.\n";
785 voltage = vtplan[i + 2];
786 label = planes[i + 2].type;
791 std::string& label) {
793 if (!tube)
return false;
797 label = planes[4].type;
801int ComponentAnalyticField::Field(
const double xin,
const double yin,
802 const double zin,
double& ex,
double& ey,
803 double& ez,
double& volt,
const bool opt) {
824 ex = ey = ez = volt = 0.;
826 double xpos = xin, ypos = yin;
830 xpos -= sx * int(round(xin / sx));
834 Cartesian2Polar(xin, yin, xpos, ypos);
835 arot = 180. * sy * int(round((Pi * ypos) / (sy * 180.))) / Pi;
837 Polar2Cartesian(xpos, ypos, xpos, ypos);
839 ypos -= sy * int(round(yin / sy));
843 if (perx && ynplan[0] && xpos <= coplan[0]) xpos += sx;
844 if (perx && ynplan[1] && xpos >= coplan[1]) xpos -= sx;
845 if (pery && ynplan[2] && ypos <= coplan[2]) ypos += sy;
846 if (pery && ynplan[3] && ypos >= coplan[3]) ypos -= sy;
850 if (!InTube(xpos, ypos, cotube, ntube)) {
855 if (ynplan[0] && xpos < coplan[0]) {
859 if (ynplan[1] && xpos > coplan[1]) {
863 if (ynplan[2] && ypos < coplan[2]) {
867 if (ynplan[3] && ypos > coplan[3]) {
874 for (
int i = nWires; i--;) {
875 double dxwir = xpos - w[i].x;
876 double dywir = ypos - w[i].y;
878 if (perx) dxwir -= sx * int(round(dxwir / sx));
879 if (pery) dywir -= sy * int(round(dywir / sy));
881 if (dxwir * dxwir + dywir * dywir < 0.25 * w[i].d * w[i].d) {
890 FieldA00(xpos, ypos, ex, ey, volt, opt);
893 FieldB1X(xpos, ypos, ex, ey, volt, opt);
896 FieldB1Y(xpos, ypos, ex, ey, volt, opt);
899 FieldB2X(xpos, ypos, ex, ey, volt, opt);
902 FieldB2Y(xpos, ypos, ex, ey, volt, opt);
905 FieldC10(xpos, ypos, ex, ey, volt, opt);
908 FieldC2X(xpos, ypos, ex, ey, volt, opt);
911 FieldC2Y(xpos, ypos, ex, ey, volt, opt);
914 FieldC30(xpos, ypos, ex, ey, volt, opt);
917 FieldD10(xpos, ypos, ex, ey, volt, opt);
920 FieldD20(xpos, ypos, ex, ey, volt, opt);
923 FieldD30(xpos, ypos, ex, ey, volt, opt);
928 std::cerr <<
" Unknown cell type (id " << iCellType <<
")\n";
935 double exd = 0., eyd = 0., voltd = 0.;
963 Cartesian2Polar(ex, ey, xaux, yaux);
965 Polar2Cartesian(xaux, yaux, ex, ey);
971 volt += corvta * xpos + corvtb * ypos + corvtc;
975 double ex3d = 0., ey3d = 0., ez3d = 0., volt3d = 0.;
980 Field3dA00(xin, yin, zin, ex3d, ey3d, ez3d, volt3d);
983 Field3dB2X(xin, yin, zin, ex3d, ey3d, ez3d, volt3d);
986 Field3dB2Y(xin, yin, zin, ex3d, ey3d, ez3d, volt3d);
989 Field3dD10(xin, yin, zin, ex3d, ey3d, ez3d, volt3d);
992 Field3dA00(xin, yin, zin, ex3d, ey3d, ez3d, volt3d);
1004void ComponentAnalyticField::CellInit() {
1023 perx = pery =
false;
1028 cellTypeFourier =
"A ";
1029 fperx = fpery =
false;
1030 mxmin = mxmax = mymin = mymax = 0;
1055 zmult = std::complex<double>(0., 0.);
1065 corvta = corvtb = corvtc = 0.;
1070 for (
int i = 0; i < 4; ++i) {
1076 ynplax = ynplay =
false;
1077 coplax = coplay = 1.;
1079 for (
int i = 0; i < 5; ++i) {
1080 planes[i].type =
'?';
1082 planes[i].ewxcor = 0.;
1083 planes[i].ewycor = 0.;
1084 planes[i].nStrips1 = 0;
1085 planes[i].nStrips2 = 0;
1086 planes[i].strips1.clear();
1087 planes[i].strips2.clear();
1109 down[0] = down[1] = 0.;
1113bool ComponentAnalyticField::Prepare() {
1118 std::cerr <<
" The cell does not meet the requirements.\n";
1123 std::cout <<
" Cell check ok.\n";
1129 std::cerr <<
" Type identification of the cell failed.\n";
1134 std::cout <<
" Cell is of type " << cellType <<
".\n";
1140 std::cerr <<
" Calculation of charges failed.\n";
1145 std::cout <<
" Calculation of charges was successful.\n";
1149 if (!PrepareStrips()) {
1151 std::cerr <<
" Strip preparation failed.\n";
1159bool ComponentAnalyticField::CellCheck() {
1174 double conew1 = coplan[0] - sx * int(round(coplan[0] / sx));
1175 double conew2 = coplan[1] - sx * int(round(coplan[1] / sx));
1177 if (ynplan[0] && ynplan[1] && conew1 == conew2) {
1184 if ((conew1 != coplan[0] && ynplan[0]) ||
1185 (conew2 != coplan[1] && ynplan[1])) {
1187 std::cout <<
" The planes in x or r are moved to the basic period.\n";
1188 std::cout <<
" This should not affect the results.";
1194 if (ynplan[0] && ynplan[1] &&
fabs(coplan[1] - coplan[0]) != sx) {
1196 std::cerr <<
" The separation of the x or r planes"
1197 <<
" does not match the period.\b";
1198 std::cerr <<
" The periodicity is cancelled.\n";
1202 if (ynplan[0] && ynplan[1] && vtplan[0] != vtplan[1]) {
1204 std::cerr <<
" The voltages of the two x (or r) planes differ.\n";
1205 std::cerr <<
" The periodicity is cancelled.\n";
1212 double conew3 = coplan[2] - sy * int(round(coplan[2] / sy));
1213 double conew4 = coplan[3] - sy * int(round(coplan[3] / sy));
1215 if (ynplan[2] && ynplan[3] && conew3 == conew4) {
1222 if ((conew3 != coplan[2] && ynplan[2]) ||
1223 (conew4 != coplan[3] && ynplan[3])) {
1225 std::cout <<
" The planes in y are moved to the basic period.\n";
1226 std::cout <<
" This should not affect the results.";
1232 if (ynplan[2] && ynplan[3] &&
fabs(coplan[3] - coplan[2]) != sy) {
1234 std::cerr <<
" The separation of the two y planes"
1235 <<
" does not match the period.\b";
1236 std::cerr <<
" The periodicity is cancelled.\n";
1240 if (ynplan[2] && ynplan[3] && vtplan[2] != vtplan[3]) {
1242 std::cerr <<
" The voltages of the two y planes differ.\n";
1243 std::cerr <<
" The periodicity is cancelled.\n";
1249 for (
int i = 0; i < 2; ++i) {
1250 for (
int j = 2; j < 3; ++j) {
1251 if (ynplan[i] && ynplan[j] && vtplan[i] != vtplan[j]) {
1253 std::cerr <<
" Conflicting potential of 2 crossing planes.\n";
1254 std::cerr <<
" One y (or phi) plane is removed.\n";
1261 for (
int i = 0; i < 3; i += 2) {
1262 if (ynplan[i] && ynplan[i + 1]) {
1263 if (coplan[i] == coplan[i + 1]) {
1265 std::cerr <<
" Two planes are on top of each other.\n";
1266 std::cerr <<
" One of them is removed.\n";
1267 ynplan[i + 1] =
false;
1269 if (coplan[i] > coplan[i + 1]) {
1272 std::cout <<
" Planes " << i <<
" and " << i + 1
1273 <<
" are interchanged.\n";
1276 const double cohlp = coplan[i];
1277 coplan[i] = coplan[i + 1];
1278 coplan[i + 1] = cohlp;
1280 const double vthlp = vtplan[i];
1281 vtplan[i] = vtplan[i + 1];
1282 vtplan[i + 1] = vthlp;
1284 plane plahlp = planes[i];
1285 planes[i] = planes[i + 1];
1286 planes[i + 1] = plahlp;
1293 for (
int i = 0; i < nWires; ++i) {
1294 const double xnew = w[i].x - sx * int(round(w[i].x / sx));
1295 if (
int(round(w[i].x / sx)) != 0) {
1296 double xprt = w[i].x;
1297 double yprt = w[i].y;
1298 if (polar) RTheta2RhoPhi(xprt, yprt, xprt, yprt);
1300 std::cout <<
" The " << w[i].type <<
"-wire at (" << xprt <<
", "
1301 << yprt <<
") is moved to the basic x (or r) period.\n";
1302 std::cout <<
" This should not affect the results.\n";
1310 for (
int i = 0; i < nWires; ++i) {
1311 double xnew = w[i].x;
1312 double ynew = w[i].y;
1313 Cartesian2Polar(xnew, ynew, xnew, ynew);
1314 if (
int(round((Pi / ynew) / (sy * 180.))) != 0) {
1316 std::cout <<
" The " << w[i].type <<
"-wire at (" << w[i].x <<
", "
1317 << w[i].y <<
") is moved to the basic phi period.\n";
1318 std::cout <<
" This should not affect the results.\n";
1319 ynew -= 180 * sy * int(round((Pi * ynew) / (sy * 180.))) / Pi;
1320 Polar2Cartesian(xnew, ynew, w[i].x, w[i].y);
1324 for (
int i = 0; i < nWires; ++i) {
1325 double ynew = w[i].y - sy * int(round(w[i].y / sy));
1326 if (
int(round(w[i].y / sy)) != 0) {
1327 double xprt = w[i].x;
1328 double yprt = w[i].y;
1329 if (polar) RTheta2RhoPhi(xprt, yprt, xprt, yprt);
1331 std::cout <<
" The " << w[i].type <<
"-wire at (" << xprt <<
", "
1332 << yprt <<
") is moved to the basic y period.\n";
1333 std::cout <<
" This should not affect the results.\n";
1340 int iplan1 = 0, iplan2 = 0, iplan3 = 0, iplan4 = 0;
1341 for (
int i = 0; i < nWires; ++i) {
1342 if (ynplan[0] && w[i].x <= coplan[0]) ++iplan1;
1343 if (ynplan[1] && w[i].x <= coplan[1]) ++iplan2;
1344 if (ynplan[2] && w[i].y <= coplan[2]) ++iplan3;
1345 if (ynplan[3] && w[i].y <= coplan[3]) ++iplan4;
1349 if (ynplan[0] && ynplan[1]) {
1350 if (iplan1 > nWires / 2) {
1356 if (iplan2 < nWires / 2) {
1363 if (ynplan[0] && !ynplan[1]) {
1364 if (iplan1 > nWires / 2)
1369 if (ynplan[1] && !ynplan[0]) {
1370 if (iplan2 < nWires / 2)
1376 if (ynplan[2] && ynplan[3]) {
1377 if (iplan3 > nWires / 2) {
1383 if (iplan4 < nWires / 2) {
1390 if (ynplan[2] && !ynplan[3]) {
1391 if (iplan3 > nWires / 2)
1396 if (ynplan[3] && !ynplan[2]) {
1397 if (iplan4 < nWires / 2)
1407 coplan[1] = coplan[0];
1408 vtplan[1] = vtplan[0];
1409 planes[1] = planes[0];
1415 coplan[0] = coplan[1];
1416 vtplan[0] = vtplan[1];
1417 planes[0] = planes[1];
1423 coplan[3] = coplan[2];
1424 vtplan[3] = vtplan[2];
1425 planes[3] = planes[2];
1431 coplan[2] = coplan[3];
1432 vtplan[2] = vtplan[3];
1433 planes[2] = planes[3];
1436 std::vector<bool> wrong(nWires,
false);
1438 for (
int i = 0; i < nWires; ++i) {
1439 if (ynplan[0] && w[i].x - 0.5 * w[i].d <= coplan[0]) wrong[i] =
true;
1440 if (ynplan[1] && w[i].x + 0.5 * w[i].d >= coplan[1]) wrong[i] =
true;
1441 if (ynplan[2] && w[i].y - 0.5 * w[i].d <= coplan[2]) wrong[i] =
true;
1442 if (ynplan[3] && w[i].y + 0.5 * w[i].d >= coplan[3]) wrong[i] =
true;
1444 if (!InTube(w[i].x, w[i].y, cotube, ntube)) {
1446 std::cerr <<
" The " << w[i].type <<
"-wire at (" << w[i].x <<
", "
1447 << w[i].y <<
") is located outside the tube.\n";
1448 std::cerr <<
" This wire is removed.\n";
1451 }
else if (wrong[i]) {
1452 double xprt = w[i].x;
1453 double yprt = w[i].y;
1454 if (polar) RTheta2RhoPhi(xprt, yprt, xprt, yprt);
1456 std::cerr <<
" The " << w[i].type <<
"-wire at (" << xprt <<
", "
1457 << yprt <<
") is located outside the planes.\n";
1458 std::cerr <<
" This wire is removed.\n";
1459 }
else if ((perx && w[i].d >= sx) || (pery && w[i].d >= sy)) {
1460 double xprt = w[i].x;
1461 double yprt = w[i].y;
1462 if (polar) RTheta2RhoPhi(xprt, yprt, xprt, yprt);
1464 std::cerr <<
" The diameter of the " << w[i].type <<
"-wire at ("
1465 << xprt <<
", " << yprt <<
") exceeds 1 period.\n";
1466 std::cerr <<
" This wire is removed.\n";
1472 for (
int i = 0; i < nWires; ++i) {
1473 if (wrong[i])
continue;
1474 for (
int j = i + 1; j < nWires; ++j) {
1475 if (wrong[j])
continue;
1480 double xaux1, xaux2, yaux1, yaux2;
1481 Cartesian2Polar(w[i].x, w[i].y, xaux1, yaux1);
1482 Cartesian2Polar(w[j].x, w[j].y, xaux2, yaux2);
1483 yaux1 -= sy * int(round(yaux1 / sy));
1484 yaux2 -= sy * int(round(yaux2 / sy));
1485 Polar2Cartesian(xaux1, yaux1, xaux1, yaux1);
1486 Polar2Cartesian(xaux2, yaux2, xaux2, yaux2);
1487 xsepar = xaux1 - xaux2;
1488 ysepar = yaux1 - yaux2;
1490 xsepar = w[i].x - w[j].x;
1491 ysepar = w[i].y - w[j].y;
1494 xsepar =
fabs(w[i].x - w[j].x);
1495 if (perx) xsepar -= sx * int(round(xsepar / sx));
1496 ysepar =
fabs(w[i].y - w[j].y);
1497 if (pery) ysepar -= sy * int(round(ysepar / sy));
1499 if (xsepar * xsepar + ysepar * ysepar < 0.25 *
pow(w[i].d + w[j].d, 2)) {
1500 double xprti = w[i].x;
1501 double yprti = w[i].y;
1502 double xprtj = w[j].x;
1503 double yprtj = w[j].y;
1504 if (polar) RTheta2RhoPhi(xprti, yprti, xprti, yprti);
1505 if (polar) RTheta2RhoPhi(xprtj, yprtj, xprtj, yprtj);
1507 std::cerr <<
" The " << w[i].type <<
"-wire at (" << xprti <<
", "
1509 <<
" and the " << w[j].type <<
"-wire at (" << xprtj
1510 <<
", " << yprtj <<
") overlap at least partially.\n";
1511 std::cerr <<
" The latter wire is removed.\n";
1518 const int iWires = nWires;
1520 for (
int i = 0; i < iWires; ++i) {
1522 w[nWires].x = w[i].x;
1523 w[nWires].y = w[i].y;
1524 w[nWires].d = w[i].d;
1525 w[nWires].v = w[i].v;
1526 w[nWires].type = w[i].type;
1527 w[nWires].u = w[i].u;
1528 w[nWires].e = w[i].e;
1529 w[nWires].ind = w[i].ind;
1530 w[nWires].nTrap = w[i].nTrap;
1536 int nElements = nWires;
1537 if (ynplan[0]) ++nElements;
1538 if (ynplan[1]) ++nElements;
1539 if (ynplan[2]) ++nElements;
1540 if (ynplan[3]) ++nElements;
1541 if (tube) ++nElements;
1543 if (nElements < 2) {
1545 std::cerr <<
" At least 2 elements are necessary.\n";
1546 std::cerr <<
" Cell rejected.\n";
1562 for (
int i = nWires; i--;) {
1564 xmin = std::min(xmin, w[i].x - w[i].d / 2.);
1565 xmax = std::max(xmax, w[i].x + w[i].d / 2.);
1567 xmin = w[i].x - w[i].d / 2.;
1568 xmax = w[i].x + w[i].d / 2.;
1572 ymin = std::min(ymin, w[i].y - w[i].d / 2.);
1573 ymax = std::max(ymax, w[i].y + w[i].d / 2.);
1575 ymin = w[i].y - w[i].d / 2.;
1576 ymax = w[i].y + w[i].d / 2.;
1580 zmin = std::min(zmin, -w[i].u / 2.);
1581 zmax = std::max(zmax, +w[i].u / 2.);
1583 zmin = -w[i].u / 2.;
1584 zmax = +w[i].u / 2.;
1588 vmin = std::min(vmin, w[i].v);
1589 vmax = std::max(vmax, w[i].v);
1591 vmin = vmax = w[i].v;
1596 for (
int i = 0; i < 4; ++i) {
1597 if (!ynplan[i])
continue;
1600 xmin = std::min(xmin, coplan[i]);
1601 xmax = std::max(xmax, coplan[i]);
1603 xmin = xmax = coplan[i];
1608 ymin = std::min(ymin, coplan[i]);
1609 ymax = std::max(ymax, coplan[i]);
1611 ymin = ymax = coplan[i];
1616 vmin = std::min(vmin, vtplan[i]);
1617 vmax = std::max(vmax, vtplan[i]);
1619 vmin = vmax = vtplan[i];
1626 xmin = -1.1 * cotube;
1627 xmax = +1.1 * cotube;
1629 ymin = -1.1 * cotube;
1630 ymax = +1.1 * cotube;
1632 vmin = std::min(vmin, vttube);
1633 vmax = std::max(vmax, vttube);
1638 if (perx && sx > (xmax - xmin)) {
1644 if (pery && sy > (ymax - ymin)) {
1650 if (polar && (ymax - ymin) >= TwoPi) {
1657 if (setx && xmin != xmax && (ymin == ymax || !sety)) {
1658 ymin -=
fabs(xmax - xmin) / 2.;
1659 ymax +=
fabs(xmax - xmin) / 2.;
1662 if (sety && ymin != ymax && (xmin == xmax || !setx)) {
1663 xmin -=
fabs(ymax - ymin) / 2.;
1664 xmax +=
fabs(ymax - ymin) / 2.;
1669 zmin = -(
fabs(xmax - xmin) +
fabs(ymax - ymin)) / 4.;
1670 zmax = +(
fabs(xmax - xmin) +
fabs(ymax - ymin)) / 4.;
1675 if (!(setx && sety && setz)) {
1677 std::cerr <<
" Unable to establish"
1678 <<
" default dimensions in all directions.\n";
1682 if (vmin == vmax || !setv) {
1684 std::cerr <<
" All potentials in the cell are the same.\n";
1685 std::cerr <<
" There is no point in going on.\n";
1693bool ComponentAnalyticField::CellType() {
1705 }
else if (ntube >= 3 && ntube <= 8) {
1715 std::cerr <<
" Potentials for tube with " << ntube
1716 <<
" edges are not yet available.\n";
1717 std::cerr <<
" Using a round tube instead.\n";
1726 if (!(perx || pery) && !(ynplan[0] && ynplan[1]) &&
1727 !(ynplan[2] && ynplan[3])) {
1734 if (perx && !pery && !(ynplan[0] || ynplan[1]) && !(ynplan[2] && ynplan[3])) {
1741 if (pery && !perx && !(ynplan[0] && ynplan[1]) && !(ynplan[2] || ynplan[3])) {
1748 if (perx && !pery && !(ynplan[2] && ynplan[3])) {
1754 if (!(perx || pery) && !(ynplan[2] && ynplan[3]) &&
1755 (ynplan[0] && ynplan[1])) {
1756 sx =
fabs(coplan[1] - coplan[0]);
1763 if (pery && !perx && !(ynplan[0] && ynplan[1])) {
1769 if (!(perx || pery) && !(ynplan[0] && ynplan[1]) &&
1770 (ynplan[2] && ynplan[3])) {
1771 sy =
fabs(coplan[3] - coplan[2]);
1778 if (!(ynplan[0] || ynplan[1] || ynplan[2] || ynplan[3]) && perx && pery) {
1785 if (!((ynplan[2] && pery) || (ynplan[2] && ynplan[3]))) {
1786 if (ynplan[0] && ynplan[1]) {
1787 sx =
fabs(coplan[1] - coplan[0]);
1792 if (perx && ynplan[0]) {
1800 if (!((ynplan[0] && perx) || (ynplan[0] && ynplan[1]))) {
1801 if (ynplan[2] && ynplan[3]) {
1802 sy =
fabs(coplan[3] - coplan[2]);
1807 if (pery && ynplan[2]) {
1822 sy =
fabs(coplan[3] - coplan[2]);
1829 sx =
fabs(coplan[1] - coplan[0]);
1835 if (ynplan[0] && ynplan[1] && ynplan[2] && ynplan[3]) {
1837 sx =
fabs(coplan[1] - coplan[0]);
1838 sy =
fabs(coplan[3] - coplan[2]);
1847bool ComponentAnalyticField::PrepareStrips() {
1854 double gapDef[4] = {0., 0., 0., 0.};
1859 gapDef[0] = coplan[1] - coplan[0];
1860 }
else if (nWires <= 0) {
1863 gapDef[0] = w[0].x - coplan[0];
1864 for (
int i = nWires; i--;) {
1865 if (w[i].x - coplan[0] < gapDef[0]) gapDef[0] = w[i].x - coplan[0];
1872 gapDef[1] = coplan[1] - coplan[0];
1873 }
else if (nWires <= 0) {
1876 gapDef[1] = coplan[1] - w[0].x;
1877 for (
int i = nWires; i--;) {
1878 if (coplan[1] - w[i].x < gapDef[1]) gapDef[1] = coplan[1] - w[i].x;
1885 gapDef[2] = coplan[3] - coplan[2];
1886 }
else if (nWires <= 0) {
1889 gapDef[2] = w[0].y - coplan[2];
1890 for (
int i = nWires; i--;) {
1891 if (w[i].y - coplan[2] < gapDef[2]) gapDef[2] = w[i].y - coplan[2];
1898 gapDef[3] = coplan[3] - coplan[2];
1899 }
else if (nWires <= 0) {
1902 gapDef[3] = coplan[3] - w[0].y;
1903 for (
int i = nWires; i--;) {
1904 if (coplan[3] - w[i].y < gapDef[3]) gapDef[3] = coplan[3] - w[i].y;
1910 for (
int i = 0; i < 4; ++i) {
1911 for (
int j = planes[i].nStrips1; j--;) {
1912 if (planes[i].strips1[j].gap < 0.) {
1913 planes[i].strips1[j].gap = gapDef[i];
1915 if (planes[i].strips1[j].gap < 0.) {
1917 std::cerr <<
" Not able to set a default anode-cathode gap\n";
1918 std::cerr <<
" for x/y-strip " << j <<
" of plane " << i <<
".\n";
1922 for (
int j = planes[i].nStrips2; j--;) {
1923 if (planes[i].strips2[j].gap < 0.) {
1924 planes[i].strips2[j].gap = gapDef[i];
1926 if (planes[i].strips2[j].gap < 0.) {
1928 std::cerr <<
" Not able to set a default anode-cathode gap\n";
1929 std::cerr <<
" for z-strip " << j <<
" of plane " << i <<
".\n";
1941 for (
int i = 0; i < nReadout; ++i) {
1942 if (readout[i] == label) {
1944 std::cout <<
" Readout group " << label <<
" already exists.\n";
1949 readout.push_back(label);
1952 int nWiresFound = 0;
1953 for (
int i = 0; i < nWires; ++i) {
1954 if (w[i].type == label) ++nWiresFound;
1957 int nPlanesFound = 0;
1958 int nStripsFound = 0;
1959 for (
int i = 0; i < 5; ++i) {
1960 if (planes[i].type == label) ++nPlanesFound;
1961 for (
int j = 0; j < planes[i].nStrips1; ++j) {
1962 if (planes[i].strips1[j].type == label) ++nStripsFound;
1964 for (
int j = 0; j < planes[i].nStrips2; ++j) {
1965 if (planes[i].strips2[j].type == label) ++nStripsFound;
1969 if (nWiresFound == 0 && nPlanesFound == 0 && nStripsFound == 0) {
1971 std::cerr <<
" At present there are no wires, planes or strips\n";
1972 std::cerr <<
" associated to readout group " << label <<
".\n";
1975 std::cout <<
" Readout group " << label <<
" comprises:\n";
1976 if (nWiresFound > 1) {
1977 std::cout <<
" " << nWiresFound <<
" wires\n";
1978 }
else if (nWiresFound == 1) {
1979 std::cout <<
" 1 wire\n";
1981 if (nPlanesFound > 1) {
1982 std::cout <<
" " << nPlanesFound <<
" planes\n";
1983 }
else if (nPlanesFound == 1) {
1984 std::cout <<
" 1 plane\n";
1986 if (nStripsFound > 1) {
1987 std::cout <<
" " << nStripsFound <<
" strips\n";
1988 }
else if (nStripsFound == 1) {
1989 std::cout <<
" 1 strip\n";
1996bool ComponentAnalyticField::Setup() {
2007 }
else if (ynplan[1]) {
2017 }
else if (ynplan[3]) {
2029 }
else if ((ynplan[0] && ynplan[1]) && !(ynplan[2] || ynplan[3])) {
2030 corvta = (vtplan[0] - vtplan[1]) / (coplan[0] - coplan[1]);
2032 corvtc = (vtplan[1] * coplan[0] - vtplan[0] * coplan[1]) /
2033 (coplan[0] - coplan[1]);
2034 }
else if ((ynplan[2] && ynplan[3]) && !(ynplan[0] || ynplan[1])) {
2036 corvtb = (vtplan[2] - vtplan[3]) / (coplan[2] - coplan[3]);
2037 corvtc = (vtplan[3] * coplan[2] - vtplan[2] * coplan[3]) /
2038 (coplan[2] - coplan[3]);
2040 corvta = corvtb = corvtc = 0.;
2041 if (ynplan[0]) corvtc = vtplan[0];
2042 if (ynplan[1]) corvtc = vtplan[1];
2043 if (ynplan[2]) corvtc = vtplan[2];
2044 if (ynplan[3]) corvtc = vtplan[3];
2048 if (nWires <= 0)
return true;
2052 for (
int i = 0; i < nWires; ++i) {
2053 a[i].resize(nWires);
2059 if (cellType ==
"A ") ok = SetupA00();
2060 if (cellType ==
"B1X") ok = SetupB1X();
2061 if (cellType ==
"B1Y") ok = SetupB1Y();
2062 if (cellType ==
"B2X") ok = SetupB2X();
2063 if (cellType ==
"B2Y") ok = SetupB2Y();
2064 if (cellType ==
"C1 ") ok = SetupC10();
2065 if (cellType ==
"C2X") ok = SetupC2X();
2066 if (cellType ==
"C2Y") ok = SetupC2Y();
2067 if (cellType ==
"C3 ") ok = SetupC30();
2068 if (cellType ==
"D1 ") ok = SetupD10();
2069 if (cellType ==
"D2 ") ok = SetupD20();
2070 if (cellType ==
"D3 ") ok = SetupD30();
2077 std::cerr <<
" Computing the dipole moments failed.\n";
2085 std::cerr <<
" Preparing the cell for field calculations"
2086 <<
" did not succeed.\n";
2092bool ComponentAnalyticField::SetupA00() {
2102 for (
int i = 0; i < nWires; ++i) {
2103 a[i][i] = 0.25 * w[i].d * w[i].d;
2105 if (ynplax) a[i][i] /= 4. *
pow(w[i].x - coplax, 2);
2106 if (ynplay) a[i][i] /= 4. *
pow(w[i].y - coplay, 2);
2108 if (ynplax && ynplay)
2109 a[i][i] *= 4.0 * (
pow(w[i].x - coplax, 2) +
pow(w[i].y - coplay, 2));
2111 a[i][i] = -0.5 * log(a[i][i]);
2113 for (
int j = i + 1; j < nWires; ++j) {
2114 a[i][j] =
pow(w[i].x - w[j].x, 2) +
pow(w[i].y - w[j].y, 2);
2117 a[i][j] = a[i][j] / (
pow(w[i].x + w[j].x - 2. * coplax, 2) +
2118 pow(w[i].y - w[j].y, 2));
2120 a[i][j] = a[i][j] / (
pow(w[i].x - w[j].x, 2) +
2121 pow(w[i].y + w[j].y - 2. * coplay, 2));
2123 if (ynplax && ynplay)
2124 a[i][j] *=
pow(w[i].x + w[j].x - 2. * coplax, 2) +
2125 pow(w[i].y + w[j].y - 2. * coplay, 2);
2127 a[i][j] = -0.5 * log(a[i][j]);
2136bool ComponentAnalyticField::SetupB1X() {
2148 double xx = 0., yy = 0., yymirr = 0.;
2152 for (
int i = 0; i < nWires; ++i) {
2153 a[i][i] = -log(0.5 * w[i].d * Pi / sx);
2156 yy = (Pi / sx) * 2. * (w[i].y - coplay);
2157 if (
fabs(yy) > 20.) a[i][i] +=
fabs(yy) - CLog2;
2158 if (
fabs(yy) <= 20.) a[i][i] += log(
fabs(sinh(yy)));
2161 for (
int j = i + 1; j < nWires; ++j) {
2162 xx = (Pi / sx) * (w[i].x - w[j].x);
2163 yy = (Pi / sx) * (w[i].y - w[j].y);
2164 if (
fabs(yy) > 20.) a[i][j] = -
fabs(yy) + CLog2;
2165 if (
fabs(yy) <= 20.)
2166 a[i][j] = -0.5 * log(
pow(sinh(yy), 2) +
pow(
sin(xx), 2));
2170 yymirr = (Pi / sx) * (w[i].y + w[j].y - 2. * coplay);
2171 if (
fabs(yymirr) > 20.) r2plan =
fabs(yymirr) - CLog2;
2172 if (
fabs(yymirr) <= 20.)
2173 r2plan = 0.5 * log(
pow(sinh(yymirr), 2) +
pow(
sin(xx), 2));
2184bool ComponentAnalyticField::SetupB1Y() {
2195 double xx = 0., yy = 0., xxmirr = 0.;
2199 for (
int i = 0; i < nWires; ++i) {
2200 a[i][i] = -log(0.5 * w[i].d * Pi / sy);
2203 xx = (Pi / sy) * 2. * (w[i].x - coplax);
2204 if (
fabs(xx) > 20.) a[i][i] +=
fabs(xx) - CLog2;
2205 if (
fabs(xx) <= 20.) a[i][i] += log(
fabs(sinh(xx)));
2208 for (
int j = i + 1; j < nWires; ++j) {
2209 xx = (Pi / sy) * (w[i].x - w[j].x);
2210 yy = (Pi / sy) * (w[i].y - w[j].y);
2211 if (
fabs(xx) > 20.) a[i][j] = -
fabs(xx) + CLog2;
2212 if (
fabs(xx) <= 20.)
2213 a[i][j] = -0.5 * log(
pow(sinh(xx), 2.) +
pow(
sin(yy), 2.));
2216 xxmirr = (Pi / sy) * (w[i].x + w[j].x - 2. * coplax);
2218 if (
fabs(xxmirr) > 20.) r2plan =
fabs(xxmirr) - CLog2;
2219 if (
fabs(xxmirr) <= 20.)
2220 r2plan = 0.5 * log(
pow(sinh(xxmirr), 2.) +
pow(
sin(yy), 2.));
2231bool ComponentAnalyticField::SetupB2X() {
2244 b2sin.resize(nWires);
2246 double xx, yy, xxneg, yymirr;
2249 for (
int i = 0; i < nWires; ++i) {
2250 xx = (Pi / sx) * (w[i].x - coplax);
2251 a[i][i] = (0.25 * w[i].d * Pi / sx) /
sin(xx);
2254 yymirr = (Pi / sx) * (w[i].y - coplay);
2255 if (
fabs(yymirr) <= 20.) {
2256 a[i][i] *=
sqrt(
pow(sinh(yymirr), 2) +
pow(
sin(xx), 2)) / sinh(yymirr);
2260 a[i][i] = -log(
fabs(a[i][i]));
2262 for (
int j = i + 1; j < nWires; ++j) {
2263 xx = HalfPi * (w[i].x - w[j].x) / sx;
2264 yy = HalfPi * (w[i].y - w[j].y) / sx;
2265 xxneg = HalfPi * (w[i].x + w[j].x - 2. * coplax) / sx;
2266 if (
fabs(yy) <= 20.) {
2267 a[i][j] = (
pow(sinh(yy), 2) +
pow(
sin(xx), 2)) /
2268 (
pow(sinh(yy), 2) +
pow(
sin(xxneg), 2));
2270 if (
fabs(yy) > 20.) a[i][j] = 1.0;
2273 yymirr = HalfPi * (w[i].y + w[j].y - 2. * coplay) / sx;
2274 if (
fabs(yymirr) <= 20.) {
2275 a[i][j] *= (
pow(sinh(yymirr), 2) +
pow(
sin(xxneg), 2)) /
2276 (
pow(sinh(yymirr), 2) +
pow(
sin(xx), 2));
2280 a[i][j] = -0.5 * log(a[i][j]);
2284 b2sin[i] =
sin(Pi * (coplax - w[i].x) / sx);
2290bool ComponentAnalyticField::SetupB2Y() {
2303 b2sin.resize(nWires);
2305 double xx = 0., yy = 0.;
2310 for (
int i = 0; i < nWires; ++i) {
2311 yy = (Pi / sy) * (w[i].y - coplay);
2312 a[i][i] = (0.25 * w[i].d * Pi / sy) /
sin(yy);
2315 xxmirr = (Pi / sy) * (w[i].x - coplax);
2316 if (
fabs(xxmirr) <= 20.) {
2317 a[i][i] *=
sqrt(
pow(sinh(xxmirr), 2) +
pow(
sin(yy), 2)) / sinh(xxmirr);
2321 a[i][i] = -log(
fabs(a[i][i]));
2323 for (
int j = i + 1; j < nWires; j++) {
2324 xx = HalfPi * (w[i].x - w[j].x) / sy;
2325 yy = HalfPi * (w[i].y - w[j].y) / sy;
2326 yyneg = HalfPi * (w[i].y + w[j].y - 2. * coplay) / sy;
2327 if (
fabs(xx) <= 20.) {
2328 a[i][j] = (
pow(sinh(xx), 2) +
pow(
sin(yy), 2)) /
2329 (
pow(sinh(xx), 2) +
pow(
sin(yyneg), 2));
2331 if (
fabs(xx) > 20.) a[i][j] = 1.0;
2334 xxmirr = HalfPi * (w[i].x + w[j].x - 2. * coplax) / sy;
2335 if (
fabs(xxmirr) <= 20.) {
2336 a[i][j] *= (
pow(sinh(xxmirr), 2) +
pow(
sin(yyneg), 2)) /
2337 (
pow(sinh(xxmirr), 2) +
pow(
sin(yy), 2));
2341 a[i][j] = -0.5 * log(a[i][j]);
2345 b2sin[i] =
sin(Pi * (coplay - w[i].y) / sy);
2351bool ComponentAnalyticField::SetupC10() {
2369 if (sy / sx < 8.) p =
exp(-Pi * sy / sx);
2370 zmult = std::complex<double>(Pi / sx, 0.);
2373 if (sx / sy < 8.) p =
exp(-Pi * sx / sy);
2374 zmult = std::complex<double>(0., Pi / sy);
2377 if (p1 > 1.e-10) p2 =
pow(p, 6);
2381 std::cout <<
" p, p1, p2 = " << p <<
", " << p1 <<
", " << p2 <<
"\n";
2382 std::cout <<
" zmult = " << zmult <<
"\n";
2383 std::cout <<
" mode = " << mode <<
"\n";
2386 double xyi = 0., xyj = 0., temp = 0.;
2388 for (
int i = 0; i < nWires; ++i) {
2389 for (
int j = 0; j < nWires; ++j) {
2390 xyi = mode == 0 ? w[i].x : w[i].y;
2391 xyj = mode == 0 ? w[j].x : w[j].y;
2392 temp = xyi * xyj * TwoPi / (sx * sy);
2394 a[i][j] = Ph2Lim(0.5 * w[i].d) - temp;
2396 a[i][j] = Ph2(w[i].x - w[j].x, w[i].y - w[j].y) - temp;
2401 if (!Charge())
return false;
2404 for (
int j = 0; j < nWires; ++j) {
2405 xyj = mode == 0 ? w[j].x : w[j].y;
2408 c1 = -s * 2. * Pi / (sx * sy);
2412bool ComponentAnalyticField::SetupC2X() {
2427 if (2. * sx <= sy) {
2429 if (sy / sx < 25.) p =
exp(-HalfPi * sy / sx);
2430 zmult = std::complex<double>(HalfPi / sx, 0.);
2433 if (sx / sy < 6.) p =
exp(-2. * Pi * sx / sy);
2434 zmult = std::complex<double>(0., Pi / sy);
2437 if (p1 > 1.e-10) p2 =
pow(p, 6);
2441 std::cout <<
" p, p1, p2 = " << p <<
", " << p1 <<
", " << p2 <<
"\n";
2442 std::cout <<
" zmult = " << zmult <<
"\n";
2443 std::cout <<
" mode = " << mode <<
"\n";
2448 for (
int i = 0; i < nWires; ++i) {
2449 const double cx = coplax - sx * int(round((coplax - w[i].x) / sx));
2450 for (
int j = 0; j < nWires; ++j) {
2452 if (mode == 0) temp = (w[i].x - cx) * (w[j].x - cx) * TwoPi / (sx * sy);
2454 a[i][i] = Ph2Lim(0.5 * w[i].d) - Ph2(2. * (w[i].x - cx), 0.) - temp;
2456 a[i][j] = Ph2(w[i].x - w[j].x, w[i].y - w[j].y) -
2457 Ph2(w[i].x + w[j].x - 2. * cx, w[i].y - w[j].y) - temp;
2462 if (!Charge())
return false;
2467 for (
int i = 0; i < nWires; ++i) {
2468 const double cx = coplax - sx * int(round((coplax - w[i].x) / sx));
2469 s += w[i].e * (w[i].x - cx);
2471 c1 = -s * TwoPi / (sx * sy);
2476bool ComponentAnalyticField::SetupC2Y() {
2491 if (sx <= 2. * sy) {
2493 if (sy / sx <= 6.) p =
exp(-2. * Pi * sy / sx);
2494 zmult = std::complex<double>(Pi / sx, 0.);
2497 if (sx / sy <= 25.) p =
exp(-HalfPi * sx / sy);
2498 zmult = std::complex<double>(0., HalfPi / sy);
2501 if (p1 > 1.e-10) p2 =
pow(p, 6);
2505 std::cout <<
" p, p1, p2 = " << p <<
", " << p1 <<
", " << p2 <<
"\n";
2506 std::cout <<
" zmult = " << zmult <<
"\n";
2507 std::cout <<
" mode = " << mode <<
"\n";
2512 for (
int i = 0; i < nWires; ++i) {
2513 const double cy = coplay - sy * int(round((coplay - w[i].y) / sy));
2514 for (
int j = 0; j < nWires; ++j) {
2516 if (mode == 1) temp = (w[i].y - cy) * (w[j].y - cy) * TwoPi / (sx * sy);
2518 a[i][i] = Ph2Lim(0.5 * w[i].d) - Ph2(0., 2. * (w[j].y - cy)) - temp;
2520 a[i][j] = Ph2(w[i].x - w[j].x, w[i].y - w[j].y) -
2521 Ph2(w[i].x - w[j].x, w[i].y + w[j].y - 2. * cy) - temp;
2526 if (!Charge())
return false;
2531 for (
int i = 0; i < nWires; ++i) {
2532 const double cy = coplay - sy * int(round((coplay - w[i].y) / sy));
2533 s += w[i].e * (w[i].y - cy);
2535 c1 = -s * TwoPi / (sx * sy);
2540bool ComponentAnalyticField::SetupC30() {
2557 if (sy / sx <= 13.) p =
exp(-Pi * sy / sx);
2558 zmult = std::complex<double>(HalfPi / sx, 0.);
2561 if (sx / sy <= 13.) p =
exp(-Pi * sx / sy);
2562 zmult = std::complex<double>(0., HalfPi / sy);
2565 if (p1 > 1.e-10) p2 =
pow(p, 6);
2569 std::cout <<
" p, p1, p2 = " << p <<
", " << p1 <<
", " << p2 <<
"\n";
2570 std::cout <<
" zmult = " << zmult <<
"\n";
2571 std::cout <<
" mode = " << mode <<
"\n";
2575 for (
int i = 0; i < nWires; ++i) {
2576 double cx = coplax - sx * int(round((coplax - w[i].x) / sx));
2577 double cy = coplay - sy * int(round((coplay - w[i].y) / sy));
2578 for (
int j = 0; j < nWires; ++j) {
2580 a[i][i] = Ph2Lim(0.5 * w[i].d) - Ph2(0., 2. * (w[i].y - cy)) -
2581 Ph2(2. * (w[i].x - cx), 0.) +
2582 Ph2(2. * (w[i].x - cx), 2. * (w[i].y - cy));
2584 a[i][j] = Ph2(w[i].x - w[j].x, w[i].y - w[j].y) -
2585 Ph2(w[i].x - w[j].x, w[i].y + w[j].y - 2. * cy) -
2586 Ph2(w[i].x + w[j].x - 2. * cx, w[i].y - w[j].y) +
2587 Ph2(w[i].x + w[j].x - 2. * cx, w[i].y + w[j].y - 2. * cy);
2592 if (!Charge())
return false;
2598bool ComponentAnalyticField::SetupD10() {
2607 std::complex<double> zi, zj;
2610 for (
int i = 0; i < nWires; ++i) {
2612 a[i][i] = -log(0.5 * w[i].d * cotube /
2613 (cotube * cotube - (w[i].x * w[i].x + w[i].y * w[i].y)));
2615 zi = std::complex<double>(w[i].x, w[i].y);
2617 for (
int j = i + 1; j < nWires; j++) {
2619 zj = std::complex<double>(w[j].x, w[j].y);
2621 -log(abs(cotube * (zi - zj) / (cotube * cotube - conj(zi) * zj)));
2630bool ComponentAnalyticField::SetupD20() {
2640 std::complex<double> zi, zj;
2643 for (
int i = 0; i < nWires; ++i) {
2645 zi = std::complex<double>(w[i].x, w[i].y);
2646 if (abs(zi) < w[i].d / 2.) {
2649 for (
int j = 0; j < nWires; ++j) {
2654 (cotube - (w[i].x * w[i].x + w[i].y * w[i].y) / cotube));
2657 zj = std::complex<double>(w[j].x, w[j].y);
2658 a[j][i] = -log(abs((1. / cotube) * (zi - zj) /
2659 (1. - conj(zi) * zj / (cotube * cotube))));
2665 for (
int j = 0; j < nWires; ++j) {
2668 a[i][i] = -log(abs(0.5 * w[i].d * mtube *
pow(zi, mtube - 1) /
2669 (
pow(cotube, mtube) *
2670 (1. -
pow((abs(zi) / cotube), 2 * mtube)))));
2673 zj = std::complex<double>(w[j].x, w[j].y);
2675 -log(abs((1 /
pow(cotube, mtube)) *
2676 (
pow(zj, mtube) -
pow(zi, mtube)) /
2677 (1. -
pow(zj * conj(zi) / (cotube * cotube), mtube))));
2686bool ComponentAnalyticField::SetupD30() {
2696 wmap.assign(nWires, std::complex<double>(0., 0.));
2698 std::complex<double> wd = std::complex<double>(0., 0.);
2700 InitializeCoefficientTables();
2703 kappa = tgamma((ntube + 1.) / ntube) * tgamma((ntube - 2.) / ntube) /
2704 tgamma((ntube - 1.) / ntube);
2706 for (
int i = 0; i < nWires; ++i) {
2708 ConformalMap(std::complex<double>(w[i].x, w[i].y) / cotube, wmap[i], wd);
2711 -log(abs((0.5 * w[i].d / cotube) * wd / (1. -
pow(abs(wmap[i]), 2))));
2713 for (
int j = 0; j < i; ++j) {
2714 a[i][j] = -log(abs((wmap[i] - wmap[j]) / (1. - conj(wmap[i]) * wmap[j])));
2723bool ComponentAnalyticField::Charge() {
2733 std::vector<double> b;
2735 for (
int i = 0; i < nWires; ++i) {
2736 b[i] = w[i].v - (corvta * w[i].x + corvtb * w[i].y + corvtc);
2743 if (!(ynplan[0] || ynplan[1] || ynplan[2] || ynplan[3] || tube)) {
2746 a.resize(nWires + 1);
2748 for (
int i = 0; i < nWires; ++i) {
2750 a[nWires].push_back(1.);
2752 a[nWires].push_back(0.);
2757 std::cerr <<
" Matrix inversion failed.\n";
2761 if (a[nWires][nWires] != 0.) {
2762 const double t = 1. / a[nWires][nWires];
2763 for (
int i = 0; i < nWires; ++i) {
2764 for (
int j = 0; j < nWires; ++j) {
2765 a[i][j] -= t * a[i][nWires] * a[nWires][j];
2770 std::cerr <<
" True inverse of the capacitance matrix"
2771 <<
" could not be calculated.\n";
2772 std::cerr <<
" Use of the FACTOR instruction should be avoided.\n";
2787 std::cerr <<
" Failure to solve the capacitance equations.\n";
2788 std::cerr <<
" No charges are available.\n";
2793 for (
int i = 0; i < nWires; ++i) w[i].e = b[i];
2798 std::cout <<
" Dump of the capacitance matrix after inversion:\n";
2799 for (
int i = 0; i < nWires; i += 10) {
2800 for (
int j = 0; j < nWires; j += 10) {
2801 std::cout <<
" (Block " << i / 10 <<
", " << j / 10 <<
")\n";
2802 for (
int ii = 0; ii < 10; ++ii) {
2803 if (i + ii >= nWires)
break;
2804 for (
int jj = 0; jj < 10; ++jj) {
2805 if (j + jj >= nWires)
break;
2806 std::cout << std::setw(6) << a[i + ii][j + jj] <<
" ";
2814 std::cout <<
" End of the inverted capacitance matrix.\n";
2820 std::cout <<
" Quality check of the charge calculation.\n";
2821 std::cout <<
" Wire E as obtained E reconstructed\n";
2822 for (
int i = 0; i < nWires; ++i) {
2824 for (
int j = 0; j < nWires; ++j) {
2826 (w[j].v - v0 - (corvta * w[j].x + corvtb * w[j].y + corvtc));
2828 std::cout <<
" " << i <<
" " << w[i].e <<
" " << b[i] <<
"\n";
2834double ComponentAnalyticField::Ph2(
const double xpos,
const double ypos) {
2850 std::complex<double> zeta = zmult * std::complex<double>(xpos, ypos);
2851 if (
fabs(imag(zeta)) < 10.) {
2852 std::complex<double> zsin =
sin(zeta);
2853 std::complex<double> zcof = 4. * zsin * zsin - 2.;
2854 std::complex<double> zu = -p1 - zcof * p2;
2855 std::complex<double> zunew = 1. - zcof * zu - p2;
2856 std::complex<double> zterm = (zunew + zu) * zsin;
2857 return -log(abs(zterm));
2860 return -
fabs(imag(zeta)) + CLog2;
2863void ComponentAnalyticField::ConformalMap(std::complex<double> z,
2864 std::complex<double>& ww,
2865 std::complex<double>& wd) {
2877 const int nterm = 15;
2884 }
else if (abs(z) < 0.75) {
2887 std::complex<double> zterm =
pow(kappa * z, ntube);
2888 std::complex<double> wdsum = 0.;
2889 std::complex<double> wsum = cc1[ntube - 3][nterm];
2890 for (
int i = nterm; i--;) {
2891 wdsum = wsum + zterm * wdsum;
2892 wsum = cc1[ntube - 3][i] + zterm * wsum;
2895 ww = kappa * z * wsum;
2896 wd = kappa * (wsum + double(ntube) * zterm * wdsum);
2901 -TwoPi * int(round(atan2(imag(z), real(z)) * ntube / TwoPi)) / ntube;
2902 std::complex<double> zz = z * std::complex<double>(
cos(arot),
sin(arot));
2904 std::complex<double> zterm =
pow(kappa * (1. - zz), ntube / (ntube - 2.));
2905 std::complex<double> wdsum = 0.;
2906 std::complex<double> wsum = cc2[ntube - 3][nterm];
2907 for (
int i = nterm; i--;) {
2908 wdsum = wsum + zterm * wdsum;
2909 wsum = cc2[ntube - 3][i] + zterm * wsum;
2912 ww = std::complex<double>(
cos(arot), -
sin(arot)) * (1. - zterm * wsum);
2913 wd = ntube * kappa *
pow(kappa * (1. - zz), 2. / (ntube - 2.)) *
2914 (wsum + zterm * wdsum) / (ntube - 2.);
2918void ComponentAnalyticField::E2Sum(
const double xpos,
const double ypos,
2919 double& ex,
double& ey) {
2932 const std::complex<double> icons = std::complex<double>(0., 1.);
2934 std::complex<double> wsum = 0.;
2935 std::complex<double> zsin, zcof, zu, zunew;
2936 std::complex<double> zterm1, zterm2, zeta;
2938 for (
int j = 0; j < nWires; ++j) {
2939 zeta = zmult * std::complex<double>(xpos - w[j].x, ypos - w[j].y);
2940 if (imag(zeta) > 15.) {
2941 wsum -= w[j].e * icons;
2942 }
else if (imag(zeta) < -15.) {
2943 wsum += w[j].e * icons;
2946 zcof = 4. * zsin * zsin - 2.;
2947 zu = -p1 - zcof * p2;
2948 zunew = 1. - zcof * zu - p2;
2949 zterm1 = (zunew + zu) * zsin;
2950 zu = -3. * p1 - zcof * 5. * p2;
2951 zunew = 1. - zcof * zu - 5. * p2;
2952 zterm2 = (zunew - zu) *
cos(zeta);
2953 wsum += w[j].e * (zterm2 / zterm1);
2956 ex = -real(-zmult * wsum);
2957 ey = imag(-zmult * wsum);
2960void ComponentAnalyticField::FieldA00(
const double xpos,
const double ypos,
2961 double& ex,
double& ey,
double& volt,
2982 double xxmirr = 0., yymirr = 0.;
2984 for (
int i = nWires; i--;) {
2985 const double xx = xpos - w[i].x;
2986 const double yy = ypos - w[i].y;
2987 double r2 = xx * xx + yy * yy;
2989 double exhelp = xx / r2;
2990 double eyhelp = yy / r2;
2993 xxmirr = w[i].x + (xpos - 2. * coplax);
2994 const double r2plan = xxmirr * xxmirr + yy * yy;
2995 exhelp -= xxmirr / r2plan;
2996 eyhelp -= yy / r2plan;
3001 yymirr = w[i].y + (ypos - 2. * coplay);
3002 const double r2plan = xx * xx + yymirr * yymirr;
3003 exhelp -= xx / r2plan;
3004 eyhelp -= yymirr / r2plan;
3008 if (ynplax && ynplay) {
3009 const double r2plan = xxmirr * xxmirr + yymirr * yymirr;
3010 exhelp += xxmirr / r2plan;
3011 eyhelp += yymirr / r2plan;
3015 if (opt) volt -= 0.5 * w[i].e * log(r2);
3016 ex += w[i].e * exhelp;
3017 ey += w[i].e * eyhelp;
3021void ComponentAnalyticField::FieldB1X(
const double xpos,
const double ypos,
3022 double& ex,
double& ey,
double& volt,
3033 const std::complex<double> icons = std::complex<double>(0., 1.);
3035 std::complex<double> zz, ecompl, zzmirr;
3044 for (
int i = nWires; i--;) {
3045 const double xx = (Pi / sx) * (xpos - w[i].x);
3046 const double yy = (Pi / sx) * (ypos - w[i].y);
3047 zz = std::complex<double>(xx, yy);
3049 if (yy > 20.) ecompl = -icons;
3050 if (
fabs(yy) <= 20.)
3052 icons * (
exp(2. * icons * zz) + 1.) / (
exp(2. * icons * zz) - 1.);
3053 if (yy < -20.) ecompl = icons;
3055 if (
fabs(yy) > 20.) r2 = -
fabs(yy) + CLog2;
3056 if (
fabs(yy) <= 20.) r2 = -0.5 * log(
pow(sinh(yy), 2) +
pow(
sin(xx), 2));
3060 const double yymirr = (Pi / sx) * (ypos + w[i].y - 2. * coplay);
3061 zzmirr = std::complex<double>(xx, yymirr);
3062 if (yymirr > 20.) ecompl += icons;
3063 if (
fabs(yymirr) <= 20.)
3064 ecompl += -icons * (
exp(2. * icons * zzmirr) + 1.) /
3065 (
exp(2. * icons * zzmirr) - 1.);
3066 if (yymirr < -20.) ecompl += -icons;
3068 if (opt &&
fabs(yymirr) > 20.) r2 +=
fabs(yymirr) - CLog2;
3069 if (opt &&
fabs(yymirr) <= 20.)
3070 r2 += 0.5 * log(
pow(sinh(yymirr), 2) +
pow(
sin(xx), 2));
3073 ex += w[i].e * real(ecompl);
3074 ey -= w[i].e * imag(ecompl);
3075 if (opt) volt += w[i].e * r2;
3081void ComponentAnalyticField::FieldB1Y(
const double xpos,
const double ypos,
3082 double& ex,
double& ey,
double& volt,
3093 std::complex<double> zz, ecompl, zzmirr;
3102 for (
int i = nWires; i--;) {
3103 const double xx = (Pi / sy) * (xpos - w[i].x);
3104 const double yy = (Pi / sy) * (ypos - w[i].y);
3105 zz = std::complex<double>(xx, yy);
3107 if (xx > 20.) ecompl = 1.;
3108 if (
fabs(xx) <= 20.) ecompl = (
exp(2. * zz) + 1.) / (
exp(2. * zz) - 1.);
3109 if (xx < -20.) ecompl = -1.;
3111 if (
fabs(xx) > 20.) r2 = -
fabs(xx) + CLog2;
3112 if (
fabs(xx) <= 20.) r2 = -0.5 * log(
pow(sinh(xx), 2) +
pow(
sin(yy), 2));
3116 const double xxmirr = (Pi / sy) * (xpos + w[i].x - 2. * coplax);
3117 zzmirr = std::complex<double>(xxmirr, yy);
3118 if (xxmirr > 20.) ecompl -= 1.;
3119 if (xxmirr < -20.) ecompl += 1.;
3120 if (
fabs(xxmirr) <= 20.)
3121 ecompl -= (
exp(2. * zzmirr) + 1.) / (
exp(2. * zzmirr) - 1.);
3122 if (opt &&
fabs(xxmirr) > 20.) r2 +=
fabs(xxmirr) - CLog2;
3123 if (opt &&
fabs(xxmirr) <= 20.)
3124 r2 += 0.5 * log(
pow(sinh(xxmirr), 2) +
pow(
sin(yy), 2));
3127 ex += w[i].e * real(ecompl);
3128 ey -= w[i].e * imag(ecompl);
3129 if (opt) volt += w[i].e * r2;
3135void ComponentAnalyticField::FieldB2X(
const double xpos,
const double ypos,
3136 double& ex,
double& ey,
double& volt,
3148 std::complex<double> zz, ecompl, zzmirr, zzneg, zznmirr;
3155 for (
int i = nWires; i--;) {
3156 const double xx = HalfPi * (xpos - w[i].x) / sx;
3157 const double yy = HalfPi * (ypos - w[i].y) / sx;
3158 const double xxneg = HalfPi * (xpos - w[i].x - 2 * coplax) / sx;
3159 zz = std::complex<double>(xx, yy);
3160 zzneg = std::complex<double>(xxneg, yy);
3164 if (
fabs(yy) <= 20.) {
3165 ecompl = -b2sin[i] / (
sin(zz) *
sin(zzneg));
3167 r2 = (
pow(sinh(yy), 2) +
pow(
sin(xx), 2)) /
3168 (
pow(sinh(yy), 2) +
pow(
sin(xxneg), 2));
3173 const double yymirr = HalfPi * (ypos + w[i].y - 2 * coplay) / sx;
3174 zzmirr = std::complex<double>(xx, yymirr);
3175 zznmirr = std::complex<double>(xxneg, yymirr);
3176 if (
fabs(yymirr) <= 20.) {
3177 ecompl += b2sin[i] / (
sin(zzmirr) *
sin(zznmirr));
3179 const double r2plan = (
pow(sinh(yymirr), 2) +
pow(
sin(xx), 2)) /
3180 (
pow(sinh(yymirr), 2) +
pow(
sin(xxneg), 2));
3186 ex += w[i].e * real(ecompl);
3187 ey -= w[i].e * imag(ecompl);
3188 if (opt) volt -= 0.5 * w[i].e * log(r2);
3190 ex *= (HalfPi / sx);
3191 ey *= (HalfPi / sx);
3194void ComponentAnalyticField::FieldB2Y(
const double xpos,
const double ypos,
3195 double& ex,
double& ey,
double& volt,
3207 const std::complex<double> icons(0., 1.);
3209 std::complex<double> zz, zzneg, zzmirr, zznmirr, ecompl;
3216 for (
int i = nWires; i--;) {
3217 const double xx = HalfPi * (xpos - w[i].x) / sy;
3218 const double yy = HalfPi * (ypos - w[i].y) / sy;
3219 const double yyneg = HalfPi * (ypos + w[i].y - 2. * coplay) / sy;
3220 zz = std::complex<double>(xx, yy);
3221 zzneg = std::complex<double>(xx, yyneg);
3225 if (
fabs(xx) <= 20.) {
3226 ecompl = icons * b2sin[i] / (
sin(icons * zz) *
sin(icons * zzneg));
3228 r2 = (
pow(sinh(xx), 2) +
pow(
sin(yy), 2)) /
3229 (
pow(sinh(xx), 2) +
pow(
sin(yyneg), 2));
3234 const double xxmirr = HalfPi * (xpos + w[i].x - 2. * coplax) / sy;
3235 zzmirr = std::complex<double>(xxmirr, yy);
3236 zznmirr = std::complex<double>(xxmirr, yyneg);
3237 if (
fabs(xxmirr) <= 20.) {
3239 icons * b2sin[i] / (
sin(icons * zzmirr) *
sin(icons * zznmirr));
3241 const double r2plan = (
pow(sinh(xxmirr), 2) +
pow(
sin(yy), 2)) /
3242 (
pow(sinh(xxmirr), 2) +
pow(
sin(yyneg), 2));
3248 ex += w[i].e * real(ecompl);
3249 ey -= w[i].e * imag(ecompl);
3250 if (opt) volt -= 0.5 * w[i].e * log(r2);
3252 ex *= (HalfPi / sy);
3253 ey *= (HalfPi / sy);
3256void ComponentAnalyticField::FieldC10(
const double xpos,
const double ypos,
3257 double& ex,
double& ey,
double& volt,
3268 if (mode == 0) volt = v0 + c1 * xpos;
3269 if (mode == 1) volt = v0 + c1 * ypos;
3270 for (
int i = 0; i < nWires; ++i) {
3271 volt += w[i].e * Ph2(xpos - w[i].x, ypos - w[i].y);
3276 E2Sum(xpos, ypos, ex, ey);
3277 if (mode == 0) ex -= c1;
3278 if (mode == 1) ey -= c1;
3281void ComponentAnalyticField::FieldC2X(
const double xpos,
const double ypos,
3282 double& ex,
double& ey,
double& volt,
3291 const std::complex<double> icons(0., 1.);
3293 std::complex<double> zsin, zcof, zu, zunew;
3294 std::complex<double> zterm1, zterm2, zeta;
3297 std::complex<double> wsum1 = 0.;
3298 std::complex<double> wsum2 = 0.;
3302 for (
int i = nWires; i--;) {
3304 zeta = zmult * std::complex<double>(xpos - w[i].x, ypos - w[i].y);
3305 if (imag(zeta) > 15.) {
3306 wsum1 -= w[i].e * icons;
3307 if (opt) volt -= w[i].e * (
fabs(imag(zeta)) - CLog2);
3308 }
else if (imag(zeta) < -15.) {
3309 wsum1 += w[i].e * icons;
3310 if (opt) volt -= w[i].e * (
fabs(imag(zeta)) - CLog2);
3313 zcof = 4. * zsin * zsin - 2.;
3314 zu = -p1 - zcof * p2;
3315 zunew = 1. - zcof * zu - p2;
3316 zterm1 = (zunew + zu) * zsin;
3317 zu = -3. * p1 - zcof * 5. * p2;
3318 zunew = 1. - zcof * zu - 5. * p2;
3319 zterm2 = (zunew - zu) *
cos(zeta);
3320 wsum1 += w[i].e * (zterm2 / zterm1);
3321 if (opt) volt -= w[i].e * log(abs(zterm1));
3324 double cx = coplax - sx * int(round((coplax - w[i].x) / sx));
3326 zeta = zmult * std::complex<double>(2. * cx - xpos - w[i].x, ypos - w[i].y);
3327 if (imag(zeta) > 15.) {
3328 wsum2 -= w[i].e * icons;
3329 if (opt) volt += w[i].e * (
fabs(imag(zeta)) - CLog2);
3330 }
else if (imag(zeta) < -15.) {
3331 wsum2 += w[i].e * icons;
3332 if (opt) volt += w[i].e * (
fabs(imag(zeta)) - CLog2);
3335 zcof = 4. * zsin * zsin - 2.;
3336 zu = -p1 - zcof * p2;
3337 zunew = 1. - zcof * zu - p2;
3338 zterm1 = (zunew + zu) * zsin;
3339 zu = -3. * p1 - zcof * 5. * p2;
3340 zunew = 1. - zcof * zu - 5. * p2;
3341 zterm2 = (zunew - zu) *
cos(zeta);
3342 wsum2 += w[i].e * (zterm2 / zterm1);
3343 if (opt) volt += w[i].e * log(abs(zterm1));
3346 if (opt && mode == 0) {
3347 volt -= TwoPi * w[i].e * (xpos - cx) * (w[i].x - cx) / (sx * sy);
3351 ex = real(zmult * (wsum1 + wsum2));
3352 ey = -imag(zmult * (wsum1 - wsum2));
3354 if (mode == 0) ex -= c1;
3357void ComponentAnalyticField::FieldC2Y(
const double xpos,
const double ypos,
3358 double& ex,
double& ey,
double& volt,
3367 const std::complex<double> icons(0., 1.);
3369 std::complex<double> zsin, zcof, zu, zunew;
3370 std::complex<double> zterm1, zterm2, zeta;
3374 std::complex<double> wsum1 = 0.;
3375 std::complex<double> wsum2 = 0.;
3378 for (
int i = nWires; i--;) {
3380 zeta = zmult * std::complex<double>(xpos - w[i].x, ypos - w[i].y);
3381 if (imag(zeta) > 15.) {
3382 wsum1 -= w[i].e * icons;
3383 if (opt) volt -= w[i].e * (
fabs(imag(zeta)) - CLog2);
3384 }
else if (imag(zeta) < -15.) {
3385 wsum1 += w[i].e * icons;
3386 if (opt) volt -= w[i].e * (
fabs(imag(zeta)) - CLog2);
3389 zcof = 4. * zsin * zsin - 2.;
3390 zu = -p1 - zcof * p2;
3391 zunew = 1. - zcof * zu - p2;
3392 zterm1 = (zunew + zu) * zsin;
3393 zu = -3. * p1 - zcof * 5. * p2;
3394 zunew = 1. - zcof * zu - 5. * p2;
3395 zterm2 = (zunew - zu) *
cos(zeta);
3396 wsum1 += w[i].e * (zterm2 / zterm1);
3397 if (opt) volt -= w[i].e * log(abs(zterm1));
3400 const double cy = coplay - sy * int(round((coplay - w[i].y) / sy));
3402 zeta = zmult * std::complex<double>(xpos - w[i].x, 2 * cy - ypos - w[i].y);
3403 if (imag(zeta) > 15.) {
3404 wsum2 -= w[i].e * icons;
3405 if (opt) volt += w[i].e * (
fabs(imag(zeta)) - CLog2);
3406 }
else if (imag(zeta) < -15.) {
3407 wsum2 += w[i].e * icons;
3408 if (opt) volt += w[i].e * (
fabs(imag(zeta)) - CLog2);
3411 zcof = 4. * zsin * zsin - 2.;
3412 zu = -p1 - zcof * p2;
3413 zunew = 1. - zcof * zu - p2;
3414 zterm1 = (zunew + zu) * zsin;
3415 zu = -3. * p1 - zcof * 5. * p2;
3416 zunew = 1. - zcof * zu - 5. * p2;
3417 zterm2 = (zunew - zu) *
cos(zeta);
3418 wsum2 += w[i].e * (zterm2 / zterm1);
3419 if (opt) volt += w[i].e * log(abs(zterm1));
3422 if (opt && mode == 1) {
3423 volt -= TwoPi * w[i].e * (ypos - cy) * (w[i].y - cy) / (sx * sy);
3427 ex = real(zmult * (wsum1 - wsum2));
3428 ey = -imag(zmult * (wsum1 + wsum2));
3430 if (mode == 1) ey -= c1;
3433void ComponentAnalyticField::FieldC30(
const double xpos,
const double ypos,
3434 double& ex,
double& ey,
double& volt,
3443 const std::complex<double> icons(0., 1.);
3445 std::complex<double> zsin, zcof, zu, zunew;
3446 std::complex<double> zterm1, zterm2, zeta;
3449 std::complex<double> wsum1 = 0.;
3450 std::complex<double> wsum2 = 0.;
3451 std::complex<double> wsum3 = 0.;
3452 std::complex<double> wsum4 = 0.;
3456 for (
int i = 0; i < nWires; ++i) {
3458 zeta = zmult * std::complex<double>(xpos - w[i].x, ypos - w[i].y);
3459 if (imag(zeta) > 15.) {
3460 wsum1 -= w[i].e * icons;
3461 if (opt) volt -= w[i].e * (
fabs(imag(zeta)) - CLog2);
3462 }
else if (imag(zeta) < -15.) {
3463 wsum1 += w[i].e * icons;
3464 if (opt) volt -= w[i].e * (
fabs(imag(zeta)) - CLog2);
3467 zcof = 4. * zsin * zsin - 2.;
3468 zu = -p1 - zcof * p2;
3469 zunew = 1. - zcof * zu - p2;
3470 zterm1 = (zunew + zu) * zsin;
3471 zu = -3. * p1 - zcof * 5. * p2;
3472 zunew = 1. - zcof * zu - 5. * p2;
3473 zterm2 = (zunew - zu) *
cos(zeta);
3474 wsum1 += w[i].e * (zterm2 / zterm1);
3475 if (opt) volt -= w[i].e * log(abs(zterm1));
3478 double cx = coplax - sx * int(round((coplax - w[i].x) / sx));
3480 zeta = zmult * std::complex<double>(2. * cx - xpos - w[i].x, ypos - w[i].y);
3481 if (imag(zeta) > 15.) {
3482 wsum2 -= w[i].e * icons;
3483 if (opt) volt += w[i].e * (
fabs(imag(zeta)) - CLog2);
3484 }
else if (imag(zeta) < -15.) {
3485 wsum2 += w[i].e * icons;
3486 if (opt) volt += w[i].e * (
fabs(imag(zeta)) - CLog2);
3489 zcof = 4. * zsin * zsin - 2.;
3490 zu = -p1 - zcof * p2;
3491 zunew = 1. - zcof * zu - p2;
3492 zterm1 = (zunew + zu) * zsin;
3493 zu = -3. * p1 - zcof * 5. * p2;
3494 zunew = 1. - zcof * zu - 5. * p2;
3495 zterm2 = (zunew - zu) *
cos(zeta);
3496 wsum2 += w[i].e * (zterm2 / zterm1);
3497 if (opt) volt += w[i].e * log(abs(zterm1));
3500 double cy = coplay - sy * int(round((coplay - w[i].y) / sy));
3502 zeta = zmult * std::complex<double>(2. * cx - xpos - w[i].x, ypos - w[i].y);
3503 if (imag(zeta) > 15.) {
3504 wsum3 -= w[i].e * icons;
3505 if (opt) volt += w[i].e * (
fabs(imag(zeta)) - CLog2);
3506 }
else if (imag(zeta) < -15.) {
3507 wsum3 += w[i].e * icons;
3508 if (opt) volt += w[i].e * (
fabs(imag(zeta)) - CLog2);
3511 zcof = 4. * zsin * zsin - 2.;
3512 zu = -p1 - zcof * p2;
3513 zunew = 1. - zcof * zu - p2;
3514 zterm1 = (zunew + zu) * zsin;
3515 zu = -3. * p1 - zcof * 5. * p2;
3516 zunew = 1. - zcof * zu - 5. * p2;
3517 zterm2 = (zunew - zu) *
cos(zeta);
3518 wsum3 += w[i].e * (zterm2 / zterm1);
3519 if (opt) volt += w[i].e * log(abs(zterm1));
3522 zeta = zmult * std::complex<double>(2. * cx - xpos - w[i].x,
3523 2. * cy - ypos - w[i].y);
3524 if (imag(zeta) > 15.) {
3525 wsum4 -= w[i].e * icons;
3526 if (opt) volt -= w[i].e * (
fabs(imag(zeta)) - CLog2);
3527 }
else if (imag(zeta) < -15.) {
3528 wsum4 += w[i].e * icons;
3529 if (opt) volt -= w[i].e * (
fabs(imag(zeta)) - CLog2);
3532 zcof = 4. * zsin * zsin - 2.;
3533 zu = -p1 - zcof * p2;
3534 zunew = 1. - zcof * zu - p2;
3535 zterm1 = (zunew + zu) * zsin;
3536 zu = -3. * p1 - zcof * 5. * p2;
3537 zunew = 1. - zcof * zu - 5. * p2;
3538 zterm2 = (zunew - zu) *
cos(zeta);
3539 wsum4 += w[i].e * (zterm2 / zterm1);
3540 if (opt) volt -= w[i].e * log(abs(zterm1));
3544 ex = real(zmult * (wsum1 + wsum2 - wsum3 - wsum4));
3545 ey = -imag(zmult * (wsum1 - wsum2 + wsum3 - wsum4));
3548void ComponentAnalyticField::FieldD10(
const double xpos,
const double ypos,
3549 double& ex,
double& ey,
double& volt,
3567 std::complex<double> zpos = std::complex<double>(xpos, ypos);
3568 std::complex<double> zi;
3569 std::complex<double> wi;
3572 for (
int i = nWires; i--;) {
3574 zi = std::complex<double>(w[i].x, w[i].y);
3579 log(abs(cotube * (zpos - zi) / (cotube * cotube - zpos * conj(zi))));
3581 wi = 1. / conj(zpos - zi) + zi / (cotube * cotube - conj(zpos) * zi);
3582 ex += w[i].e * real(wi);
3583 ey += w[i].e * imag(wi);
3587void ComponentAnalyticField::FieldD20(
const double xpos,
const double ypos,
3588 double& ex,
double& ey,
double& volt,
3606 std::complex<double> zpos = std::complex<double>(xpos, ypos);
3607 std::complex<double> zi;
3608 std::complex<double> wi;
3611 for (
int i = nWires; i--;) {
3613 zi = std::complex<double>(w[i].x, w[i].y);
3615 if (abs(zi) > w[i].d / 2.) {
3620 log(abs((1. /
pow(cotube, mtube)) *
3621 (
pow(zpos, mtube) -
pow(zi, mtube)) /
3622 (1. -
pow(zpos * conj(zi) / (cotube * cotube), mtube))));
3625 wi = double(mtube) *
pow(conj(zpos), mtube - 1) *
3626 (1. / conj(
pow(zpos, mtube) -
pow(zi, mtube)) +
3628 (
pow(cotube, 2 * mtube) -
pow(conj(zpos) * zi, mtube)));
3629 ex += w[i].e * real(wi);
3630 ey += w[i].e * imag(wi);
3634 volt -= w[i].e * log(abs((1. / cotube) * (zpos - zi) /
3635 (1. - zpos * conj(zi) / (cotube * cotube))));
3637 wi = 1. / conj(zpos - zi) + zi / (cotube * cotube - conj(zpos) * zi);
3639 ex += w[i].e * real(wi);
3640 ey += w[i].e * imag(wi);
3645void ComponentAnalyticField::FieldD30(
const double xpos,
const double ypos,
3646 double& ex,
double& ey,
double& volt,
3663 std::complex<double> whelp;
3666 std::complex<double> wpos, wdpos;
3667 ConformalMap(std::complex<double>(xpos, ypos) / cotube, wpos, wdpos);
3669 for (
int i = nWires; i--;) {
3672 volt -= w[i].e * log(abs((wpos - wmap[i]) / (1. - wpos * conj(wmap[i]))));
3674 whelp = wdpos * (1. -
pow(abs(wmap[i]), 2)) /
3675 ((wpos - wmap[i]) * (1. - conj(wmap[i]) * wpos));
3677 ex += w[i].e * real(whelp);
3678 ey -= w[i].e * imag(whelp);
3684bool ComponentAnalyticField::InTube(
const double x0,
const double y0,
3685 const double a,
const int n) {
3695 if (x0 == 0. && y0 == 0.)
return true;
3699 if (x0 * x0 + y0 * y0 > a * a)
return false;
3703 if (n < 0 || n == 1 || n == 2) {
3705 std::cerr <<
" Invalid number of edges (n = " << n <<
")\n";
3711 double phi = atan2(y0, x0);
3712 if (phi < 0.)
phi += TwoPi;
3713 phi -= TwoPi * int(0.5 * n * phi / Pi) / n;
3715 if ((x0 * x0 + y0 * y0) *
pow(
cos(Pi / n - phi), 2) >
3716 a * a *
pow(
cos(Pi / n), 2))
3722void ComponentAnalyticField::InitializeCoefficientTables() {
3724 const int nterms = 16;
3729 for (
int i = 0; i < 6; ++i) {
3731 cc1[i].resize(nterms);
3733 cc2[i].resize(nterms);
3737 const double cc13[nterms] = {
3738 0.1000000000e+01, -.1666666865e+00, 0.3174602985e-01, -.5731921643e-02,
3739 0.1040112227e-02, -.1886279933e-03, 0.3421107249e-04, -.6204730198e-05,
3740 0.1125329618e-05, -.2040969207e-06, 0.3701631357e-07, -.6713513301e-08,
3741 0.1217605794e-08, -.2208327132e-09, 0.4005162868e-10, -.7264017512e-11};
3742 const double cc23[nterms] = {
3743 0.3333333135e+00, -.5555555597e-01, 0.1014109328e-01, -.1837154618e-02,
3744 0.3332451452e-03, -.6043842586e-04, 0.1096152027e-04, -.1988050826e-05,
3745 0.3605655365e-06, -.6539443120e-07, 0.1186035448e-07, -.2151069323e-08,
3746 0.3901317047e-09, -.7075676156e-10, 0.1283289534e-10, -.2327455936e-11};
3749 const double cc14[nterms] = {
3750 0.1000000000e+01, -.1000000238e+00, 0.8333332837e-02, -.7051283028e-03,
3751 0.5967194738e-04, -.5049648280e-05, 0.4273189802e-06, -.3616123934e-07,
3752 0.3060091514e-08, -.2589557457e-09, 0.2191374859e-10, -.1854418528e-11,
3753 0.1569274224e-12, -.1327975205e-13, 0.1123779363e-14, -.9509817570e-16};
3754 const double cc24[nterms] = {
3755 0.1000000000e+01, -.5000000000e+00, 0.3000000119e+00, -.1750000119e+00,
3756 0.1016666889e+00, -.5916666612e-01, 0.3442307562e-01, -.2002724260e-01,
3757 0.1165192947e-01, -.6779119372e-02, 0.3944106400e-02, -.2294691978e-02,
3758 0.1335057430e-02, -.7767395582e-03, 0.4519091453e-03, -.2629216760e-03};
3761 const double cc15[nterms] = {
3762 0.1000000000e+01, -.6666666269e-01, 0.1212121220e-02, -.2626262140e-03,
3763 -.3322110570e-04, -.9413293810e-05, -.2570029210e-05, -.7695705904e-06,
3764 -.2422486887e-06, -.7945993730e-07, -.2691839640e-07, -.9361642128e-08,
3765 -.3327319087e-08, -.1204430555e-08, -.4428404310e-09, -.1650302672e-09};
3766 const double cc25[nterms] = {
3767 0.1248050690e+01, -.7788147926e+00, 0.6355384588e+00, -.4899077415e+00,
3768 0.3713272810e+00, -.2838423252e+00, 0.2174729109e+00, -.1663445234e+00,
3769 0.1271933913e+00, -.9728997946e-01, 0.7442557812e-01, -.5692918226e-01,
3770 0.4354400188e-01, -.3330700099e-01, 0.2547712997e-01, -.1948769018e-01};
3773 const double cc16[nterms] = {
3774 0.1000000000e+01, -.4761904851e-01, -.1221001148e-02, -.3753788769e-03,
3775 -.9415557724e-04, -.2862767724e-04, -.9587882232e-05, -.3441659828e-05,
3776 -.1299798896e-05, -.5103651119e-06, -.2066504408e-06, -.8578405186e-07,
3777 -.3635090096e-07, -.1567239494e-07, -.6857355572e-08, -.3038770346e-08};
3778 const double cc26[nterms] = {
3779 0.1333333015e+01, -.8888888955e+00, 0.8395061493e+00, -.7242798209e+00,
3780 0.6016069055e+00, -.5107235312e+00, 0.4393203855e+00, -.3745460510e+00,
3781 0.3175755739e+00, -.2703750730e+00, 0.2308617830e+00, -.1966916919e+00,
3782 0.1672732830e+00, -.1424439549e+00, 0.1214511395e+00, -.1034612656e+00};
3785 const double cc17[nterms] = {
3786 0.1000000000e+01, -.3571428731e-01, -.2040816238e-02, -.4936389159e-03,
3787 -.1446709794e-03, -.4963850370e-04, -.1877940667e-04, -.7600909157e-05,
3788 -.3232265954e-05, -.1427365532e-05, -.6493634714e-06, -.3026190711e-06,
3789 -.1438593245e-06, -.6953911225e-07, -.3409525462e-07, -.1692310647e-07};
3790 const double cc27[nterms] = {
3791 0.1359752655e+01, -.9244638681e+00, 0.9593217969e+00, -.8771237731e+00,
3792 0.7490229011e+00, -.6677658558e+00, 0.6196745634e+00, -.5591596961e+00,
3793 0.4905325770e+00, -.4393517375e+00, 0.4029803872e+00, -.3631100059e+00,
3794 0.3199430704e+00, -.2866140604e+00, 0.2627358437e+00, -.2368256450e+00};
3797 const double cc18[nterms] = {
3798 0.1000000000e+01, -.2777777612e-01, -.2246732125e-02, -.5571441725e-03,
3799 -.1790652314e-03, -.6708275760e-04, -.2766949183e-04, -.1219387286e-04,
3800 -.5640039490e-05, -.2706697160e-05, -.1337270078e-05, -.6763995657e-06,
3801 -.3488264610e-06, -.1828456675e-06, -.9718036154e-07, -.5227070332e-07};
3802 const double cc28[nterms] = {
3803 0.1362840652e+01, -.9286670089e+00, 0.1035511017e+01, -.9800255299e+00,
3804 0.8315343261e+00, -.7592730522e+00, 0.7612683773e+00, -.7132136226e+00,
3805 0.6074471474e+00, -.5554352999e+00, 0.5699443221e+00, -.5357525349e+00,
3806 0.4329345822e+00, -.3916820884e+00, 0.4401986003e+00, -.4197303057e+00};
3808 for (
int i = 0; i < nterms; ++i) {
3809 cc1[0][i] = cc13[i];
3810 cc2[0][i] = cc23[i];
3811 cc1[1][i] = cc14[i];
3812 cc2[1][i] = cc24[i];
3813 cc1[2][i] = cc15[i];
3814 cc2[2][i] = cc25[i];
3815 cc1[3][i] = cc16[i];
3816 cc2[3][i] = cc26[i];
3817 cc1[4][i] = cc17[i];
3818 cc2[4][i] = cc27[i];
3819 cc1[5][i] = cc18[i];
3820 cc2[5][i] = cc28[i];
3824void ComponentAnalyticField::Field3dA00(
const double xpos,
const double ypos,
3825 const double zpos,
double& ex,
3826 double& ey,
double& ez,
double& volt) {
3839 double exhelp, eyhelp, ezhelp, vhelp;
3842 ex = ey = ez = volt = 0.;
3845 for (
int i = 0; i < n3d; ++i) {
3847 const double dx = xpos - ch3d[i].x;
3848 const double dy = ypos - ch3d[i].y;
3849 const double dz = zpos - ch3d[i].z;
3850 const double r =
sqrt(dx * dx + dy * dy + dz * dz);
3851 if (
fabs(r) < Small)
continue;
3852 const double r3 =
pow(r, 3);
3858 double dxm = 0., dym = 0.;
3860 dxm = ch3d[i].x + xpos - 2 * coplax;
3861 const double rplan =
sqrt(dxm * dxm + dy * dy);
3862 if (
fabs(rplan) < Small)
continue;
3863 const double rplan3 =
pow(rplan, 3);
3864 exhelp += dxm / rplan3;
3865 eyhelp += dy / rplan3;
3866 ezhelp += dz / rplan3;
3867 vhelp -= 1. / rplan;
3871 dym = ch3d[i].y + ypos - 2. * coplay;
3872 const double rplan =
sqrt(dx * dx + dym * dym);
3873 if (
fabs(rplan) < Small)
continue;
3874 const double rplan3 =
pow(rplan, 3);
3875 exhelp += dx / rplan3;
3876 eyhelp += dym / rplan3;
3877 ezhelp += dz / rplan3;
3878 vhelp -= 1. / rplan;
3881 if (ynplax && ynplay) {
3882 const double rplan =
sqrt(dxm * dxm + dym * dym);
3883 if (
fabs(rplan) < Small)
continue;
3884 const double rplan3 =
pow(rplan, 3);
3885 exhelp -= dxm / rplan3;
3886 eyhelp -= dym / rplan3;
3887 ezhelp -= dz / rplan3;
3888 vhelp += 1. / rplan;
3891 ex -= ch3d[i].e * exhelp;
3892 ey -= ch3d[i].e * eyhelp;
3893 ez -= ch3d[i].e * ezhelp;
3894 volt += ch3d[i].e * vhelp;
3898void ComponentAnalyticField::Field3dB2X(
const double xpos,
const double ypos,
3899 const double zpos,
double& ex,
3900 double& ey,
double& ez,
double& volt) {
3911 const double rcut = 1.;
3913 double rr1, rr2, rm1, rm2, err, ezz;
3914 double exsum = 0., eysum = 0., ezsum = 0., vsum = 0.;
3915 double k0r, k1r, k0rm, k1rm;
3918 ex = ey = ez = volt = 0.;
3921 for (
int i = 0; i < n3d; ++i) {
3923 if (xpos == ch3d[i].x && ypos == ch3d[i].y && zpos == ch3d[i].z)
continue;
3924 const double dx = xpos - ch3d[i].x;
3925 const double dy = ypos - ch3d[i].y;
3926 const double dz = zpos - ch3d[i].z;
3927 const double dxm = xpos + ch3d[i].x - 2 * coplax;
3929 if (dy * dy + dz * dz >
pow(rcut * 2 * sx, 2)) {
3931 exsum = eysum = ezsum = vsum = 0.;
3933 for (
int j = 1; j <= nTermBessel; ++j) {
3935 const double rr = Pi * j *
sqrt(dy * dy + dz * dz) / sx;
3936 const double zzp = Pi * j * dx / sx;
3937 const double zzn = Pi * j * dxm / sx;
3947 const double czzp =
cos(zzp);
3948 const double czzn =
cos(zzn);
3949 vsum += (1. / sx) * k0r * (czzp - czzn);
3950 err = (TwoPi * j / (sx * sx)) * k1r * (czzp - czzn);
3951 ezz = (TwoPi * j / (sx * sx)) * k0r * (
sin(zzp) -
sin(zzn));
3953 eysum += err * dy /
sqrt(dy * dy + dz * dz);
3954 ezsum += err * dz /
sqrt(dy * dy + dz * dz);
3960 for (
int j = 0; j <= nTermPoly; ++j) {
3962 rr1 =
sqrt(
pow(dx + j * 2 * sx, 2) + dy * dy + dz * dz);
3963 rr2 =
sqrt(
pow(dx - j * 2 * sx, 2) + dy * dy + dz * dz);
3964 rm1 =
sqrt(
pow(dxm - j * 2 * sx, 2) + dy * dy + dz * dz);
3965 rm2 =
sqrt(
pow(dxm + j * 2 * sx, 2) + dy * dy + dz * dz);
3966 const double rr13 =
pow(rr1, 3);
3967 const double rm13 =
pow(rm1, 3);
3970 vsum = 1. / rr1 - 1. / rm1;
3971 exsum = dx / rr13 - dxm / rm13;
3972 eysum = dy * (1. / rr13 - 1. / rm13);
3973 ezsum = dz * (1. / rr13 - 1. / rm13);
3976 const double rr23 =
pow(rr2, 3);
3977 const double rm23 =
pow(rm2, 3);
3979 vsum += 1. / rr1 + 1. / rr2 - 1. / rm1 - 1. / rm2;
3980 exsum += (dx + j * 2 * sx) / rr13 + (dx - j * 2 * sx) / rr23 -
3981 (dxm - j * 2 * sx) / rm13 - (dxm + j * 2 * sx) / rm23;
3982 eysum += dy * (1. / rr13 + 1. / rr23 - 1. / rm13 - 1. / rm23);
3983 ezsum += dz * (1. / rr13 + 1. / rr23 - 1. / rm13 - 1. / rm23);
3988 const double dym = ypos + ch3d[i].y - 2. * coplay;
3989 if (dym * dym + dz * dz >
pow(rcut * 2 * sx, 2)) {
3992 for (
int j = 1; j <= nTermBessel; ++j) {
3994 const double rrm = Pi * j *
sqrt(dym * dym + dz * dz) / sx;
3995 const double zzp = Pi * j * dx / sx;
3996 const double zzn = Pi * j * dxm / sx;
4006 const double czzp =
cos(zzp);
4007 const double czzn =
cos(zzn);
4008 vsum += (1. / sx) * k0rm * (czzp - czzn);
4009 err = (TwoPi / (sx * sx)) * k1rm * (czzp - czzn);
4010 ezz = (TwoPi / (sx * sx)) * k0rm * (
sin(zzp) -
sin(zzn));
4012 eysum += err * dym /
sqrt(dym * dym + dz * dz);
4013 ezsum += err * dz /
sqrt(dym * dym + dz * dz);
4018 for (
int j = 0; j <= nTermPoly; ++j) {
4020 rr1 =
sqrt(
pow(dx + j * 2 * sx, 2) + dym * dym + dz * dz);
4021 rr2 =
sqrt(
pow(dx - j * 2 * sx, 2) + dym * dym + dz * dz);
4022 rm1 =
sqrt(
pow(dxm - j * 2 * sx, 2) + dym * dym + dz * dz);
4023 rm2 =
sqrt(
pow(dxm + j * 2 * sx, 2) + dym * dym + dz * dz);
4024 const double rr13 =
pow(rr1, 3);
4025 const double rm13 =
pow(rm1, 3);
4028 vsum += -1. / rr1 + 1. / rm1;
4029 exsum += -dx / rr13 + dxm / rm13;
4030 eysum += -dym * (1. / rr13 - 1. / rm13);
4031 ezsum += -dz * (1. / rr13 - 1. / rm13);
4034 const double rr23 =
pow(rr2, 3);
4035 const double rm23 =
pow(rm2, 3);
4037 vsum += -1. / rr1 - 1. / rr2 + 1. / rm1 + 1. / rm2;
4038 exsum += -(dx + j * 2 * sx) / rr13 - (dx - j * 2 * sx) / rr23 +
4039 (dxm - j * 2 * sx) / rm13 + (dxm + j * 2 * sx) / rm23;
4040 eysum += -dym * (1. / rr13 + 1. / rr23 - 1. / rm13 - 1. / rm23);
4041 ezsum += -dz * (1. / rr13 + 1. / rr23 - 1. / rm13 - 1. / rm23);
4045 ex += ch3d[i].e * exsum;
4046 ey += ch3d[i].e * eysum;
4047 ez += ch3d[i].e * ezsum;
4048 volt += ch3d[i].e * vsum;
4052void ComponentAnalyticField::Field3dB2Y(
const double xpos,
const double ypos,
4053 const double zpos,
double& ex,
4054 double& ey,
double& ez,
double& volt) {
4065 const double rcut = 1.;
4067 double rr1, rr2, rm1, rm2, err, ezz;
4068 double exsum = 0., eysum = 0., ezsum = 0., vsum = 0.;
4069 double k0r, k1r, k0rm, k1rm;
4072 ex = ey = ez = volt = 0.;
4075 for (
int i = n3d; i--;) {
4077 if (xpos == ch3d[i].x && ypos == ch3d[i].y && zpos == ch3d[i].z)
continue;
4078 const double dx = xpos - ch3d[i].x;
4079 const double dy = ypos - ch3d[i].y;
4080 const double dz = zpos - ch3d[i].z;
4081 const double dym = ypos + ch3d[i].y - 2 * coplay;
4083 if (dx * dx + dz * dz >
pow(rcut * 2 * sy, 2)) {
4085 exsum = eysum = ezsum = vsum = 0.;
4087 for (
int j = 1; j <= nTermBessel; ++j) {
4089 const double rr = Pi * j *
sqrt(dx * dx + dz * dz) / sy;
4090 const double zzp = Pi * j * dy / sy;
4091 const double zzn = Pi * j * dym / sy;
4101 const double czzp =
cos(zzp);
4102 const double czzn =
cos(zzn);
4103 vsum += (1. / sy) * k0r * (czzp - czzn);
4104 err = (TwoPi * j / (sy * sy)) * k1r * (czzp - czzn);
4105 ezz = (TwoPi * j / (sy * sy)) * k0r * (
sin(zzp) -
sin(zzn));
4106 exsum += err * dx /
sqrt(dx * dx + dz * dz);
4107 ezsum += err * dz /
sqrt(dx * dx + dz * dz);
4114 for (
int j = 0; j <= nTermPoly; ++j) {
4116 rr1 =
sqrt(dx * dx + dz * dz +
pow(dy + j * 2 * sy, 2));
4117 rr2 =
sqrt(dx * dx + dz * dz +
pow(dy - j * 2 * sy, 2));
4118 rm1 =
sqrt(dx * dx + dz * dz +
pow(dym - j * 2 * sy, 2));
4119 rm2 =
sqrt(dx * dx + dz * dz +
pow(dym + j * 2 * sy, 2));
4120 const double rr13 =
pow(rr1, 3);
4121 const double rm13 =
pow(rm1, 3);
4124 vsum = 1. / rr1 - 1. / rm1;
4125 exsum = dx * (1. / rr13 - 1. / rm13);
4126 ezsum = dz * (1. / rr13 - 1. / rm13);
4127 eysum = dy / rr13 - dym / rm13;
4131 const double rr23 =
pow(rr2, 3);
4132 const double rm23 =
pow(rm2, 3);
4133 vsum += 1. / rr1 + 1. / rr2 - 1. / rm1 - 1. / rm2;
4134 exsum += dx * (1. / rr13 + 1. / rr23 - 1. / rm13 - 1. / rm23);
4135 ezsum += dz * (1. / rr13 + 1. / rr23 - 1. / rm13 - 1. / rm23);
4136 eysum += (dy + j * 2 * sy) / rr13 + (dy - j * 2 * sy) / rr23 -
4137 (dym - j * 2 * sy) / rm13 - (dym + j * 2 * sy) / rm23;
4142 const double dxm = xpos + ch3d[i].x - 2. * coplax;
4143 if (dxm * dxm + dz * dz >
pow(rcut * 2 * sy, 2)) {
4146 for (
int j = 1; j <= nTermBessel; ++j) {
4148 const double rrm = Pi * j *
sqrt(dxm * dxm + dz * dz) / sy;
4149 const double zzp = Pi * j * dy / sy;
4150 const double zzn = Pi * j * dym / sy;
4160 const double czzp =
cos(zzp);
4161 const double czzn =
cos(zzn);
4162 vsum += (1. / sy) * k0rm * (czzp - czzn);
4163 err = (TwoPi / (sy * sy)) * k1rm * (czzp - czzn);
4164 ezz = (TwoPi / (sy * sy)) * k0rm * (
sin(zzp) -
sin(zzn));
4165 exsum += err * dxm /
sqrt(dxm * dxm + dz * dz);
4166 ezsum += err * dz /
sqrt(dxm * dxm + dz * dz);
4172 for (
int j = 0; j <= nTermPoly; ++j) {
4174 rr1 =
sqrt(
pow(dy + j * 2 * sy, 2) + dxm * dxm + dz * dz);
4175 rr2 =
sqrt(
pow(dy - j * 2 * sy, 2) + dxm * dxm + dz * dz);
4176 rm1 =
sqrt(
pow(dym - j * 2 * sy, 2) + dxm * dxm + dz * dz);
4177 rm2 =
sqrt(
pow(dym + j * 2 * sy, 2) + dxm * dxm + dz * dz);
4178 const double rr13 =
pow(rr1, 3);
4179 const double rm13 =
pow(rm1, 3);
4182 vsum += -1. / rr1 + 1. / rm1;
4183 exsum += -dxm * (1. / rr13 - 1. / rm13);
4184 ezsum += -dz * (1. / rr13 - 1. / rm13);
4185 eysum += -dy / rr13 + dym / rm13;
4188 const double rr23 =
pow(rr2, 3);
4189 const double rm23 =
pow(rm2, 3);
4191 vsum += -1. / rr1 - 1. / rr2 + 1. / rm1 + 1. / rm2;
4192 exsum += -dxm * (1. / rr13 + 1. / rr23 - 1. / rm13 - 1. / rm23);
4193 ezsum += -dz * (1. / rr13 + 1. / rr23 - 1. / rm13 - 1. / rm23);
4194 eysum += -(dy + j * 2 * sy) / rr13 - (dy - j * 2 * sy) / rr23 +
4195 (dym - j * 2 * sy) / rm13 + (dym + j * 2 * sy) / rm23;
4199 ex += ch3d[i].e * exsum;
4200 ey += ch3d[i].e * eysum;
4201 ez += ch3d[i].e * ezsum;
4202 volt += ch3d[i].e * vsum;
4206void ComponentAnalyticField::Field3dD10(
const double xxpos,
const double yypos,
4207 const double zzpos,
double& eex,
4208 double& eey,
double& eez,
4220 const double rcut = 1.;
4222 double x3d, y3d, z3d;
4223 double exsum = 0., eysum = 0., ezsum = 0., vsum = 0.;
4224 double rr1, rr2, rm1, rm2, err, ezz;
4228 eex = eey = eez = volt = 0.;
4229 double ex = 0., ey = 0., ez = 0.;
4234 std::cerr <<
" Inappropriate potential function.\n";
4239 const double ssx = log(2. * cotube / w[0].d);
4240 const double cpl = log(w[0].d / 2.);
4243 const double xpos = 0.5 * log(xxpos * xxpos + yypos * yypos);
4244 const double ypos = atan2(yypos, xxpos);
4245 const double zpos = zzpos;
4248 for (
int i = 0; i < n3d; ++i) {
4249 for (
int ii = -1; ii <= 1; ++ii) {
4250 x3d = 0.5 * log(ch3d[i].x * ch3d[i].x + ch3d[i].y * ch3d[i].y);
4251 y3d = atan2(ch3d[i].y, ch3d[i].x + ii * TwoPi);
4253 const double dx = xpos - x3d;
4254 const double dy = ypos - y3d;
4255 const double dz = zpos - z3d;
4256 const double dxm = xpos + x3d - 2 * cpl;
4258 if (xpos == x3d && ypos == y3d && zpos == z3d)
continue;
4260 if (dy * dy + dz * dz >
pow(rcut * 2 * ssx, 2)) {
4262 exsum = eysum = ezsum = vsum = 0.;
4264 for (
int j = 1; j <= nTermBessel; ++j) {
4266 const double rr = Pi * j *
sqrt(dy * dy + dz * dz) / ssx;
4267 const double zzp = Pi * j * dx / ssx;
4268 const double zzn = Pi * j * dxm / ssx;
4278 const double czzp =
cos(zzp);
4279 const double czzn =
cos(zzn);
4280 vsum += (1. / ssx) * k0r * (czzp - czzn);
4281 err = (j * TwoPi / (ssx * ssx)) * k1r * (czzp - czzn);
4282 ezz = (j * TwoPi / (ssx * ssx)) * k0r * (
sin(zzp) -
sin(zzn));
4284 eysum += err * dy /
sqrt(dy * dy + dz * dz);
4285 ezsum += err * dz /
sqrt(dy * dy + dz * dz);
4290 for (
int j = 0; j < nTermPoly; ++j) {
4292 rr1 =
sqrt(
pow(dx + j * 2 * ssx, 2) + dy * dy + dz * dz);
4293 rr2 =
sqrt(
pow(dx - j * 2 * ssx, 2) + dy * dy + dz * dz);
4294 rm1 =
sqrt(
pow(dxm - j * 2 * ssx, 2) + dy * dy + dz * dz);
4295 rm2 =
sqrt(
pow(dxm + j * 2 * ssx, 2) + dy * dy + dz * dz);
4296 const double rr13 =
pow(rr1, 3);
4297 const double rm13 =
pow(rm1, 3);
4300 vsum = 1. / rr1 - 1. / rm1;
4301 exsum = dxm / rr13 - dxm / rm13;
4302 eysum = dy * (1. / rr13 - 1. / rm13);
4303 ezsum = dz * (1. / rr13 - 1. / rm13);
4306 const double rr23 =
pow(rr2, 3);
4307 const double rm23 =
pow(rm2, 3);
4309 vsum += 1. / rr1 + 1. / rr2 - 1. / rm1 - 1. / rm2;
4310 exsum += (dx + j * 2 * ssx) / rr13 + (dx - j * 2 * ssx) / rr23 -
4311 (dxm - j * 2 * ssx) / rm13 - (dxm + j * 2 * ssx) / rm23;
4312 eysum += dy * (1. / rr13 + 1. / rr23 - 1. / rm13 - 1. / rm23);
4313 ezsum += dz * (1. / rr13 + 1. / rr23 - 1. / rm13 - 1. / rm23);
4316 ex += ch3d[i].e * exsum;
4317 ey += ch3d[i].e * eysum;
4318 ez += ch3d[i].e * ezsum;
4324 eex =
exp(-xpos) * (ex *
cos(ypos) - ey *
sin(ypos));
4325 eey =
exp(-ypos) * (ex *
sin(ypos) + ey *
cos(ypos));
4329bool ComponentAnalyticField::PrepareSignals() {
4336 if (nReadout <= 0) {
4337 std::cerr <<
m_className <<
"::PrepareSignals:\n";
4338 std::cerr <<
" There are no readout groups defined.\n";
4339 std::cerr <<
" Calculation of weighting fields makes no sense.\n";
4345 std::cerr <<
m_className <<
"::PrepareSignals:\n";
4346 std::cerr <<
" Cell could not be set up.\n";
4347 std::cerr <<
" No calculation of weighting fields possible.\n";
4354 if (nFourier == 0) {
4355 cellTypeFourier = cellType;
4356 }
else if (cellType ==
"A " || cellType ==
"B1X" || cellType ==
"B1Y" ||
4357 cellType ==
"C1 ") {
4358 cellTypeFourier =
"A ";
4359 }
else if (cellType ==
"B2X" || cellType ==
"C2X") {
4360 cellTypeFourier =
"B2X";
4361 }
else if (cellType ==
"B2Y" || cellType ==
"C2Y") {
4362 cellTypeFourier =
"B2Y";
4363 }
else if (cellType ==
"C3 ") {
4364 cellTypeFourier =
"C3 ";
4365 }
else if (cellType ==
"D1 ") {
4366 cellTypeFourier =
"D1 ";
4367 }
else if (cellType ==
"D3 ") {
4368 cellTypeFourier =
"D3 ";
4371 std::cerr <<
m_className <<
"::PrepareSignals:\n";
4372 std::cerr <<
" No potentials available to handle cell type " << cellType
4378 fperx = fpery =
false;
4379 if (nFourier == 0) {
4382 if (cellType ==
"B1X" || cellType ==
"C1 " || cellType ==
"C2Y") {
4385 if (cellType ==
"B1Y" || cellType ==
"C1 " || cellType ==
"C2X") {
4388 mfexp = int(0.1 + log(1. * nFourier) / log(2.));
4390 fperx = fpery =
false;
4394 mxmin = mymin = mxmax = mymax = 0;
4396 mxmin = std::min(0, 1 - nFourier / 2);
4397 mxmax = nFourier / 2;
4400 mymin = std::min(0, 1 - nFourier / 2);
4401 mymax = nFourier / 2;
4406 std::cout <<
m_className <<
"::PrepareSignals:\n";
4407 std::cout <<
" Cell type: " << cellType <<
"\n";
4408 std::cout <<
" Fourier cell type: " << cellTypeFourier <<
"\n";
4409 std::cout <<
" x convolutions: " << fperx <<
"\n";
4410 std::cout <<
" y convolutions: " << fpery <<
"\n";
4411 std::cout <<
" No of Fourier terms: " << nFourier <<
" (= 2**" << mfexp
4416 if (!SetupWireSignals()) {
4417 std::cerr <<
m_className <<
"::PrepareSignals:\n";
4418 std::cerr <<
" Preparing wire signal capacitance matrices failed.\n";
4422 if (!SetupPlaneSignals()) {
4423 std::cerr <<
m_className <<
"::PrepareSignals:\n";
4424 std::cerr <<
" Preparing plane charges failed.\n";
4434 for (
int i = 0; i < nReadout; ++i) {
4435 for (
int j = 0; j < nWires; ++j) {
4436 if (w[j].type == readout[i]) w[j].ind = i;
4438 for (
int j = 0; j < 5; ++j) {
4439 if (planes[j].type == readout[i]) planes[j].ind = i;
4440 for (
int k = 0; k < planes[j].nStrips1; ++k) {
4441 if (planes[j].strips1[k].type == readout[i]) {
4442 planes[j].strips1[i].ind = i;
4445 for (
int k = 0; k < planes[j].nStrips2; ++k) {
4446 if (planes[j].strips2[k].type == readout[i]) {
4447 planes[j].strips2[i].ind = i;
4458bool ComponentAnalyticField::SetupWireSignals() {
4472 sigmat.resize(nWires);
4473 for (
int i = 0; i < nWires; ++i) {
4475 sigmat[i].resize(nWires);
4478 std::vector<std::vector<std::complex<double> > > fftmat;
4481 if (fperx || fpery) {
4482 fftmat.resize(nFourier);
4483 for (
int i = 0; i < nFourier; ++i) {
4484 fftmat[i].resize(nWires);
4488 if (fperx || fpery) {
4499 for (
int mx = mxmin; mx <= mxmax; ++mx) {
4500 for (
int my = mymin; my <= mymax; ++my) {
4502 if (cellTypeFourier ==
"A ") {
4504 }
else if (cellTypeFourier ==
"B2X") {
4506 }
else if (cellTypeFourier ==
"B2Y") {
4508 }
else if (cellTypeFourier ==
"C2X") {
4510 }
else if (cellTypeFourier ==
"C2Y") {
4512 }
else if (cellTypeFourier ==
"D1 ") {
4514 }
else if (cellTypeFourier ==
"D3 ") {
4517 std::cerr <<
m_className <<
"::SetupWireSignals:\n";
4518 std::cerr <<
" Unknown signal cell type " << cellTypeFourier <<
"\n";
4522 std::cout <<
m_className <<
"::SetupWireSignals:\n";
4523 std::cout <<
" Signal matrix MX = " << mx <<
", MY = " << my
4524 <<
" has been calculated.\n";
4526 if (fperx || fpery) {
4534 std::cout <<
m_className <<
"::SetupWireSignals:\n";
4535 std::cout <<
" Dump of signal matrix (" << mx <<
", " << my
4536 <<
") before inversion:\n";
4537 for (
int i = 0; i < nWires; i += 10) {
4538 for (
int j = 0; j < nWires; j += 10) {
4539 std::cout <<
" (Re-Block " << i / 10 <<
", " << j / 10 <<
")\n";
4540 for (
int ii = 0; ii < 10; ++ii) {
4541 if (i + ii >= nWires)
break;
4542 for (
int jj = 0; jj < 10; ++jj) {
4543 if (j + jj >= nWires)
break;
4544 std::cout << real(sigmat[i + ii][j + jj]) <<
" ";
4549 std::cout <<
" (Im-Block " << i / 10 <<
", " << j / 10 <<
")\n";
4550 for (
int ii = 0; ii < 10; ++ii) {
4551 if (i + ii >= nWires)
break;
4552 for (
int jj = 0; jj < 10; ++jj) {
4553 if (j + jj >= nWires)
break;
4554 std::cout << imag(sigmat[i + ii][j + jj]) <<
" ";
4561 std::cout <<
m_className <<
"::SetupWireSignals:\n";
4562 std::cout <<
" End of the uninverted capacitance matrix dump.\n";
4569 if ((fperx && !fpery) || (fpery && !fperx)) {
4570 for (
int i = 0; i < nWires; ++i) {
4571 for (
int m = -nFourier / 2; m < nFourier / 2; ++m) {
4574 for (
int j = 0; j < nWires; ++j) {
4575 fftmat[m + nFourier / 2][j] = sigmat[i][j];
4578 for (
int j = 0; j < nWires; ++j) {
4581 for (
int m = -nFourier / 2; m < nFourier / 2; ++m) {
4584 for (
int j = 0; j < nWires; ++j) {
4585 sigmat[i][j] = fftmat[m + nFourier / 2][j];
4593 if (fperx || fpery) {
4594 for (
int i = 0; i < nWires; ++i) {
4595 for (
int mx = mxmin; mx <= mxmax; ++mx) {
4596 for (
int my = mymin; my <= mymax; ++my) {
4599 for (
int j = 0; j < nWires; ++j) {
4600 fftmat[my + nFourier / 2 - 1][j] = sigmat[i][j];
4603 for (
int j = 0; j < nWires; ++j) {
4606 for (
int my = mymin; my <= mymax; ++my) {
4609 for (
int j = 0; j < nWires; ++j) {
4610 sigmat[i][j] = fftmat[my + nFourier / 2 - 1][j];
4616 for (
int my = mymin; my <= mymax; ++my) {
4617 for (
int mx = mxmin; mx <= mxmax; ++mx) {
4620 for (
int j = 0; j < nWires; ++j) {
4621 fftmat[mx + nFourier / 2 - 1][j] = sigmat[i][j];
4624 for (
int j = 0; j < nWires; ++j) {
4627 for (
int mx = mxmin; mx <= mxmax; ++mx) {
4630 for (
int j = 0; j < nWires; ++j) {
4631 sigmat[i][j] = fftmat[mx + nFourier / 2 - 1][j];
4641 for (
int mx = mxmin; mx <= mxmax; ++mx) {
4642 for (
int my = mymin; my <= mymax; ++my) {
4644 if (fperx || fpery) {
4653 std::cerr <<
m_className <<
"::PrepareWireSignals:\n";
4654 std::cerr <<
" Inversion of signal matrix (" << mx <<
", " << my
4656 std::cerr <<
" No reliable results.\n";
4657 std::cerr <<
" Preparation of weighting fields is abandoned.\n";
4662 if (fperx || fpery) {
4671 if ((fperx && !fpery) || (fpery && !fperx)) {
4672 for (
int i = 0; i < nWires; ++i) {
4673 for (
int m = -nFourier / 2; m < nFourier / 2; ++m) {
4676 for (
int j = 0; j < nWires; ++j) {
4677 fftmat[m + nFourier / 2][j] = sigmat[i][j];
4680 for (
int j = 0; j < nWires; ++j) {
4683 for (
int m = -nFourier / 2; m < nFourier / 2; ++m) {
4686 for (
int j = 0; j < nWires; ++j) {
4687 sigmat[i][j] = fftmat[m + nFourier / 2][j] / double(nFourier);
4695 if (fperx && fpery) {
4696 for (
int i = 0; i < nWires; ++i) {
4697 for (
int mx = mxmin; mx <= mxmax; ++mx) {
4698 for (
int my = mymin; my <= mymax; ++my) {
4701 for (
int j = 0; j < nWires; ++j) {
4702 fftmat[my + nFourier / 2 - 1][j] = sigmat[i][j];
4705 for (
int j = 0; j < nWires; ++j) {
4708 for (
int my = mymin; my <= mymax; ++my) {
4711 for (
int j = 0; j < nWires; ++j) {
4712 sigmat[i][j] = fftmat[my + nFourier / 2 - 1][j] / double(nFourier);
4718 for (
int my = mymin; my <= mymax; ++my) {
4719 for (
int mx = mxmin; mx <= mxmax; ++mx) {
4722 for (
int j = 0; j < nWires; ++j) {
4723 fftmat[mx + nFourier / 2 - 1][j] = sigmat[i][j];
4726 for (
int j = 0; j < nWires; ++j) {
4729 for (
int mx = mxmin; mx <= mxmax; ++mx) {
4732 for (
int j = 0; j < nWires; ++j) {
4733 sigmat[i][j] = fftmat[mx + nFourier / 2 - 1][j] / double(nFourier);
4744 for (
int mx = mxmin; mx <= mxmax; ++mx) {
4745 for (
int my = mymin; my <= mymax; ++my) {
4746 std::cout <<
m_className <<
"::SetupWireSignals:\n";
4747 std::cout <<
" Dump of signal matrix (" << mx <<
", " << my
4748 <<
") after inversion:\n";
4749 for (
int i = 0; i < nWires; i += 10) {
4750 for (
int j = 0; j < nWires; j += 10) {
4751 std::cout <<
" (Re-Block " << i / 10 <<
", " << j / 10 <<
")\n";
4752 for (
int ii = 0; ii < 10; ++ii) {
4753 if (i + ii >= nWires)
break;
4754 for (
int jj = 0; jj < 10; ++jj) {
4755 if (j + jj >= nWires)
break;
4756 std::cout << real(sigmat[i + ii][j + jj]) <<
" ";
4761 std::cout <<
" (Im-Block " << i / 10 <<
", " << j / 10 <<
")\n";
4762 for (
int ii = 0; ii < 10; ++ii) {
4763 if (i + ii >= nWires)
break;
4764 for (
int jj = 0; jj < 10; ++jj) {
4765 if (j + jj >= nWires)
break;
4766 std::cout << imag(sigmat[i + ii][j + jj]) <<
" ";
4773 std::cout <<
m_className <<
"::SetupWireSignals:\n";
4774 std::cout <<
" End of the inverted capacitance matrix dump.\n";
4781bool ComponentAnalyticField::SetupPlaneSignals() {
4789 const int nPlanes = 5;
4790 qplane.resize(nPlanes);
4791 for (
int i = 0; i < nPlanes; ++i) {
4792 qplane[i].resize(nWires);
4798 for (
int mx = mxmin; mx <= mxmax; ++mx) {
4799 for (
int my = mymin; my <= mymax; ++my) {
4808 for (
int i = 0; i < 5; ++i) {
4809 for (
int j = 0; j < nWires; ++j) qplane[i][j] = 0.;
4814 for (
int i = 0; i < nWires; ++i) {
4816 vw = -(coplan[1] - w[i].x) / (coplan[1] - coplan[0]);
4818 vw = -(coplan[0] + sx - w[i].x) / sx;
4823 for (
int j = 0; j < nWires; ++j) {
4824 qplane[0][j] += real(sigmat[i][j]) * vw;
4831 for (
int i = 0; i < nWires; ++i) {
4833 vw = -(coplan[0] - w[i].x) / (coplan[0] - coplan[1]);
4835 vw = -(w[i].x - coplan[1] + sx) / sx;
4840 for (
int j = 0; j < nWires; ++j) {
4841 qplane[1][j] += real(sigmat[i][j]) * vw;
4848 for (
int i = 0; i < nWires; ++i) {
4850 vw = -(coplan[3] - w[i].y) / (coplan[3] - coplan[2]);
4852 vw = -(coplan[2] + sy - w[i].y) / sy;
4857 for (
int j = 0; j < nWires; ++j) {
4858 qplane[2][i] += real(sigmat[i][j]) * vw;
4865 for (
int i = 0; i < nWires; ++i) {
4867 vw = -(coplan[2] - w[i].y) / (coplan[2] - coplan[3]);
4869 vw = -(w[i].y - coplan[3] + sy) / sy;
4874 for (
int j = 0; j < nWires; ++j) {
4875 qplane[3][i] += real(sigmat[i][j]) * vw;
4881 for (
int i = 0; i < nWires; ++i) {
4882 for (
int j = 0; j < nWires; ++j) {
4883 qplane[4][i] -= real(sigmat[i][j]);
4898 if (ynplan[0] && ynplan[1]) {
4899 planes[0].ewxcor = 1. / (coplan[1] - coplan[0]);
4900 planes[1].ewxcor = 1. / (coplan[0] - coplan[1]);
4901 }
else if (ynplan[0] && perx) {
4902 planes[0].ewxcor = 1. / sx;
4903 planes[1].ewxcor = 0.;
4904 }
else if (ynplan[1] && perx) {
4905 planes[0].ewxcor = 0.;
4906 planes[1].ewxcor = -1. / sx;
4908 planes[0].ewxcor = planes[1].ewxcor = 0.;
4910 planes[2].ewxcor = planes[3].ewxcor = planes[4].ewxcor = 0.;
4912 planes[0].ewycor = planes[1].ewycor = 0.;
4913 if (ynplan[2] && ynplan[3]) {
4914 planes[2].ewycor = 1. / (coplan[3] - coplan[2]);
4915 planes[3].ewycor = 1. / (coplan[2] - coplan[3]);
4916 }
else if (ynplan[2] && pery) {
4917 planes[2].ewycor = 1. / sy;
4918 planes[3].ewycor = 0.;
4919 }
else if (ynplan[3] && pery) {
4920 planes[2].ewycor = 0.;
4921 planes[3].ewycor = -1. / sy;
4923 planes[2].ewycor = planes[3].ewycor = 0.;
4926 planes[4].ewycor = 0.;
4930 std::cout <<
m_className <<
"::SetupPlaneSignals:\n";
4931 std::cout <<
" Charges for currents induced in the planes:\n";
4932 std::cout <<
" Wire x-Plane 1 x-Plane 2"
4933 <<
" y-Plane 1 y-Plane 2"
4935 for (
int i = 0; i < nWires; ++i) {
4936 std::cout <<
" " << i <<
" " << qplane[0][i] <<
" " << qplane[1][i]
4937 <<
" " << qplane[2][i] <<
" " << qplane[3][i] <<
" "
4938 << qplane[4][i] <<
"\n";
4940 std::cout <<
m_className <<
"::SetupPlaneSignals:\n";
4941 std::cout <<
" Bias fields:\n";
4942 std::cout <<
" Plane x-Bias [1/cm] y-Bias [1/cm]\n";
4943 for (
int i = 0; i < 4; ++i) {
4944 std::cout <<
" " << i <<
" " << planes[i].ewxcor <<
" "
4945 << planes[i].ewycor <<
"\n";
4952bool ComponentAnalyticField::IprA00(
const int mx,
const int my) {
4959 const double dx = mx * sx;
4960 const double dy = my * sy;
4963 for (
int i = 0; i < nWires; ++i) {
4965 if (dx != 0. || dy != 0.) {
4966 aa = dx * dx + dy * dy;
4968 aa = 0.25 * w[i].d * w[i].d;
4971 if (ynplax) aa /= 2. *
pow(w[i].x - coplax, 2) + dy * dy;
4972 if (ynplay) aa /= 2. *
pow(w[i].y - coplay, 2) + dx * dx;
4974 if (ynplax && ynplay)
4975 aa *= 4. * (
pow(w[i].x - coplax, 2) +
pow(w[i].y - coplay, 2));
4977 sigmat[i][i] = -0.5 * log(aa);
4978 for (
int j = i + 1; j < nWires; ++j) {
4979 aa =
pow(w[i].x + dx - w[j].x, 2) +
pow(w[i].y + dy - w[j].y, 2);
4982 aa /=
pow(2. * coplax - w[i].x - dx - w[j].x, 2) +
4983 pow(w[i].y + dy - w[j].y, 2);
4985 aa /=
pow(w[i].x + dx - w[j].x, 2) +
4986 pow(2. * coplay - w[i].y - dy - w[j].y, 2);
4988 if (ynplax && ynplay) {
4989 aa *=
pow(2. * coplax - w[i].x - dx - w[j].x, 2) +
4990 pow(2. * coplay - w[i].y - dy - w[j].y, 2);
4993 sigmat[i][j] = -0.5 * log(aa);
4994 sigmat[j][i] = sigmat[i][j];
5000bool ComponentAnalyticField::IprB2X(
const int my) {
5008 b2sin.resize(nWires);
5010 const double dy = my * sy;
5012 double xx, yy, xxneg, yymirr;
5015 for (
int i = 0; i < nWires; ++i) {
5016 xx = (Pi / sx) * (w[i].x - coplan[0]);
5018 aa =
pow(sinh(Pi * dy / sx) /
sin(xx), 2);
5020 aa =
pow((0.25 * w[i].d * Pi / sx) /
sin(xx), 2);
5024 yymirr = (Pi / sx) * (w[i].y - coplay);
5025 if (
fabs(yymirr) <= 20.) {
5026 aa *= (
pow(sinh(yymirr), 2) +
pow(
sin(xx), 2)) /
pow(sinh(yymirr), 2);
5030 sigmat[i][i] = -0.5 * log(aa);
5032 for (
int j = i + 1; j < nWires; ++j) {
5033 yy = HalfPi * (w[i].y + dy - w[j].y) / sx;
5034 xx = HalfPi * (w[i].x - w[j].x) / sx;
5035 xxneg = HalfPi * (w[i].x + w[j].x - 2. * coplan[0]) / sx;
5036 if (
fabs(yy) <= 20.) {
5037 aa = (
pow(sinh(yy), 2) +
pow(
sin(xx), 2)) /
5038 (
pow(sinh(yy), 2) +
pow(
sin(xxneg), 2));
5044 yymirr = HalfPi * (w[i].y + w[j].y - 2. * coplay) / sx;
5045 if (
fabs(yymirr) <= 20.) {
5046 aa *= (
pow(sinh(yymirr), 2) +
pow(
sin(xxneg), 2)) /
5047 (
pow(sinh(yymirr), 2) +
pow(
sin(xx), 2));
5051 sigmat[i][j] = -0.5 * log(aa);
5052 sigmat[j][i] = sigmat[i][j];
5055 b2sin[i] =
sin(Pi * (coplan[0] - w[i].x) / sx);
5061bool ComponentAnalyticField::IprB2Y(
const int mx) {
5069 b2sin.resize(nWires);
5071 const double dx = mx * sx;
5073 double xx, yy, xxmirr, yyneg;
5076 for (
int i = 0; i < nWires; ++i) {
5077 yy = (Pi / sy) * (w[i].y - coplan[2]);
5079 aa =
pow(sinh(Pi * dx / sy) /
sin(yy), 2);
5081 aa =
pow((0.25 * w[i].d * Pi / sy) /
sin(yy), 2);
5085 xxmirr = (Pi / sy) * (w[i].x - coplax);
5086 if (
fabs(xxmirr) <= 20.) {
5087 aa *= (
pow(sinh(xxmirr), 2) +
pow(
sin(yy), 2)) /
pow(sinh(xxmirr), 2);
5091 sigmat[i][i] = -0.5 * log(aa);
5093 for (
int j = i + 1; j < nWires; ++j) {
5094 xx = HalfPi * (w[i].x + dx - w[j].x) / sy;
5095 yy = HalfPi * (w[i].y - w[j].y) / sy;
5096 yyneg = HalfPi * (w[i].y + w[j].y - 2. * coplan[2]) / sy;
5097 if (
fabs(xx) <= 20.) {
5098 aa = (
pow(sinh(xx), 2) +
pow(
sin(yy), 2)) /
5099 (
pow(sinh(xx), 2) +
pow(
sin(yyneg), 2));
5105 xxmirr = HalfPi * (w[i].x + w[j].x - 2. * coplax) / sy;
5106 if (
fabs(xxmirr) <= 20.) {
5107 aa *= (
pow(sinh(xxmirr), 2) +
pow(
sin(yyneg), 2)) /
5108 (
pow(sinh(xxmirr), 2) +
pow(
sin(yy), 2));
5112 sigmat[i][j] = -0.5 * log(aa);
5113 sigmat[j][i] = sigmat[i][j];
5116 b2sin[i] =
sin(Pi * (coplan[2] - w[i].y) / sy);
5121bool ComponentAnalyticField::IprC2X() {
5133 for (
int i = 0; i < nWires; ++i) {
5134 double cx = coplax - sx * int(round((coplax - w[i].x) / sx));
5135 for (
int j = 0; j < nWires; ++j) {
5138 temp = (w[i].x - cx) * (w[j].x - cx) * TwoPi / (sx * sy);
5142 Ph2Lim(0.5 * w[i].d) - Ph2(2. * (w[j].x - cx), 0.) - temp;
5144 sigmat[i][j] = Ph2(w[i].x - w[j].x, w[i].y - w[j].y) -
5145 Ph2(w[i].x + w[j].x - 2. * cx, w[i].y - w[j].y) - temp;
5152bool ComponentAnalyticField::IprC2Y() {
5164 for (
int i = 0; i < nWires; ++i) {
5165 double cy = coplay - sy * int(round((coplay - w[i].y) / sy));
5166 for (
int j = 0; j < nWires; ++j) {
5169 temp = (w[i].y - cy) * (w[j].y - cy) * TwoPi / (sx * sy);
5173 Ph2Lim(0.5 * w[i].d) - Ph2(0., 2. * (w[j].y - cy)) - temp;
5175 sigmat[i][j] = Ph2(w[i].x - w[j].x, w[i].y - w[j].y) -
5176 Ph2(w[i].x - w[j].x, w[i].y + w[j].y - 2. * cy) - temp;
5183bool ComponentAnalyticField::IprC30() {
5194 for (
int i = 0; i < nWires; ++i) {
5195 double cx = coplax - sx * int(round((coplax - w[i].x) / sx));
5196 double cy = coplay - sy * int(round((coplay - w[i].y) / sy));
5197 for (
int j = 0; j < nWires; ++j) {
5199 sigmat[i][i] = Ph2Lim(0.5 * w[i].d) - Ph2(0., 2. * (w[i].y - cy)) -
5200 Ph2(2. * (w[i].x - cx), 0.) +
5201 Ph2(2. * (w[i].x - cx), 2. * (w[i].y - cy));
5204 Ph2(w[i].x - w[j].x, w[i].y - w[j].y) -
5205 Ph2(w[i].x - w[j].x, w[i].y + w[j].y - 2. * cy) -
5206 Ph2(w[i].x + w[j].x - 2. * cx, w[i].y - w[j].y) +
5207 Ph2(w[i].x + w[j].x - 2. * cx, w[i].y + w[j].y - 2. * cy);
5214bool ComponentAnalyticField::IprD10() {
5222 std::complex<double> zi, zj;
5225 for (
int i = 0; i < nWires; ++i) {
5229 (cotube - (w[i].x * w[i].x + w[i].y * w[i].y) / cotube));
5231 zi = std::complex<double>(w[i].x, w[i].y);
5233 for (
int j = i + 1; j < nWires; ++j) {
5235 zj = std::complex<double>(w[j].x, w[j].y);
5236 sigmat[i][j] = -log(abs((1. / cotube) * (zi - zj) /
5237 (1. - conj(zi) * zj / (cotube * cotube))));
5239 sigmat[j][i] = sigmat[i][j];
5245bool ComponentAnalyticField::IprD30() {
5253 wmap.resize(nWires);
5255 std::complex<double> wd;
5256 InitializeCoefficientTables();
5259 for (
int i = 0; i < nWires; ++i) {
5261 ConformalMap(std::complex<double>(w[i].x, w[i].y) / cotube, wmap[i], wd);
5264 -log(abs((0.5 * w[i].d / cotube) * wd / (1. -
pow(abs(wmap[i]), 2))));
5266 for (
int j = 0; j < i - 1; ++j) {
5268 -log(abs((wmap[i] - wmap[j]) / (1. - conj(wmap[i]) * wmap[j])));
5270 sigmat[j][i] = sigmat[i][j];
5276bool ComponentAnalyticField::Wfield(
const double xpos,
const double ypos,
5277 const double zpos,
double& exsum,
5278 double& eysum,
double& ezsum,
double& vsum,
5279 const int isw,
const bool opt) {
5287 exsum = eysum = ezsum = vsum = 0.;
5288 double ex = 0., ey = 0., ez = 0.;
5291 if (!sigset)
return false;
5294 for (
int mx = mxmin; mx <= mxmax; ++mx) {
5295 for (
int my = mymin; my <= mymax; ++my) {
5306 for (
int iw = nWires; iw--;) {
5308 if (w[iw].ind == isw) {
5310 if (cellTypeFourier ==
"A ") {
5311 WfieldWireA00(xpos, ypos, ex, ey, volt, mx, my, iw, opt);
5312 }
else if (cellTypeFourier ==
"B2X") {
5313 WfieldWireB2X(xpos, ypos, ex, ey, volt, my, iw, opt);
5314 }
else if (cellTypeFourier ==
"B2Y") {
5315 WfieldWireB2Y(xpos, ypos, ex, ey, volt, mx, iw, opt);
5316 }
else if (cellTypeFourier ==
"C2X") {
5317 WfieldWireC2X(xpos, ypos, ex, ey, volt, iw, opt);
5318 }
else if (cellTypeFourier ==
"C2Y") {
5319 WfieldWireC2Y(xpos, ypos, ex, ey, volt, iw, opt);
5320 }
else if (cellTypeFourier ==
"C3 ") {
5321 WfieldWireC30(xpos, ypos, ex, ey, volt, iw, opt);
5322 }
else if (cellTypeFourier ==
"D1 ") {
5323 WfieldWireD10(xpos, ypos, ex, ey, volt, iw, opt);
5324 }
else if (cellTypeFourier ==
"D3 ") {
5325 WfieldWireD30(xpos, ypos, ex, ey, volt, iw, opt);
5328 std::cerr <<
" Unkown signal field type " << cellTypeFourier
5329 <<
" received. Program error!\n";
5330 std::cerr <<
" Encountered for wire " << iw
5331 <<
", readout group = " << w[iw].ind <<
"\n";
5332 exsum = eysum = ezsum = vsum = 0.;
5338 if (opt) vsum += volt;
5351 for (
int ip = 0; ip < 5; ++ip) {
5353 if (planes[ip].ind == isw) {
5355 if (cellTypeFourier ==
"A ") {
5356 WfieldPlaneA00(xpos, ypos, ex, ey, volt, mx, my, ip, opt);
5357 }
else if (cellTypeFourier ==
"B2X") {
5358 WfieldPlaneB2X(xpos, ypos, ex, ey, volt, my, ip, opt);
5359 }
else if (cellTypeFourier ==
"B2Y") {
5360 WfieldPlaneB2Y(xpos, ypos, ex, ey, volt, mx, ip, opt);
5361 }
else if (cellTypeFourier ==
"C2X") {
5362 WfieldPlaneC2X(xpos, ypos, ex, ey, volt, ip, opt);
5363 }
else if (cellTypeFourier ==
"C2Y") {
5364 WfieldPlaneC2Y(xpos, ypos, ex, ey, volt, ip, opt);
5365 }
else if (cellTypeFourier ==
"D1 ") {
5366 WfieldPlaneD10(xpos, ypos, ex, ey, volt, ip, opt);
5367 }
else if (cellTypeFourier ==
"D3 ") {
5368 WfieldPlaneD30(xpos, ypos, ex, ey, volt, ip, opt);
5371 std::cerr <<
" Unkown field type " << cellTypeFourier
5372 <<
" received. Program error!\n";
5373 std::cerr <<
" Encountered for plane " << ip
5374 <<
", readout group = " << planes[ip].ind <<
"\n";
5375 exsum = eysum = ezsum = 0.;
5381 if (opt) vsum += volt;
5388 for (
int ip = 0; ip < 5; ++ip) {
5389 if (planes[ip].ind == isw) {
5390 exsum += planes[ip].ewxcor;
5391 eysum += planes[ip].ewycor;
5393 if (ip == 0 || ip == 1) {
5396 xx -= sx * int(round(xpos / sx));
5397 if (ynplan[0] && xx <= coplan[0]) xx += sx;
5398 if (ynplan[1] && xx >= coplan[1]) xx -= sx;
5400 vsum += 1. - planes[ip].ewxcor * (xx - coplan[ip]);
5401 }
else if (ip == 2 || ip == 3) {
5404 yy -= sy * int(round(ypos / sy));
5405 if (ynplan[2] && yy <= coplan[2]) yy += sy;
5406 if (ynplan[3] && yy >= coplan[3]) yy -= sy;
5408 vsum += 1. - planes[ip].ewycor * (yy - coplan[ip]);
5415 for (
int ip = 0; ip < 5; ++ip) {
5416 for (
int istrip = 0; istrip < planes[ip].nStrips1; ++istrip) {
5417 if (planes[ip].strips1[istrip].ind == isw) {
5418 WfieldStripXy(xpos, ypos, zpos, ex, ey, ez, volt, ip, istrip, opt);
5422 if (opt) vsum += volt;
5425 for (
int istrip = 0; istrip < planes[ip].nStrips2; ++istrip) {
5426 if (planes[ip].strips2[istrip].ind == isw) {
5427 WfieldStripZ(xpos, ypos, ex, ey, volt, ip, istrip, opt);
5430 if (opt) vsum += volt;
5437void ComponentAnalyticField::WfieldWireA00(
const double xpos,
const double ypos,
5438 double& ex,
double& ey,
double& volt,
5439 const int mx,
const int my,
5440 const int isw,
const bool opt) {
5454 ex = ey = volt = 0.;
5456 double xxmirr = 0., yymirr = 0.;
5458 for (
int i = nWires; i--;) {
5460 const double xx = xpos - w[i].x - mx * sx;
5461 const double yy = ypos - w[i].y - my * sy;
5463 double r2 = xx * xx + yy * yy;
5464 if (r2 <= 0.)
continue;
5465 double exhelp = xx / r2;
5466 double eyhelp = yy / r2;
5469 xxmirr = xpos + w[i].x - 2. * coplax;
5470 const double r2plan = xxmirr * xxmirr + yy * yy;
5471 if (r2plan <= 0.)
continue;
5472 exhelp -= xxmirr / r2plan;
5473 eyhelp -= yy / r2plan;
5478 yymirr = ypos + w[i].y - 2. * coplay;
5479 const double r2plan = xx * xx + yymirr * yymirr;
5480 if (r2plan <= 0.)
continue;
5481 exhelp -= xx / r2plan;
5482 eyhelp -= yymirr / r2plan;
5486 if (ynplax && ynplay) {
5487 const double r2plan = xxmirr * xxmirr + yymirr * yymirr;
5488 if (r2plan <= 0.)
continue;
5489 exhelp += xxmirr / r2plan;
5490 eyhelp += yymirr / r2plan;
5494 if (opt) volt -= 0.5 * real(sigmat[isw][i]) * log(r2);
5495 ex += real(sigmat[isw][i]) * exhelp;
5496 ey += real(sigmat[isw][i]) * eyhelp;
5500void ComponentAnalyticField::WfieldWireB2X(
const double xpos,
const double ypos,
5501 double& ex,
double& ey,
double& volt,
5502 const int my,
const int isw,
5514 std::complex<double> zz, ecompl, zzmirr, zzneg, zznmirr;
5517 ex = ey = volt = 0.;
5520 for (
int i = nWires; i--;) {
5521 const double xx = HalfPi * (xpos - w[i].x) / sx;
5522 const double yy = HalfPi * (ypos - w[i].y - my * sy) / sx;
5523 const double xxneg = HalfPi * (xpos + w[i].x - 2. * coplan[0]) / sx;
5524 zz = std::complex<double>(xx, yy);
5525 zzneg = std::complex<double>(xxneg, yy);
5529 if (
fabs(yy) <= 20.) {
5530 ecompl = -b2sin[i] / (
sin(zz) *
sin(zzneg));
5532 r2 = (
pow(sinh(yy), 2) +
pow(
sin(xx), 2)) /
5533 (
pow(sinh(yy), 2) +
pow(
sin(xxneg), 2));
5538 const double yymirr = (HalfPi / sx) * (ypos + w[i].y - 2. * coplay);
5539 zzmirr = std::complex<double>(xx, yymirr);
5540 zznmirr = std::complex<double>(xxneg, yymirr);
5541 if (
fabs(yymirr) <= 20.) {
5542 ecompl += b2sin[i] / (
sin(zzmirr) *
sin(zznmirr));
5544 const double r2plan = (
pow(sinh(yymirr), 2) +
pow(
sin(xx), 2)) /
5545 (
pow(sinh(yymirr), 2) +
pow(
sin(xxneg), 2));
5551 ex += real(sigmat[isw][i]) * real(ecompl);
5552 ey -= real(sigmat[isw][i]) * imag(ecompl);
5553 if (opt) volt -= 0.5 * real(sigmat[isw][i]) * log(r2);
5559void ComponentAnalyticField::WfieldWireB2Y(
const double xpos,
const double ypos,
5560 double& ex,
double& ey,
double& volt,
5561 const int mx,
const int isw,
5573 const std::complex<double> icons = std::complex<double>(0., 1.);
5575 std::complex<double> zz, ecompl, zzmirr, zzneg, zznmirr;
5578 ex = ey = volt = 0.;
5581 for (
int i = 0; i < nWires; ++i) {
5582 const double xx = HalfPi * (xpos - w[i].x - mx * sx) / sy;
5583 const double yy = HalfPi * (ypos - w[i].y) / sy;
5584 const double yyneg = HalfPi * (ypos + w[i].y - 2. * coplan[2]) / sy;
5585 zz = std::complex<double>(xx, yy);
5586 zzneg = std::complex<double>(xx, yyneg);
5590 if (
fabs(xx) <= 20.) {
5591 ecompl = icons * b2sin[i] / (
sin(icons * zz) *
sin(icons * zzneg));
5593 r2 = (
pow(sinh(xx), 2) +
pow(
sin(yy), 2)) /
5594 (
pow(sinh(xx), 2) +
pow(
sin(yyneg), 2));
5599 const double xxmirr = (HalfPi / sy) * (xpos + w[i].x - 2. * coplax);
5600 zzmirr = std::complex<double>(xxmirr, yy);
5601 zznmirr = std::complex<double>(xxmirr, yyneg);
5602 if (
fabs(xxmirr) <= 20.) {
5604 icons * b2sin[i] / (
sin(icons * zzmirr) *
sin(icons * zznmirr));
5606 const double r2plan = (
pow(sinh(xxmirr), 2) +
pow(
sin(yy), 2)) /
5607 (
pow(sinh(xxmirr), 2) +
pow(
sin(yyneg), 2));
5613 ex += real(sigmat[isw][i]) * real(ecompl);
5614 ey -= real(sigmat[isw][i]) * imag(ecompl);
5615 if (opt) volt -= 0.5 * real(sigmat[isw][i]) * log(r2);
5621void ComponentAnalyticField::WfieldWireC2X(
const double xpos,
const double ypos,
5622 double& ex,
double& ey,
double& volt,
5623 const int isw,
const bool opt) {
5632 const std::complex<double> icons = std::complex<double>(0., 1.);
5633 std::complex<double> zsin, zcof, zu, zunew, zterm1, zterm2, zeta;
5636 std::complex<double> wsum1 = 0.;
5637 std::complex<double> wsum2 = 0.;
5642 for (
int i = 0; i < nWires; ++i) {
5644 zeta = zmult * std::complex<double>(xpos - w[i].x, ypos - w[i].y);
5645 if (imag(zeta) > 15.) {
5646 wsum1 -= real(sigmat[isw][i]) * icons;
5647 if (opt) volt -= real(sigmat[isw][i]) * (
fabs(imag(zeta)) - CLog2);
5648 }
else if (imag(zeta) < -15.) {
5649 wsum1 += real(sigmat[isw][i]) * icons;
5650 if (opt) volt -= real(sigmat[isw][i]) * (
fabs(imag(zeta)) - CLog2);
5653 zcof = 4. * zsin * zsin - 2.;
5654 zu = -p1 - zcof * p2;
5655 zunew = 1. - zcof * zu - p2;
5656 zterm1 = (zunew + zu) * zsin;
5657 zu = -3. * p1 - zcof * 5. * p2;
5658 zunew = 1. - zcof * zu - 5. * p2;
5659 zterm2 = (zunew - zu) *
cos(zeta);
5660 wsum1 += real(sigmat[isw][i]) * (zterm2 / zterm1);
5661 if (opt) volt -= real(sigmat[isw][i]) * log(abs(zterm1));
5664 double cx = coplax - sx * int(round((coplax - w[i].x) / sx));
5666 s += real(sigmat[isw][i]) * (w[i].x - cx);
5668 zeta = zmult * std::complex<double>(2. * cx - xpos - w[i].x, ypos - w[i].y);
5669 if (imag(zeta) > +15.) {
5670 wsum2 -= real(sigmat[isw][i]) * icons;
5671 if (opt) volt += real(sigmat[isw][i]) * (
fabs(imag(zeta)) - CLog2);
5672 }
else if (imag(zeta) < -15.) {
5673 wsum2 += real(sigmat[isw][i]) * icons;
5674 if (opt) volt += real(sigmat[isw][i]) * (
fabs(imag(zeta)) - CLog2);
5677 zcof = 4. * zsin * zsin - 2.;
5678 zu = -p1 - zcof * p2;
5679 zunew = 1. - zcof * zu - p2;
5680 zterm1 = (zunew + zu) * zsin;
5681 zu = -3. * p1 - zcof * 5. * p2;
5682 zunew = 1. - zcof * zu - 5. * p2;
5683 zterm2 = (zunew - zu) *
cos(zeta);
5684 wsum2 += real(sigmat[isw][i]) * (zterm2 / zterm1);
5685 if (opt) volt += real(sigmat[isw][i]) * log(abs(zterm1));
5688 if (opt && mode == 0) {
5689 volt -= TwoPi * real(sigmat[isw][i]) * (xpos - cx) * (w[i].x - cx) /
5694 ex = real(zmult * (wsum1 + wsum2));
5695 ey = -imag(zmult * (wsum1 - wsum2));
5697 if (mode == 0) ex += s * TwoPi / (sx * sy);
5700void ComponentAnalyticField::WfieldWireC2Y(
const double xpos,
const double ypos,
5701 double& ex,
double& ey,
double& volt,
5702 const int isw,
const bool opt) {
5711 const std::complex<double> icons = std::complex<double>(0., 1.);
5712 std::complex<double> zsin, zcof, zu, zunew, zterm1, zterm2, zeta;
5715 std::complex<double> wsum1 = 0.;
5716 std::complex<double> wsum2 = 0.;
5721 for (
int i = 0; i < nWires; ++i) {
5723 zeta = zmult * std::complex<double>(xpos - w[i].x, ypos - w[i].y);
5724 if (imag(zeta) > +15.) {
5725 wsum1 -= real(sigmat[isw][i]) * icons;
5726 if (opt) volt -= real(sigmat[isw][i]) * (
fabs(imag(zeta)) - CLog2);
5727 }
else if (imag(zeta) < -15.) {
5728 wsum1 += real(sigmat[isw][i]) * icons;
5729 if (opt) volt -= real(sigmat[isw][i]) * (
fabs(imag(zeta)) - CLog2);
5732 zcof = 4. * zsin * zsin - 2.;
5733 zu = -p1 - zcof * p2;
5734 zunew = 1. - zcof * zu - p2;
5735 zterm1 = (zunew + zu) * zsin;
5736 zu = -3. * p1 - zcof * 5. * p2;
5737 zunew = 1. - zcof * zu - 5. * p2;
5738 zterm2 = (zunew - zu) *
cos(zeta);
5739 wsum1 += real(sigmat[isw][i]) * (zterm2 / zterm1);
5740 if (opt) volt -= real(sigmat[isw][i]) * log(abs(zterm1));
5743 double cy = coplay - sy * int(round((coplay - w[i].y) / sy));
5745 s += real(sigmat[isw][i]) * (w[i].y - cy);
5747 zeta = zmult * std::complex<double>(xpos - w[i].x, 2. * cy - ypos - w[i].y);
5748 if (imag(zeta) > +15.) {
5749 wsum2 -= real(sigmat[isw][i]) * icons;
5750 if (opt) volt += real(sigmat[isw][i]) * (
fabs(imag(zeta)) - CLog2);
5751 }
else if (imag(zeta) < -15.) {
5752 wsum2 += real(sigmat[isw][i]) * icons;
5753 if (opt) volt += real(sigmat[isw][i]) * (
fabs(imag(zeta)) - CLog2);
5756 zcof = 4. * zsin * zsin - 2.;
5757 zu = -p1 - zcof * p2;
5758 zunew = 1. - zcof * zu - p2;
5759 zterm1 = (zunew + zu) * zsin;
5760 zu = -3. * p1 - zcof * 5. * p2;
5761 zunew = 1. - zcof * zu - 5. * p2;
5762 zterm2 = (zunew - zu) *
cos(zeta);
5763 wsum2 += real(sigmat[isw][i]) * (zterm2 / zterm1);
5764 if (opt) volt += real(sigmat[isw][i]) * log(abs(zterm1));
5767 if (opt && mode == 1) {
5768 volt -= TwoPi * real(sigmat[isw][i]) * (ypos - cy) * (w[i].y - cy) /
5773 ex = real(zmult * (wsum1 - wsum2));
5774 ey = -imag(zmult * (wsum1 + wsum2));
5776 if (mode == 1) ey += s * TwoPi / (sx * sy);
5779void ComponentAnalyticField::WfieldWireC30(
const double xpos,
const double ypos,
5780 double& ex,
double& ey,
double& volt,
5781 const int isw,
const bool opt) {
5790 const std::complex<double> icons = std::complex<double>(0., 1.);
5791 std::complex<double> zsin, zcof, zu, zunew, zterm1, zterm2, zeta;
5794 std::complex<double> wsum1 = 0.;
5795 std::complex<double> wsum2 = 0.;
5796 std::complex<double> wsum3 = 0.;
5797 std::complex<double> wsum4 = 0.;
5801 for (
int i = 0; i < nWires; ++i) {
5803 zeta = zmult * std::complex<double>(xpos - w[i].x, ypos - w[i].y);
5804 if (imag(zeta) > +15.) {
5805 wsum1 -= real(sigmat[isw][i]) * icons;
5806 if (opt) volt -= real(sigmat[isw][i]) * (
fabs(imag(zeta)) - CLog2);
5807 }
else if (imag(zeta) < -15.) {
5808 wsum1 += real(sigmat[isw][i]) * icons;
5809 if (opt) volt -= real(sigmat[isw][i]) * (
fabs(imag(zeta)) - CLog2);
5812 zcof = 4. * zsin * zsin - 2.;
5813 zu = -p1 - zcof * p2;
5814 zunew = 1. - zcof * zu - p2;
5815 zterm1 = (zunew + zu) * zsin;
5816 zu = -3. * p1 - zcof * 5. * p2;
5817 zunew = 1. - zcof * zu - 5. * p2;
5818 zterm2 = (zunew - zu) *
cos(zeta);
5819 wsum1 += real(sigmat[isw][i]) * (zterm2 / zterm1);
5820 if (opt) volt -= real(sigmat[isw][i]) * log(abs(zterm1));
5823 double cx = coplax - sx * int(round((coplax - w[i].x) / sx));
5825 zeta = zmult * std::complex<double>(2. * cx - xpos - w[i].x, ypos - w[i].y);
5826 if (imag(zeta) > +15.) {
5827 wsum2 -= real(sigmat[isw][i]) * icons;
5828 if (opt) volt += real(sigmat[isw][i]) * (
fabs(imag(zeta)) - CLog2);
5829 }
else if (imag(zeta) < -15.) {
5830 wsum2 += real(sigmat[isw][i]) * icons;
5831 if (opt) volt += real(sigmat[isw][i]) * (
fabs(imag(zeta)) - CLog2);
5834 zcof = 4. * zsin * zsin - 2.;
5835 zu = -p1 - zcof * p2;
5836 zunew = 1. - zcof * zu - p2;
5837 zterm1 = (zunew + zu) * zsin;
5838 zu = -3. * p1 - zcof * 5. * p2;
5839 zunew = 1. - zcof * zu - 5. * p2;
5840 zterm2 = (zunew - zu) *
cos(zeta);
5841 wsum2 += real(sigmat[isw][i]) * (zterm2 / zterm1);
5842 if (opt) volt += real(sigmat[isw][i]) * log(abs(zterm1));
5845 double cy = coplay - sy * int(round((coplay - w[i].y) / sy));
5847 zeta = zmult * std::complex<double>(xpos - w[i].x, 2. * cy - ypos - w[i].y);
5848 if (imag(zeta) > +15.) {
5849 wsum3 -= real(sigmat[isw][i]) * icons;
5850 if (opt) volt += real(sigmat[isw][i]) * (
fabs(imag(zeta)) - CLog2);
5851 }
else if (imag(zeta) < -15.) {
5852 wsum3 += real(sigmat[isw][i]) * icons;
5853 if (opt) volt += real(sigmat[isw][i]) * (
fabs(imag(zeta)) - CLog2);
5856 zcof = 4. * zsin * zsin - 2.;
5857 zu = -p1 - zcof * p2;
5858 zunew = 1. - zcof * zu - p2;
5859 zterm1 = (zunew + zu) * zsin;
5860 zu = -3. * p1 - zcof * 5. * p2;
5861 zunew = 1. - zcof * zu - 5. * p2;
5862 zterm2 = (zunew - zu) *
cos(zeta);
5863 wsum3 += real(sigmat[isw][i]) * (zterm2 / zterm1);
5864 if (opt) volt += real(sigmat[isw][i]) * log(abs(zterm1));
5867 zeta = zmult * std::complex<double>(2. * cx - xpos - w[i].x,
5868 2. * cy - ypos - w[i].y);
5869 if (imag(zeta) > +15.) {
5870 wsum4 -= real(sigmat[isw][i]) * icons;
5871 if (opt) volt -= real(sigmat[isw][i]) * (
fabs(imag(zeta)) - CLog2);
5872 }
else if (imag(zeta) < -15.) {
5873 wsum4 += real(sigmat[isw][i]) * icons;
5874 if (opt) volt -= real(sigmat[isw][i]) * (
fabs(imag(zeta)) - CLog2);
5877 zcof = 4. * zsin * zsin - 2.;
5878 zu = -p1 - zcof * p2;
5879 zunew = 1. - zcof * zu - p2;
5880 zterm1 = (zunew + zu) * zsin;
5881 zu = -3. * p1 - zcof * 5. * p2;
5882 zunew = 1. - zcof * zu - 5. * p2;
5883 zterm2 = (zunew - zu) *
cos(zeta);
5884 wsum4 += real(sigmat[isw][i]) * (zterm2 / zterm1);
5885 if (opt) volt -= real(sigmat[isw][i]) * log(abs(zterm1));
5889 ex = real(zmult * (wsum1 + wsum2 - wsum3 - wsum4));
5890 ey = -imag(zmult * (wsum1 - wsum2 + wsum3 - wsum4));
5893void ComponentAnalyticField::WfieldWireD10(
const double xpos,
const double ypos,
5894 double& ex,
double& ey,
double& volt,
5895 const int isw,
const bool opt) {
5908 ex = ey = volt = 0.;
5911 std::complex<double> zpos = std::complex<double>(xpos, ypos);
5912 std::complex<double> zi;
5913 std::complex<double> wi;
5916 for (
int i = nWires; i--;) {
5918 zi = std::complex<double>(w[i].x, w[i].y);
5922 real(sigmat[isw][i]) *
5923 log(abs(cotube * (zpos - zi) / (cotube * cotube - zpos * conj(zi))));
5926 wi = 1. / conj(zpos - zi) + zi / (cotube * cotube - conj(zpos) * zi);
5927 ex += real(sigmat[isw][i]) * real(wi);
5928 ey += real(sigmat[isw][i]) * imag(wi);
5932void ComponentAnalyticField::WfieldWireD30(
const double xpos,
const double ypos,
5933 double& ex,
double& ey,
double& volt,
5934 const int isw,
const bool opt) {
5946 ex = ey = volt = 0.;
5948 std::complex<double> whelp;
5951 std::complex<double> wpos, wdpos;
5952 ConformalMap(std::complex<double>(xpos, ypos) / cotube, wpos, wdpos);
5954 for (
int i = nWires; i--;) {
5957 volt -= real(sigmat[isw][i]) *
5958 log(abs((wpos - wmap[i]) / (1. - wpos * conj(wmap[i]))));
5961 whelp = wdpos * (1. -
pow(abs(wmap[i]), 2)) /
5962 ((wpos - wmap[i]) * (1. - conj(wmap[i]) * wpos));
5963 ex += real(sigmat[isw][i]) * real(whelp);
5964 ey -= real(sigmat[isw][i]) * imag(whelp);
5970void ComponentAnalyticField::WfieldPlaneA00(
const double xpos,
5971 const double ypos,
double& ex,
5972 double& ey,
double& volt,
5973 const int mx,
const int my,
5974 const int iplane,
const bool opt) {
5986 ex = ey = volt = 0.;
5988 double xxmirr = 0., yymirr = 0.;
5990 for (
int i = nWires; i--;) {
5992 const double xx = xpos - w[i].x - mx * sx;
5993 const double yy = ypos - w[i].y - my * sy;
5995 double r2 = xx * xx + yy * yy;
5996 if (r2 <= 0.)
continue;
5997 double exhelp = xx / r2;
5998 double eyhelp = yy / r2;
6001 xxmirr = xpos + w[i].x - 2 * coplax;
6002 const double r2plan = xxmirr * xxmirr + yy * yy;
6003 if (r2plan <= 0.)
continue;
6004 exhelp -= xxmirr / r2plan;
6005 eyhelp -= yy / r2plan;
6010 yymirr = ypos + w[i].y - 2 * coplay;
6011 const double r2plan = xx * xx + yymirr * yymirr;
6012 if (r2plan <= 0.)
continue;
6013 exhelp -= xx / r2plan;
6014 eyhelp -= yymirr / r2plan;
6018 if (ynplax && ynplay) {
6019 const double r2plan = xxmirr * xxmirr + yymirr * yymirr;
6020 if (r2plan <= 0.)
continue;
6021 exhelp += xxmirr / r2plan;
6022 eyhelp += yymirr / r2plan;
6026 if (opt) volt -= 0.5 * qplane[iplane][i] * log(r2);
6027 ex += qplane[iplane][i] * exhelp;
6028 ey += qplane[iplane][i] * eyhelp;
6032void ComponentAnalyticField::WfieldPlaneB2X(
const double xpos,
6033 const double ypos,
double& ex,
6034 double& ey,
double& volt,
6035 const int my,
const int iplane,
6047 std::complex<double> zz, ecompl, zzmirr, zzneg, zznmirr;
6050 ex = ey = volt = 0.;
6052 for (
int i = nWires; i--;) {
6053 const double xx = HalfPi * (xpos - w[i].x) / sx;
6054 const double yy = HalfPi * (ypos - w[i].y - my * sy) / sx;
6055 const double xxneg = HalfPi * (xpos + w[i].x - 2 * coplan[0]) / sx;
6056 zz = std::complex<double>(xx, yy);
6057 zzneg = std::complex<double>(xxneg, yy);
6061 if (
fabs(yy) <= 20.) {
6062 ecompl = -b2sin[i] / (
sin(zz) *
sin(zzneg));
6064 r2 = (
pow(sinh(yy), 2) +
pow(
sin(xx), 2)) /
6065 (
pow(sinh(yy), 2) +
pow(
sin(xxneg), 2));
6070 const double yymirr = (HalfPi / sx) * (ypos + w[i].y - 2 * coplay);
6071 zzmirr = std::complex<double>(yy, yymirr);
6072 zznmirr = std::complex<double>(xxneg, yymirr);
6073 if (
fabs(yymirr) <= 20.) {
6074 ecompl += b2sin[i] / (
sin(zzmirr) *
sin(zznmirr));
6076 const double r2plan = (
pow(sinh(yymirr), 2) +
pow(
sin(xx), 2)) /
6077 (
pow(sinh(yymirr), 2) +
pow(
sin(xxneg), 2));
6083 ex += qplane[iplane][i] * real(ecompl);
6084 ey -= qplane[iplane][i] * imag(ecompl);
6085 if (opt) volt -= 0.5 * qplane[iplane][i] * log(r2);
6087 ex *= (HalfPi / sx);
6088 ey *= (HalfPi / sx);
6091void ComponentAnalyticField::WfieldPlaneB2Y(
const double xpos,
6092 const double ypos,
double& ex,
6093 double& ey,
double& volt,
6094 const int mx,
const int iplane,
6106 const std::complex<double> icons = std::complex<double>(0., 1.);
6108 std::complex<double> zz, ecompl, zzmirr, zzneg, zznmirr;
6111 ex = ey = volt = 0.;
6113 for (
int i = nWires; i--;) {
6114 const double xx = HalfPi * (xpos - w[i].x - mx * sx) / sy;
6115 const double yy = HalfPi * (ypos - w[i].y) / sy;
6116 const double yyneg = HalfPi * (ypos + w[i].y - 2 * coplan[2]) / sy;
6117 zz = std::complex<double>(xx, yy);
6118 zzneg = std::complex<double>(xx, yyneg);
6122 if (
fabs(xx) <= 20.) {
6123 ecompl = icons * b2sin[i] / (
sin(icons * zz) *
sin(icons * zzneg));
6125 r2 = (
pow(sinh(xx), 2) +
pow(
sin(yy), 2)) /
6126 (
pow(sinh(xx), 2) +
pow(
sin(yyneg), 2));
6131 const double xxmirr = (HalfPi / sy) * (xpos + w[i].x - 2 * coplax);
6132 zzmirr = std::complex<double>(xxmirr, yy);
6133 zznmirr = std::complex<double>(xxmirr, yyneg);
6134 if (
fabs(xxmirr) <= 20.) {
6135 ecompl -= b2sin[i] / (
sin(icons * zzmirr) *
sin(icons * zznmirr));
6137 const double r2plan = (
pow(sinh(xxmirr), 2) +
pow(
sin(yy), 2)) /
6138 (
pow(sinh(xxmirr), 2) +
pow(
sin(yyneg), 2));
6144 ex += qplane[iplane][i] * real(ecompl);
6145 ey -= qplane[iplane][i] * imag(ecompl);
6146 if (opt) volt -= 0.5 * qplane[iplane][i] * log(r2);
6152void ComponentAnalyticField::WfieldPlaneC2X(
const double xpos,
6153 const double ypos,
double& ex,
6154 double& ey,
double& volt,
6155 const int iplane,
const bool opt) {
6164 const std::complex<double> icons = std::complex<double>(0., 1.);
6166 std::complex<double> zsin, zcof, zu, zunew, zterm1, zterm2, zeta;
6168 std::complex<double> wsum1 = 0.;
6169 std::complex<double> wsum2 = 0.;
6174 for (
int i = 0; i < nWires; ++i) {
6176 zeta = zmult * std::complex<double>(xpos - w[i].x, ypos - w[i].y);
6177 if (imag(zeta) > +15.) {
6178 wsum1 -= qplane[iplane][i] * icons;
6179 if (opt) volt -= qplane[iplane][i] * (
fabs(imag(zeta)) - CLog2);
6180 }
else if (imag(zeta) < -15.) {
6181 wsum1 += qplane[iplane][i] * icons;
6182 if (opt) volt -= qplane[iplane][i] * (
fabs(imag(zeta)) - CLog2);
6185 zcof = 4. * zsin * zsin - 2.;
6186 zu = -p1 - zcof * p2;
6187 zunew = 1. - zcof * zu - p2;
6188 zterm1 = (zunew + zu) * zsin;
6189 zu = -3. * p1 - zcof * 5. * p2;
6190 zunew = 1. - zcof * zu - 5. * p2;
6191 zterm2 = (zunew - zu) *
cos(zeta);
6192 wsum1 += qplane[iplane][i] * (zterm2 / zterm1);
6193 if (opt) volt -= qplane[iplane][i] * log(abs(zterm1));
6196 double cx = coplax - sx * int(round((coplax - w[i].x) / sx));
6198 s += qplane[iplane][i] * (w[i].x - cx);
6200 zeta = zmult * std::complex<double>(2. * cx - xpos - w[i].x, ypos - w[i].y);
6201 if (imag(zeta) > 15.) {
6202 wsum2 -= qplane[iplane][i] * icons;
6203 if (opt) volt += qplane[iplane][i] * (
fabs(imag(zeta)) - CLog2);
6204 }
else if (imag(zeta) < -15.) {
6205 wsum2 += qplane[iplane][i] * icons;
6206 if (opt) volt += qplane[iplane][i] * (
fabs(imag(zeta)) - CLog2);
6209 zcof = 4. * zsin * zsin - 2.;
6210 zu = -p1 - zcof * p2;
6211 zunew = 1. - zcof * zu - p2;
6212 zterm1 = (zunew + zu) * zsin;
6213 zu = -3. * p1 - zcof * 5. * p2;
6214 zunew = 1. - zcof * zu - 5. * p2;
6215 zterm2 = (zunew - zu) *
cos(zeta);
6216 wsum2 += qplane[iplane][i] * (zterm2 / zterm1);
6217 if (opt) volt += qplane[iplane][i] * log(abs(zterm1));
6219 if (opt && mode == 0) {
6221 TwoPi * qplane[iplane][i] * (xpos - cx) * (w[i].x - cx) / (sx * sy);
6225 ex = real(zmult * (wsum1 + wsum2));
6226 ey = -imag(zmult * (wsum1 - wsum2));
6228 if (mode == 0) ex += s * TwoPi / (sx * sy);
6231void ComponentAnalyticField::WfieldPlaneC2Y(
const double xpos,
6232 const double ypos,
double& ex,
6233 double& ey,
double& volt,
6234 const int iplane,
const bool opt) {
6243 const std::complex<double> icons = std::complex<double>(0., 1.);
6245 std::complex<double> zsin, zcof, zu, zunew, zterm1, zterm2, zeta;
6247 std::complex<double> wsum1 = 0.;
6248 std::complex<double> wsum2 = 0.;
6253 for (
int i = 0; i < nWires; ++i) {
6255 zeta = zmult * std::complex<double>(xpos - w[i].x, ypos - w[i].y);
6256 if (imag(zeta) > +15.) {
6257 wsum1 -= qplane[iplane][i] * icons;
6258 if (opt) volt -= qplane[iplane][i] * (
fabs(imag(zeta)) - CLog2);
6259 }
else if (imag(zeta) < -15.) {
6260 wsum1 += qplane[iplane][i] * icons;
6261 if (opt) volt -= qplane[iplane][i] * (
fabs(imag(zeta)) - CLog2);
6264 zcof = 4. * zsin * zsin - 2.;
6265 zu = -p1 - zcof * p2;
6266 zunew = 1. - zcof * zu - p2;
6267 zterm1 = (zunew + zu) * zsin;
6268 zu = -3. * p1 - zcof * 5. * p2;
6269 zunew = 1. - zcof * zu - 5. * p2;
6270 zterm2 = (zunew - zu) *
cos(zeta);
6271 wsum1 += qplane[iplane][i] * (zterm2 / zterm1);
6272 if (opt) volt -= qplane[iplane][i] * log(abs(zterm1));
6275 double cy = coplay - sy * int(round((coplay - w[i].y) / sy));
6277 s += qplane[iplane][i] * (w[i].y - cy);
6279 zeta = zmult * std::complex<double>(xpos - w[i].x, 2. * cy - ypos - w[i].y);
6280 if (imag(zeta) > 15.) {
6281 wsum2 -= qplane[iplane][i] * icons;
6282 if (opt) volt += qplane[iplane][i] * (
fabs(imag(zeta)) - CLog2);
6283 }
else if (imag(zeta) < -15.) {
6284 wsum2 += qplane[iplane][i] * icons;
6285 if (opt) volt += qplane[iplane][i] * (
fabs(imag(zeta)) - CLog2);
6288 zcof = 4. * zsin * zsin - 2.;
6289 zu = -p1 - zcof * p2;
6290 zunew = 1. - zcof * zu - p2;
6291 zterm1 = (zunew + zu) * zsin;
6292 zu = -3. * p1 - zcof * 5. * p2;
6293 zunew = 1. - zcof * zu - 5. * p2;
6294 zterm2 = (zunew - zu) *
cos(zeta);
6295 wsum2 += qplane[iplane][i] * (zterm2 / zterm1);
6296 if (opt) volt += qplane[iplane][i] * log(abs(zterm1));
6299 if (opt && mode == 1) {
6301 TwoPi * qplane[iplane][i] * (ypos - cy) * (w[i].y - cy) / (sx * sy);
6305 ex = real(zmult * (wsum1 - wsum2));
6306 ey = -imag(zmult * (wsum1 + wsum2));
6308 if (mode == 1) ey += s * TwoPi / (sx * sy);
6311void ComponentAnalyticField::WfieldPlaneC30(
const double xpos,
6312 const double ypos,
double& ex,
6313 double& ey,
double& volt,
6314 const int iplane,
const bool opt) {
6323 const std::complex<double> icons = std::complex<double>(0., 1.);
6325 std::complex<double> zsin, zcof, zu, zunew, zterm1, zterm2, zeta;
6327 std::complex<double> wsum1 = 0.;
6328 std::complex<double> wsum2 = 0.;
6329 std::complex<double> wsum3 = 0.;
6330 std::complex<double> wsum4 = 0.;
6334 for (
int i = 0; i < nWires; ++i) {
6336 zeta = zmult * std::complex<double>(xpos - w[i].x, ypos - w[i].y);
6337 if (imag(zeta) > +15.) {
6338 wsum1 -= qplane[iplane][i] * icons;
6339 if (opt) volt -= qplane[iplane][i] * (
fabs(imag(zeta)) - CLog2);
6340 }
else if (imag(zeta) < -15.) {
6341 wsum1 += qplane[iplane][i] * icons;
6342 if (opt) volt -= qplane[iplane][i] * (
fabs(imag(zeta)) - CLog2);
6345 zcof = 4. * zsin * zsin - 2.;
6346 zu = -p1 - zcof * p2;
6347 zunew = 1. - zcof * zu - p2;
6348 zterm1 = (zunew + zu) * zsin;
6349 zu = -3. * p1 - zcof * 5. * p2;
6350 zunew = 1. - zcof * zu - 5. * p2;
6351 zterm2 = (zunew - zu) *
cos(zeta);
6352 wsum1 += qplane[iplane][i] * zterm2 / zterm1;
6353 if (opt) volt -= qplane[iplane][i] * log(abs(zterm1));
6356 double cx = coplax - sx * int(round((coplax - w[i].x) / sx));
6358 zeta = zmult * std::complex<double>(2. * cx - xpos - w[i].x, ypos - w[i].y);
6359 if (imag(zeta) > 15.) {
6360 wsum2 -= qplane[iplane][i] * icons;
6361 if (opt) volt += qplane[iplane][i] * (
fabs(imag(zeta)) - CLog2);
6362 }
else if (imag(zeta) < -15.) {
6363 wsum2 += qplane[iplane][i] * icons;
6364 if (opt) volt += qplane[iplane][i] * (
fabs(imag(zeta)) - CLog2);
6367 zcof = 4. * zsin * zsin - 2.;
6368 zu = -p1 - zcof * p2;
6369 zunew = 1. - zcof * zu - p2;
6370 zterm1 = (zunew + zu) * zsin;
6371 zu = -3. * p1 - zcof * 5. * p2;
6372 zunew = 1. - zcof * zu - 5. * p2;
6373 zterm2 = (zunew - zu) *
cos(zeta);
6374 wsum2 += qplane[iplane][i] * zterm2 / zterm1;
6375 if (opt) volt += qplane[iplane][i] * log(abs(zterm1));
6378 double cy = coplay - sy * int(round((coplay - w[i].y) / sy));
6380 zeta = zmult * std::complex<double>(xpos - w[i].x, 2. * cy - ypos - w[i].y);
6381 if (imag(zeta) > 15.) {
6382 wsum3 -= qplane[iplane][i] * icons;
6383 if (opt) volt += qplane[iplane][i] * (
fabs(imag(zeta)) - CLog2);
6384 }
else if (imag(zeta) < -15.) {
6385 wsum3 += qplane[iplane][i] * icons;
6386 if (opt) volt += qplane[iplane][i] * (
fabs(imag(zeta)) - CLog2);
6389 zcof = 4. * zsin * zsin - 2.;
6390 zu = -p1 - zcof * p2;
6391 zunew = 1. - zcof * zu - p2;
6392 zterm1 = (zunew + zu) * zsin;
6393 zu = -3. * p1 - zcof * 5. * p2;
6394 zunew = 1. - zcof * zu - 5. * p2;
6395 zterm2 = (zunew - zu) *
cos(zeta);
6396 wsum3 += qplane[iplane][i] * zterm2 / zterm1;
6397 if (opt) volt += qplane[iplane][i] * log(abs(zterm1));
6400 zeta = zmult * std::complex<double>(2. * cx - xpos - w[i].x,
6401 2. * cy - ypos - w[i].y);
6402 if (imag(zeta) > 15.) {
6403 wsum4 -= qplane[iplane][i] * icons;
6404 if (opt) volt -= qplane[iplane][i] * (
fabs(imag(zeta)) - CLog2);
6405 }
else if (imag(zeta) < -15.) {
6406 wsum4 += qplane[iplane][i] * icons;
6407 if (opt) volt -= qplane[iplane][i] * (
fabs(imag(zeta)) - CLog2);
6410 zcof = 4. * zsin * zsin - 2.;
6411 zu = -p1 - zcof * p2;
6412 zunew = 1. - zcof * zu - p2;
6413 zterm1 = (zunew + zu) * zsin;
6414 zu = -3. * p1 - zcof * 5. * p2;
6415 zunew = 1. - zcof * zu - 5. * p2;
6416 zterm2 = (zunew - zu) *
cos(zeta);
6417 wsum4 += qplane[iplane][i] * zterm2 / zterm1;
6418 if (opt) volt -= qplane[iplane][i] * log(abs(zterm1));
6421 ex = real(zmult * (wsum1 + wsum2 - wsum3 - wsum4));
6422 ey = -imag(zmult * (wsum1 - wsum2 + wsum3 - wsum4));
6425void ComponentAnalyticField::WfieldPlaneD10(
const double xpos,
6426 const double ypos,
double& ex,
6427 double& ey,
double& volt,
6428 const int iplane,
const bool opt) {
6440 ex = ey = volt = 0.;
6443 std::complex<double> zpos = std::complex<double>(xpos, ypos);
6444 std::complex<double> zi;
6445 std::complex<double> wi;
6448 for (
int i = nWires; i--;) {
6450 zi = std::complex<double>(w[i].x, w[i].y);
6455 log(abs(cotube * (zpos - zi) / (cotube * cotube - zpos * conj(zi))));
6458 wi = 1. / conj(zpos - zi) + zi / (cotube * cotube - conj(zpos) * zi);
6459 ex += qplane[iplane][i] * real(wi);
6460 ey += qplane[iplane][i] * imag(wi);
6464void ComponentAnalyticField::WfieldPlaneD30(
const double xpos,
6465 const double ypos,
double& ex,
6466 double& ey,
double& volt,
6467 const int iplane,
const bool opt) {
6479 ex = ey = volt = 0.;
6481 std::complex<double> whelp;
6484 std::complex<double> wpos, wdpos;
6485 ConformalMap(std::complex<double>(xpos, ypos) / cotube, wpos, wdpos);
6487 for (
int i = 0; i < nWires; ++i) {
6490 volt -= qplane[iplane][i] *
6491 log(abs((wpos - wmap[i]) / (1. - wpos * conj(wmap[i]))));
6494 whelp = wdpos * (1. -
pow(abs(wmap[i]), 2)) /
6495 ((wpos - wmap[i]) * (1. - conj(wmap[i]) * wpos));
6496 ex += qplane[iplane][i] * real(whelp);
6497 ey -= qplane[iplane][i] * imag(whelp);
6503void ComponentAnalyticField::WfieldStripZ(
const double xpos,
const double ypos,
6504 double& ex,
double& ey,
double& volt,
6505 const int ip,
const int is,
6514 ex = ey = volt = 0.;
6516 strip theStrip = planes[ip].strips2[is];
6518 double xw = 0., yw = 0.;
6521 xw = -ypos + (theStrip.smin + theStrip.smax) / 2.;
6522 yw = xpos - coplan[ip];
6525 xw = ypos - (theStrip.smin + theStrip.smax) / 2.;
6526 yw = coplan[ip] - xpos;
6529 xw = xpos - (theStrip.smin + theStrip.smax) / 2.;
6530 yw = ypos - coplan[ip];
6533 xw = -xpos + (theStrip.smin + theStrip.smax) / 2.;
6534 yw = coplan[ip] - ypos;
6540 const double w =
fabs(theStrip.smax - theStrip.smin) / 2.;
6541 const double g = theStrip.gap;
6544 if (yw <= 0. || yw > g)
return;
6547 const double s =
sin(Pi * yw / g);
6548 const double c =
cos(Pi * yw / g);
6549 const double e1 =
exp(Pi * (w - xw) / g);
6550 const double e2 =
exp(-Pi * (w + xw) / g);
6551 const double ce12 =
pow(c - e1, 2);
6552 const double ce22 =
pow(c - e2, 2);
6554 if (c == e1 || c == e2)
return;
6557 volt = atan((c - e2) / s) - atan((c - e1) / s);
6561 const double ewx = (s / g) * (e1 / (ce12 + s * s) - e2 / (ce22 + s * s));
6562 const double ewy = ((c / (c - e2) + s * s / ce22) / (1. + s * s / ce22) -
6563 (c / (c - e1) + s * s / ce12) / (1. + s * s / ce12)) /
6587void ComponentAnalyticField::WfieldStripXy(
const double xpos,
const double ypos,
6588 const double zpos,
double& ex,
6589 double& ey,
double& ez,
double& volt,
6590 const int ip,
const int is,
6599 ex = ey = ez = volt = 0.;
6601 strip theStrip = planes[ip].strips1[is];
6603 double xw = 0., yw = 0.;
6606 xw = -zpos + (theStrip.smin + theStrip.smax) / 2.;
6607 yw = xpos - coplan[ip];
6610 xw = zpos - (theStrip.smin + theStrip.smax) / 2.;
6611 yw = coplan[ip] - xpos;
6614 xw = zpos - (theStrip.smin + theStrip.smax) / 2.;
6615 yw = ypos - coplan[ip];
6618 xw = -zpos + (theStrip.smin + theStrip.smax) / 2.;
6619 yw = coplan[ip] - ypos;
6626 const double w =
fabs(theStrip.smax - theStrip.smin) / 2.;
6627 const double g = theStrip.gap;
6630 if (yw <= 0. || yw > g)
return;
6633 const double s =
sin(Pi * yw / g);
6634 const double c =
cos(Pi * yw / g);
6635 const double e1 =
exp(Pi * (w - xw) / g);
6636 const double e2 =
exp(-Pi * (w + xw) / g);
6637 const double ce12 =
pow(c - e1, 2);
6638 const double ce22 =
pow(c - e2, 2);
6640 if (c == e1 || c == e2)
return;
6643 volt = atan((c - e2) / s) - atan((c - e1) / s);
6647 const double ewx = (s / g) * (e1 / (ce12 + s * s) - e2 / (ce22 + s * s));
6648 const double ewy = ((c / (c - e2) + s * s / ce22) / (1. + s * s / ce22) -
6649 (c / (c - e1) + s * s / ce12) / (1. + s * s / ce12)) /
DoubleAc cos(const DoubleAc &f)
DoubleAc pow(const DoubleAc &f, double p)
DoubleAc sqrt(const DoubleAc &f)
DoubleAc sin(const DoubleAc &f)
DoubleAc exp(const DoubleAc &f)
DoubleAc fabs(const DoubleAc &f)
bool GetVoltageRange(double &pmin, double &pmax)
void AddPlaneX(const double x, const double voltage, const std::string label)
void AddWire(const double x, const double y, const double diameter, const double voltage, const std::string label, const double length=100., const double tension=50., const double rho=19.3, const int ntrap=5)
void SetPeriodicityX(const double s)
bool IsInTrapRadius(double x0, double y0, double z0, double &xw, double &yx, double &rw)
bool GetPeriodicityY(double &s)
void AddCharge(const double x, const double y, const double z, const double q)
void AddReadout(const std::string label)
void AddStripOnPlaneX(const char direction, const double x, const double smin, const double smax, const std::string label, const double gap=-1.)
void AddTube(const double radius, const double voltage, const int nEdges, const std::string label)
bool IsWireCrossed(double x0, double y0, double z0, double x1, double y1, double z1, double &xc, double &yc, double &zc)
bool GetPlaneX(const int i, double &x, double &voltage, std::string &label)
bool GetPeriodicityX(double &s)
void WeightingField(const double x, const double y, const double z, double &wx, double &wy, double &wz, const std::string label)
void AddStripOnPlaneY(const char direction, const double y, const double smin, const double smax, const std::string label, const double gap=-1.)
bool GetBoundingBox(double &x0, double &y0, double &z0, double &x1, double &y1, double &z1)
void AddPlaneY(const double y, const double voltage, const std::string label)
double WeightingPotential(const double x, const double y, const double z, const std::string label)
bool GetWire(const int i, double &x, double &y, double &diameter, double &voltage, std::string &label, double &length, double &charge, int &ntrap)
void ElectricField(const double x, const double y, const double z, double &ex, double &ey, double &ez, Medium *&m, int &status)
void SetPeriodicityY(const double s)
bool GetPlaneY(const int i, double &y, double &voltage, std::string &label)
bool GetTube(double &r, double &voltage, int &nEdges, std::string &label)
GeometryBase * theGeometry
virtual Medium * GetMedium(const double &x, const double &y, const double &z)
virtual bool GetBoundingBox(double &xmin, double &ymin, double &zmin, double &xmax, double &ymax, double &zmax)=0
double BesselK0L(const double xx)
double BesselK1S(const double xx)
void Cinv(const int n, std::vector< std::vector< std::complex< double > > > &a, int &ifail)
double BesselK0S(const double xx)
void Deqinv(const int n, std::vector< std::vector< double > > &a, int &ifail, std::vector< double > &b)
double BesselK1L(const double xx)