18 std::vector<double> d,
const double V,
19 std::vector<int> sigmaIndex) {
22 std::vector<double> placeHolder(N + 1, 0);
24 const int Nholder1 = eps.size();
25 const int Nholder2 = d.size();
26 if (N != Nholder1 || N != Nholder2) {
28 <<
"::Inconsistency between the number of layers, permittivities "
29 "and thicknesses given.\n";
34 <<
"::Setup:: Number of layers must be larger then 1.\n";
47 if (sigmaIndex.size() == 0) {
48 for (
int i = 0; i < N; i++) {
49 if (eps[i] != 1) sigmaIndex.push_back(i + 1);
53 m_sigmaIndex = sigmaIndex;
55 std::vector<double> m_zHolder(N + 1);
57 for (
int i = 1; i <= N; i++) {
58 m_zHolder[i] = m_zHolder[i - 1] + m_dHolder[i - 1];
62 <<
":: z = " << m_zHolder[i]
63 <<
", epsr = " << m_epsHolder[i - 1] <<
".\n";
68 constructGeometryMatrices(m_N);
72 <<
"Setup:: Computing weighting potential functions.\n";
74 setwpStripIntegrand();
75 setwpPixelIntegrand();
77 std::cout <<
m_className <<
"Setup:: Geometry with N = " << N
82 double &x1,
double &y1,
88 if (
m_geometry->GetBoundingBox(x0, y0, z0, x1, y1, z1))
return true;
90 z0 = -std::numeric_limits<double>::infinity();
91 x0 = -std::numeric_limits<double>::infinity();
92 z1 = +std::numeric_limits<double>::infinity();
93 x1 = +std::numeric_limits<double>::infinity();
100double ComponentParallelPlate::IntegratePromptPotential(
const Electrode &el,
105 case structureelectrode::Plane: {
109 case structureelectrode::Pixel: {
110 m_wpPixelIntegral.SetParameters(x, y, el.xpos, el.ypos, el.lx, el.ly,
115 if (!m_getPotentialInPlate && epsm != 1)
return 0.;
116 double upLim = m_upperBoundIntegration;
117 if (z == 0 || m_upperBoundIntegration / z > 200) {
122 return m_wpPixelIntegral.Integral(0, upLim, 0, upLim, m_precision);
125 case structureelectrode::Strip: {
126 m_wpStripIntegral.SetParameters(x, el.xpos, el.lx, z);
130 if (!m_getPotentialInPlate && epsm != 1)
return 0.;
131 double upLim = m_upperBoundIntegration;
132 if (z == 0 || m_upperBoundIntegration / z > 200) {
137 return m_wpStripIntegral.Integral(0, upLim, m_precision);
141 std::cerr <<
m_className <<
"::IntegratePromptPotential:\n"
142 <<
" Unknown electrode type.\n";
149 const double z,
double &ex,
150 double &ey,
double &ez,
Medium *&m,
160 std::cout <<
m_className <<
"::ElectricField: Not inside geometry.\n";
165 ey = constEFieldLayer(im);
171 std::cout <<
m_className <<
"::ElectricField: No medium at (" << x <<
", "
172 << y <<
", " << z <<
").\n";
186 const double z,
double &ex,
187 double &ey,
double &ez,
double &v,
188 Medium *&m,
int &status) {
191 ex = ey = ez = v = 0;
197 std::cout <<
m_className <<
"::ElectricField: Not inside geometry.\n";
202 ey = constEFieldLayer(im);
204 v = -m_V - (y - m_z[im - 1]) * constEFieldLayer(im);
205 for (
int i = 1; i <= im - 1; i++) {
206 v -= (m_z[i] - m_z[i - 1]) * constEFieldLayer(i);
213 std::cout <<
m_className <<
"::ElectricField: No medium at (" << x <<
", "
214 << y <<
", " << z <<
").\n";
228 if (m_V == 0)
return false;
243 const std::string &label) {
249 for (
auto &electrode : m_readout_p) {
250 if (electrode.label == label) {
252 if (!electrode.formAnode) yin = m_z.back() - y;
253 if (!electrode.m_usegrid) {
254 ret += IntegratePromptPotential(electrode, z, x, yin);
256 ret += FindWeightingPotentialInGrid(electrode, z, x, yin);
263void ComponentParallelPlate::Reset() {
272 m_sigmaIndex.clear();
283void ComponentParallelPlate::UpdatePeriodicity() {
285 std::cerr <<
m_className <<
"::UpdatePeriodicity:\n"
286 <<
" Periodicities are not supported.\n";
291 double lz_input,
const std::string &label,
296 const auto it = std::find(m_readout.cbegin(), m_readout.cend(), label);
297 if (it != m_readout.end() && m_readout.size() > 0) {
299 <<
"Note that the label " << label <<
" is already in use.\n";
303 pixel.ind = structureelectrode::Pixel;
309 pixel.formAnode = anode;
311 m_readout.push_back(label);
312 m_readout_p.push_back(std::move(pixel));
313 std::cout <<
m_className <<
"::AddPixel: Added pixel electrode.\n";
317 const std::string &label,
bool anode) {
318 const auto it = std::find(m_readout.cbegin(), m_readout.cend(), label);
319 if (it != m_readout.end() && m_readout.size() > 0) {
321 <<
"Note that the label " << label <<
" is already in use.\n";
325 strip.ind = structureelectrode::Strip;
329 strip.formAnode = anode;
331 m_readout.push_back(label);
332 m_readout_p.push_back(std::move(strip));
334 std::cout <<
m_className <<
"::AddStrip: Added strip electrode.\n";
338 const auto it = std::find(m_readout.cbegin(), m_readout.cend(), label);
339 if (it != m_readout.end() && m_readout.size() > 0) {
341 <<
"Note that the label " << label <<
" is already in use.\n";
345 plate.ind = structureelectrode::Plane;
347 plate.formAnode = anode;
349 m_readout.push_back(label);
350 m_readout_p.push_back(std::move(plate));
352 std::cout <<
m_className <<
"::AddPlane: Added plane electrode.\n";
359 }
else if (m_medium) {
365bool ComponentParallelPlate::Nsigma(
366 int N, std::vector<std::vector<int>> &sigmaMatrix) {
368 int nRow = pow(2, N - 1);
370 std::vector<int> binaryNum(nCol, 0);
372 for (
int i = 0; i < nRow; i++) {
373 if (decToBinary(i, binaryNum)) {
374 sigmaMatrix.push_back(binaryNum);
375 std::reverse(sigmaMatrix[i].begin(), sigmaMatrix[i].end());
376 std::for_each(sigmaMatrix[i].begin(), sigmaMatrix[i].end(),
377 [](
int &n) { n = 1 - 2 * n; });
383bool ComponentParallelPlate::Ntheta(
384 int N, std::vector<std::vector<int>> &thetaMatrix,
385 std::vector<std::vector<int>> &sigmaMatrix) {
387 int nRow =
pow(2, N - 1);
389 std::vector<int> thetaRow(nCol, 1);
390 std::vector<int> thetaRowReset(nCol, 1);
392 for (
int i = 0; i < nRow; i++) {
393 for (
int j = 0; j < nCol; j++) {
394 for (
int l = j; l < nCol; l++) thetaRow[j] *= sigmaMatrix[i][l];
396 thetaMatrix.push_back(thetaRow);
397 thetaRow = thetaRowReset;
402void ComponentParallelPlate::constructGeometryMatrices(
const int N) {
406 std::vector<std::vector<int>> sigmaMatrix;
407 std::vector<std::vector<int>> thetaMatrix;
409 for (
int n = 1; n <= nRow; n++) {
411 Nsigma(n, sigmaMatrix);
412 Ntheta(n, thetaMatrix, sigmaMatrix);
414 m_sigmaMatrix.push_back(sigmaMatrix);
415 m_thetaMatrix.push_back(thetaMatrix);
422void ComponentParallelPlate::constructGeometryFunction(
const int N) {
425 int nCol =
pow(2, N - 1);
432 std::vector<double> cHold(nCol, 1);
433 std::vector<double> vHold(nCol, 0);
434 std::vector<double> gHold(nCol, 1);
435 std::vector<double> wHold(nCol, 0);
437 for (
int n = 1; n <= nRow; n++) {
441 for (
int i = 0; i < nCol; i++) {
443 if (ix1 ==
pow(2, n - 1)) ix1 = 0;
444 if (ix2 ==
pow(2, N - n)) ix2 = 0;
446 cHold[i] *= 1 /
pow(2, n - 1);
447 gHold[i] *= 1 /
pow(2, N - n);
450 for (
int j = 0; j < n - 1; j++) {
451 cHold[i] *= (m_eps[j] + m_sigmaMatrix[n - 1][ix1][j] * m_eps[j + 1]) /
453 vHold[i] += (m_thetaMatrix[n - 1][ix1][j] - 1) * m_d[j];
457 for (
int j = 0; j < N - n; j++) {
458 gHold[i] *= (m_eps[N - j - 1] +
459 m_sigmaMatrix[N - n][ix2][j] * m_eps[N - j - 2]) /
461 wHold[i] += (m_thetaMatrix[N - n][ix2][j] - 1) * m_d[N - 1 - j];
468 m_cMatrix.push_back(cHold);
469 m_vMatrix.push_back(vHold);
470 m_gMatrix.push_back(gHold);
471 m_wMatrix.push_back(wHold);
474 std::fill(cHold.begin(), cHold.end(), 1);
475 std::fill(vHold.begin(), vHold.end(), 0);
476 std::fill(gHold.begin(), gHold.end(), 1);
477 std::fill(wHold.begin(), wHold.end(), 0);
481void ComponentParallelPlate::setHIntegrand() {
482#if __cplusplus > 201703L
483 auto hFunction = [=,
this](
double *k,
double * ) {
485 auto hFunction = [=](
double *k,
double * ) {
495 if (!
getLayer(z, im, epsM))
return 0.;
496 LayerUpdate(z, im, epsM);
498 for (
int i = 0; i <
pow(2, m_N - im - 1); i++) {
499 h += m_gMatrix[im][i] * sinh(kk * (m_wMatrix[im][i] + m_z.back() - z));
501 for (
int i = 0; i <
pow(2, m_N - 1); i++) {
502 hNorm += m_cMatrix[m_N - 1][i] *
503 sinh(kk * (m_vMatrix[m_N - 1][i] + m_z.back()));
505 return h * m_eps[0] / (m_eps[m_N - 1] * hNorm);
507 TF2 *hF =
new TF2(
"hFunction", hFunction, 0, m_upperBoundIntegration, 0,
510 hF->Copy(m_hIntegrand);
515void ComponentParallelPlate::setwpPixelIntegrand() {
517#if __cplusplus > 201703L
518 auto intFunction = [=,
this](
double *k,
double *p) {
520 auto intFunction = [=](
double *k,
double *p) {
525 double K =
sqrt(kx * kx + ky * ky);
535 double sol =
cos(kx * (x - x0)) *
sin(kx * wx / 2) *
cos(ky * (y - y0)) *
536 sin(ky * wy / 2) * m_hIntegrand.Eval(K, z) / (kx * ky);
538 return 4 * sol / (Pi * Pi);
541 TF2 *wpPixelIntegrand =
542 new TF2(
"wpPixelIntegrand", intFunction, 0, m_upperBoundIntegration, 0,
543 m_upperBoundIntegration, 7);
544 wpPixelIntegrand->SetNpx(
546 wpPixelIntegrand->SetNpy(10000);
547 wpPixelIntegrand->Copy(m_wpPixelIntegral);
549 delete wpPixelIntegrand;
552void ComponentParallelPlate::setwpStripIntegrand() {
554#if __cplusplus > 201703L
555 auto intFunction = [=,
this](
double *k,
double *p) {
557 auto intFunction = [=](
double *k,
double *p) {
565 cos(kk * (x - x0)) *
sin(kk * wx / 2) * m_hIntegrand.Eval(kk, z) / kk;
568 TF1 *wpStripIntegrand =
569 new TF1(
"wpStripIntegrand", intFunction, 0, m_upperBoundIntegration, 4);
570 wpStripIntegrand->SetNpx(
572 wpStripIntegrand->Copy(m_wpStripIntegral);
574 delete wpStripIntegrand;
577bool ComponentParallelPlate::decToBinary(
int n, std::vector<int> &binaryNum) {
578 int L = binaryNum.size();
584 <<
"::decToBinary: Size of binary exceeds amount of colomb.\n";
588 binaryNum[i] = n % 2;
596 const double xmin,
const double xmax,
const double xsteps,
597 const double ymin,
const double ymax,
const double ysteps,
598 const double zmin,
const double zmax,
const double zsteps,
599 const std::string &label) {
601 for (
auto &electrode : m_readout_p) {
602 if (electrode.label == label) {
603 if (electrode.m_usegrid) {
605 <<
"::SetWeightingPotentialGrid: Overwriting grid.\n";
608 if (electrode.grid.SetMesh(xsteps, ysteps, zsteps, xmin, xmax, ymin, ymax,
610 std::cerr <<
m_className <<
"::SetWeightingPotentialGrid: Mesh set for "
611 << label <<
" (for " << xsteps *ysteps *zsteps
615 electrode.grid.SaveWeightingField(
this, label, label +
"map",
"xyz");
623 const double xmin,
const double xmax,
const double xsteps,
624 const double ymin,
const double ymax,
const double ysteps,
625 const double zmin,
const double zmax,
const double zsteps) {
627 for (
auto &electrode : m_readout_p) {
629 zmax, zsteps, electrode.label);
633double ComponentParallelPlate::FindWeightingPotentialInGrid(Electrode &el,
637 return el.grid.WeightingPotential(y, z, x, el.label);
void AddPlane(const std::string &label, bool fromAnode=true)
ComponentParallelPlate()
Constructor.
void AddStrip(double z, double lz, const std::string &label, bool fromAnode=true)
Add strip electrode.
double WeightingPotential(const double x, const double y, const double z, const std::string &label) override
void LoadWeightingPotentialGrid(const std::string &label)
void SetWeightingPotentialGrids(const double xmin, const double xmax, const double xsteps, const double ymin, const double ymax, const double ysteps, const double zmin, const double zmax, const double zsteps)
void Setup(const int N, std::vector< double > eps, std::vector< double > d, const double V, std::vector< int > sigmaIndex={})
void ElectricField(const double x, const double y, const double z, double &ex, double &ey, double &ez, Medium *&m, int &status) override
void SetWeightingPotentialGrid(const double xmin, const double xmax, const double xsteps, const double ymin, const double ymax, const double ysteps, const double zmin, const double zmax, const double zsteps, const std::string &label)
Medium * GetMedium(const double x, const double y, const double z) override
Get the medium at a given location (x, y, z).
bool getLayer(const double y, int &m, double &epsM)
bool GetVoltageRange(double &vmin, double &vmax) override
Calculate the voltage range [V].
void AddPixel(double x, double z, double lx, double lz, const std::string &label, bool fromAnode=true)
bool GetBoundingBox(double &xmin, double &ymin, double &zmin, double &xmax, double &ymax, double &zmax) override
Get the bounding box coordinates.
bool m_debug
Switch on/off debugging messages.
Component()=delete
Default constructor.
std::string m_className
Class name.
Geometry * m_geometry
Pointer to the geometry.
Abstract base class for media.
DoubleAc cos(const DoubleAc &f)
DoubleAc pow(const DoubleAc &f, double p)
DoubleAc sin(const DoubleAc &f)
DoubleAc sqrt(const DoubleAc &f)