Analysis Software
Documentation for sPHENIX simulation software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
Rossegger.cc
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file Rossegger.cc
1 #include "Rossegger.h"
2 
3 #include <TFile.h>
4 #include <TMath.h>
5 #include <TTree.h>
6 
7 #pragma GCC diagnostic push
8 #pragma GCC diagnostic ignored "-Wshadow"
9 #include <boost/math/special_functions.hpp> //covers all the special functions.
10 #pragma GCC diagnostic pop
11 
12 #include <algorithm> // for max
13 #include <cassert> // for assert
14 #include <cmath>
15 #include <cstdlib> // for exit, abs
16 #include <fstream>
17 #include <iostream>
18 #include <sstream>
19 #include <string>
20 
21 // the limu and kimu terms, that i need to think about a little while longer...
22 extern "C"
23 {
24  void dkia_(int *IFAC, double *X, double *A, double *DKI, double *DKID, int *IERRO);
25  void dlia_(int *IFAC, double *X, double *A, double *DLI, double *DLID, int *IERRO);
26 }
27 //
28 
29 // Bessel Function J_n(x):
30 #define jn(order, x) boost::math::cyl_bessel_j(order, x)
31 // Bessel (Neumann) Function Y_n(x):
32 #define yn(order, x) boost::math::cyl_neumann(order, x)
33 // Modified Bessel Function of the first kind I_n(x):
34 #define in(order, x) boost::math::cyl_bessel_i(order, x)
35 // Modified Bessel Function of the second kind K_n(x):
36 #define kn(order, x) boost::math::cyl_bessel_k(order, x)
37 #define limu(im_order, x) Rossegger::Limu(im_order, x)
38 #define kimu(im_order, x) Rossegger::Kimu(im_order, x)
39 
40 /*
41  This is a modified/renamed copy of Carlos and Tom's "Spacecharge" class, modified to use boost instead of fortran routines, and with phi terms added.
42  */
43 
44 Rossegger::Rossegger(double InnerRadius, double OuterRadius, double Rdo_Z, double precision)
45 {
46  a = InnerRadius;
47  b = OuterRadius;
48  L = Rdo_Z;
49 
51 
52  verbosity = 0;
53  pi = M_PI;
54 
56 
57  // load the greens functions:
58  char zeroesfilename[200];
59  sprintf(zeroesfilename, "rosseger_zeroes_eps%1.0E_a%2.2f_b%2.2f_L%2.2f.root", epsilon, a, b, L);
60  TFile *fileptr = TFile::Open(zeroesfilename, "READ");
61  if (!fileptr)
62  { // generate the lookuptable
65  SaveZeroes(zeroesfilename);
66  }
67  else
68  { // load it from a file
69  fileptr->Close();
70  LoadZeroes(zeroesfilename);
71  }
72 
74 
75  std::cout << "Rossegger object initialized as follows:" << std::endl;
76  std::cout << " Inner Radius = " << a << " cm." << std::endl;
77  std::cout << " Outer Radius = " << b << " cm." << std::endl;
78  std::cout << " Half Length = " << L << " cm." << std::endl;
79 
80  if (!CheckZeroes(0.01))
81  {
82  std::cout << "CheckZeroes(0.01) returned false, exiting" << std::endl;
83  exit(1);
84  }
85  return;
86 }
87 
88 double Rossegger::FindNextZero(double xstart, double localepsilon, int order, double (Rossegger::*func)(int, double))
89 {
90  double previous = (this->*func)(order, xstart);
91  double x = xstart + localepsilon;
92  double value = previous;
93 
94  while (!((value == 0) || (value < 0 && previous > 0) || (value > 0 && previous < 0)))
95  {
96  // Rossegger equation 5.12
97  value = (this->*func)(order, x);
98  if (value == 0)
99  {
100  std::cout << "hit it exactly! Go buy a lottery ticket!" << std::endl;
101  }
102  if ((value == 0) || (value < 0 && previous > 0) || (value > 0 && previous < 0))
103  {
104  // when we go from one sign to the other, we have bracketed the zero
105  // the following is mathematically equivalent to finding the delta
106  // between the x of our previous value and the point where we cross the axis
107  // then returning x0=x_old+delta
108  double slope = (value - previous) / localepsilon;
109  double intercept = value - slope * x;
110  double x0 = -intercept / slope;
111  if (verbosity > 1)
112  {
113  std::cout << " " << x0 << "," << std::endl;
114  }
115  double n0 = (this->*func)(order, x - localepsilon);
116  double n1 = (this->*func)(order, x + localepsilon);
117  if ((n0 < 0 && n1 < 0) || (n0 > 0 && n1 > 0))
118  {
119  printf("neighbors on both sides have the same sign. Check your function resolution!\n");
120  }
121 
122  return x0;
123  }
124  previous = value;
125  x += localepsilon;
126  }
127  std::cout << "logic break!\n";
128  assert(1 == 2);
129  return 0;
130 }
131 
132 void Rossegger::FindBetamn(double localepsilon)
133 {
134  std::cout << "Now filling the Beta[m][n] Array..." << std::endl;
135  if (verbosity > 5)
136  {
137  std::cout << "numberOfOrders= " << NumberOfOrders << std::endl;
138  }
139  for (int m = 0; m < NumberOfOrders; m++)
140  {
141  if (verbosity)
142  {
143  std::cout << "Filling Beta[" << m << "][n]..." << std::endl;
144  }
145 
146  double x = localepsilon;
147  for (int n = 0; n < NumberOfOrders; n++)
148  { // !!! Off by one from Rossegger convention !!!
149  x = FindNextZero(x, localepsilon, m, &Rossegger::Rmn_for_zeroes);
150  Betamn[m][n] = x / b;
151  x += localepsilon;
152  }
153  }
154 
155  // Now fill in the N2mn array...
156  for (int m = 0; m < NumberOfOrders; m++)
157  {
158  for (int n = 0; n < NumberOfOrders; n++)
159  {
160  // Rossegger Equation 5.17
161  // N^2_mn = 2/(pi * beta)^2 [ {Jm(beta a)/Jm(beta b)}^2 - 1 ]
162  N2mn[m][n] = 2 / (pi * pi * Betamn[m][n] * Betamn[m][n]);
163  // N2mn[m][n] *= (jn(m,Betamn[m][n]*a)*jn(m,Betamn[m][n]*a)/jn(m,Betamn[m][n]*b)/jn(m,Betamn[m][n]*b) - 1.0);
164  double jna_over_jnb = jn(m, Betamn[m][n] * a) / jn(m, Betamn[m][n] * b);
165  N2mn[m][n] *= (jna_over_jnb * jna_over_jnb - 1.0);
166  // rcc note! in eq 5.17, N2nm is set with betamn[m][n], but from context that looks to be a typo. The order is mn everywhere else
167  if (verbosity > 1)
168  {
169  std::cout << "m: " << m << " n: " << n << " N2[m][n]: " << N2mn[m][n];
170  }
171  double step = 0.01;
172  if (verbosity > 1)
173  {
174  double integral = 0.0;
175  for (double r = a; r < b; r += step)
176  {
177  double rmnval = Rmn(m, n, r);
178 
179  integral += rmnval * rmnval * r * step; // Rmn(m,n,r)*Rmn(m,n,r)*r*step;
180  }
181  std::cout << " Int: " << integral << std::endl;
182  }
183  // N2mn[m][n] = integral;
184  }
185  }
186 
187  std::cout << "Done." << std::endl;
188 }
189 
190 void Rossegger::FindMunk(double localepsilon)
191 {
192  std::cout << "Now filling the Mu[n][k] Array..." << std::endl;
193  if (verbosity > 5)
194  {
195  std::cout << "numberOfOrders= " << NumberOfOrders << std::endl;
196  }
197  // We're looking for the zeroes of Rossegger eqn. 5.46:
198  // R_nk(mu_nk;a,b)=Limu(Beta_n*a)Kimu(Beta_n*b)-Kimu(Beta_n*a)Limu(Beta_n*b)=0
199  // since a and b are fixed, R_nk is a function solely of mu_nk and n.
200  // for each 'n' we wish to find the a set of k mu_n's that result in R_nk=0
201 
202  // could add an option here to load the munks from file if the dimensions match.
203 
204  for (int n = 0; n < NumberOfOrders; n++) // !!! Off by one from Rossegger convention !!!
205  {
206  if (verbosity)
207  {
208  std::cout << "Filling Mu[" << n << "][k]..." << std::endl;
209  }
210  double x = localepsilon;
211  for (int k = 0; k < NumberOfOrders; k++)
212  {
213  x = FindNextZero(x, localepsilon, n, &Rossegger::Rnk_for_zeroes);
214  Munk[n][k] = x;
215  x += localepsilon;
216  if (verbosity > 0)
217  {
218  printf("Mu[%d][%d]=%E\n", n, k, Munk[n][k]);
219  printf("adjacent values are Rnk[mu-localepsilon]=%E\tRnk[mu+localepsilon]=%E\n",
220  Rnk_for_zeroes(n, x - localepsilon), Rnk_for_zeroes(n, x + localepsilon));
221  if (verbosity > 100)
222  {
223  printf("values of argument to limu and kimu are %f and %f\n",
224  (n + 1) * pi / L * a, (n + 1) * pi / L * b);
225  }
226  }
227  }
228  }
229 
230  // Now fill in the N2nk array...
231  for (int n = 0; n < NumberOfOrders; n++)
232  {
233  for (int k = 0; k < NumberOfOrders; k++)
234  {
235  // Rossegger Equation 5.48
236  // Integral of R_nk(r)*R_ns(r) dr/r= delta_ks*N2nk
237  // note that unlike N2mn, there is no convenient shortcut here.
238  double integral = 0.0;
239  double step = 0.001;
240 
241  for (double r = a; r < b; r += step)
242  {
243  double rnkval = Rnk_(n, k, r); // must used un-optimized. We don't have those values yet...
244 
245  integral += rnkval * rnkval / r * step;
246  }
247  if (verbosity > 1)
248  {
249  std::cout << " Int: " << integral << std::endl;
250  }
251  N2nk[n][k] = integral;
252  if (verbosity > 1)
253  {
254  std::cout << "n: " << n << " k: " << k << " N2nk[n][k]: " << N2nk[n][k];
255  }
256  }
257  }
258 
259  std::cout << "Done." << std::endl;
260  return;
261 }
262 
263 bool Rossegger::CheckZeroes(double localepsilon)
264 {
265  // confirm that the tabulated zeroes are all zeroes of their respective functions:
266  double result;
267  for (int m = 0; m < NumberOfOrders; m++)
268  {
269  for (int n = 0; n < NumberOfOrders; n++)
270  { // !!! Off by one from Rossegger convention !!!
271  result = Rmn_for_zeroes(m, Betamn[m][n] * b);
272  if (abs(result) > localepsilon)
273  {
274  printf("(m=%d,n=%d) Jm(x)Ym(lx)-Jm(lx)Ym(x) = %f for x=b*%f\n", m, n, result, Betamn[m][n]);
275  return false;
276  }
277  }
278  }
279 
280  // R_nk(mu_nk;a,b)=Limu(Beta_n*a)Kimu(Beta_n*b)-Kimu(Beta_n*a)Limu(Beta_n*b)=0
281  for (int n = 0; n < NumberOfOrders; n++)
282  {
283  for (int k = 0; k < NumberOfOrders; k++)
284  { // !!! Off by one from Rossegger convention !!!
285  result = Rnk_for_zeroes(n, Munk[n][k]);
286  if (abs(result) > localepsilon * 100)
287  {
288  printf("(n=%d,k=%d) limu(npi*a/L)kimu(npi*b/L)-kimu(npi*a/L)kimu(npi*b/L) = %f (>eps*100) for mu=%f\n",
289  n, k, result, Munk[n][k]);
290  return false;
291  }
292  }
293  }
294 
295  return true;
296 }
297 
299 { // Routine used to fill the arrays of other values used repeatedly
300  // these constants depend only on the geometry of the detector
301  printf("Precalcing %d geometric constants\n", 3 * NumberOfOrders + 5 * NumberOfOrders * NumberOfOrders);
302  for (int n = 0; n < NumberOfOrders; n++)
303  {
304  BetaN[n] = (n + 1) * pi / L; // BetaN=(n+1)*pi/L as used in eg 5.32, .46
305  BetaN_a[n] = BetaN[n] * a; // BetaN*a as used in eg 5.32, .46
306  BetaN_b[n] = BetaN[n] * b; // BetaN*b as used in eg 5.32, .46
307  for (int m = 0; m < NumberOfOrders; m++)
308  {
309  km_BetaN_a[m][n] = kn(m, BetaN_a[n]); // kn(m,BetaN*a) as used in Rossegger 5.32
310  im_BetaN_a[m][n] = in(m, BetaN_a[n]); // in(m,BetaN*a) as used in Rossegger 5.32
311  km_BetaN_b[m][n] = kn(m, BetaN_b[n]); // kn(m,BetaN*b) as used in Rossegger 5.33
312  im_BetaN_b[m][n] = in(m, BetaN_b[n]); // in(m,BetaN*b) as used in Rossegger 5.33
313  bessel_denominator[m][n] = TMath::BesselI(m, BetaN_a[n]) * TMath::BesselK(m, BetaN_b[n]) - TMath::BesselI(m, BetaN_b[n]) * TMath::BesselK(m, BetaN_a[n]); // TMath::BesselI(m,BetaN*a)*TMath::BesselK(m,BetaN*b)-TMath::BesselI(m,BetaN*b)*TMath::BesselK(m,BetaN*a) as in Rossegger 5.65
314  }
315  }
316  return;
317 }
319 { // Routine used to fill the arrays of other values used repeatedly
320  // these constants depend on geometry and the zeroes of special functions
321  printf("Precalcing %d geometric constants\n", 6 * NumberOfOrders * NumberOfOrders);
322 
323  for (int n = 0; n < NumberOfOrders; n++)
324  {
325  for (int m = 0; m < NumberOfOrders; m++)
326  {
327  ym_Betamn_a[m][n] = yn(m, Betamn[m][n] * a); // yn(m,Betamn[m][n]*a) as used in Rossegger 5.11
328  jm_Betamn_a[m][n] = jn(m, Betamn[m][n] * a); // jn(m,Betamn[m][n]*a) as used in Rossegger 5.11
329  sinh_Betamn_L[m][n] = sinh(Betamn[m][n] * L); // sinh(Betamn[m][n]*L) as in Rossegger 5.64
330  }
331  for (int k = 0; k < NumberOfOrders; k++)
332  {
333  liMunk_BetaN_a[n][k] = limu(Munk[n][k], BetaN_a[n]); // limu(Munk[n][k],BetaN*a) as used in Rossegger 5.45
334  kiMunk_BetaN_a[n][k] = kimu(Munk[n][k], BetaN_a[n]); // kimu(Munk[n][k],BetaN*a) as used in Rossegger 5.45
335  sinh_pi_Munk[n][k] = sinh(pi * Munk[n][k]); // sinh(pi*Munk[n][k]) as in Rossegger 5.66
336  }
337  }
338  return;
339 }
340 
341 double Rossegger::Limu(double mu, double x)
342 {
343  // defined in Rossegger eqn 5.44, also a canonical 'satisfactory companion' to Kimu.
344  // could use Griddit?
345  // Rossegger Equation 5.45
346  // Rnk(r) = Limu_nk (BetaN a) Kimu_nk (BetaN r) - Kimu_nk(BetaN a) Limu_nk (BetaN r)
347 
348  int IFAC = 1;
349  double A = mu;
350  double DLI = 0;
351  double DERR = 0;
352  int IERRO = 0;
353 
354  double X = x;
355  dlia_(&IFAC, &X, &A, &DLI, &DERR, &IERRO);
356  return DLI;
357 }
358 double Rossegger::Kimu(double mu, double x)
359 {
360  int IFAC = 1;
361  double A = mu;
362  double DKI = 0;
363  double DERR = 0;
364  int IERRO = 0;
365 
366  double X = x;
367  dkia_(&IFAC, &X, &A, &DKI, &DERR, &IERRO);
368  return DKI;
369 }
370 
371 double Rossegger::Rmn_for_zeroes(int m, double x)
372 {
373  double lx = a * x / b;
374  // Rossegger Equation 5.12:
375 
376  return jn(m, x) * yn(m, lx) - jn(m, lx) * yn(m, x);
377 }
378 
379 double Rossegger::Rmn(int m, int n, double r)
380 {
381  if (verbosity > 100)
382  {
383  std::cout << "Determine Rmn(" << m << "," << n << "," << r << ") = ";
384  }
385 
386  // Check input arguments for sanity...
387  int error = 0;
388  if (m < 0 || m >= NumberOfOrders)
389  {
390  error = 1;
391  }
392  if (n < 0 || n >= NumberOfOrders)
393  {
394  error = 1;
395  }
396  if (r < a || r > b)
397  {
398  error = 1;
399  }
400  if (error)
401  {
402  std::cout << "Invalid arguments Rmn(" << m << "," << n << "," << r << ")" << std::endl;
403  ;
404  return 0;
405  }
406 
407  // Calculate the function using C-libraries from boost
408  // Rossegger Equation 5.11:
409  // Rmn(r) = Ym(Beta_mn a)*Jm(Beta_mn r) - Jm(Beta_mn a)*Ym(Beta_mn r)
410  double R = 0;
411  R = ym_Betamn_a[m][n] * jn(m, Betamn[m][n] * r) - jm_Betamn_a[m][n] * yn(m, Betamn[m][n] * r);
412 
413  if (verbosity > 100)
414  {
415  std::cout << R << std::endl;
416  }
417  return R;
418 }
419 
420 double Rossegger::Rmn_(int m, int n, double r)
421 {
422  if (verbosity > 100)
423  {
424  std::cout << "Determine Rmn(" << m << "," << n << "," << r << ") = ";
425  }
426 
427  // Check input arguments for sanity...
428  int error = 0;
429  if (m < 0 || m >= NumberOfOrders)
430  {
431  error = 1;
432  }
433  if (n < 0 || n >= NumberOfOrders)
434  {
435  error = 1;
436  }
437  if (r < a || r > b)
438  {
439  error = 1;
440  }
441  if (error)
442  {
443  std::cout << "Invalid arguments Rmn(" << m << "," << n << "," << r << ")" << std::endl;
444  ;
445  return 0;
446  }
447 
448  // Calculate the function using C-libraries from boost
449  // Rossegger Equation 5.11:
450  // Rmn(r) = Ym(Beta_mn a)*Jm(Beta_mn r) - Jm(Beta_mn a)*Ym(Beta_mn r)
451  double R = 0;
452  R = yn(m, Betamn[m][n] * a) * jn(m, Betamn[m][n] * r) - jn(m, Betamn[m][n] * a) * yn(m, Betamn[m][n] * r);
453 
454  if (verbosity > 100)
455  {
456  std::cout << R << std::endl;
457  }
458  return R;
459 }
460 
461 double Rossegger::Rmn1(int m, int n, double r)
462 {
463  // Check input arguments for sanity...
464  int error = 0;
465  if (m < 0 || m >= NumberOfOrders)
466  {
467  error = 1;
468  }
469  if (n < 0 || n >= NumberOfOrders)
470  {
471  error = 1;
472  }
473  if (r < a || r > b)
474  {
475  error = 1;
476  }
477  if (error)
478  {
479  std::cout << "Invalid arguments Rmn1(" << m << "," << n << "," << r << ")" << std::endl;
480  ;
481  return 0;
482  }
483 
484  // Calculate using the TMath functions from root.
485  // Rossegger Equation 5.32
486  // Rmn1(r) = Km(BetaN a)Im(BetaN r) - Im(BetaN a) Km(BetaN r)
487  double R = 0;
488  R = km_BetaN_a[m][n] * in(m, BetaN[n] * r) - im_BetaN_a[m][n] * kn(m, BetaN[n] * r);
489 
490  return R;
491 }
492 
493 double Rossegger::Rmn1_(int m, int n, double r)
494 {
495  // Check input arguments for sanity...
496  int error = 0;
497  if (m < 0 || m >= NumberOfOrders)
498  {
499  error = 1;
500  }
501  if (n < 0 || n >= NumberOfOrders)
502  {
503  error = 1;
504  }
505  if (r < a || r > b)
506  {
507  error = 1;
508  }
509  if (error)
510  {
511  std::cout << "Invalid arguments Rmn1(" << m << "," << n << "," << r << ")" << std::endl;
512  ;
513  return 0;
514  }
515 
516  // Calculate using the TMath functions from root.
517  // Rossegger Equation 5.32
518  // Rmn1(r) = Km(BetaN a)Im(BetaN r) - Im(BetaN a) Km(BetaN r)
519  double R = 0;
520  double BetaN_ = (n + 1) * pi / L;
521  R = kn(m, BetaN_ * a) * in(m, BetaN_ * r) - in(m, BetaN_ * a) * kn(m, BetaN_ * r);
522 
523  return R;
524 }
525 
526 double Rossegger::Rmn2(int m, int n, double r)
527 {
528  // Check input arguments for sanity...
529  int error = 0;
530  if (m < 0 || m >= NumberOfOrders)
531  {
532  error = 1;
533  }
534  if (n < 0 || n >= NumberOfOrders)
535  {
536  error = 1;
537  }
538  if (r < a || r > b)
539  {
540  error = 1;
541  }
542  if (error)
543  {
544  std::cout << "Invalid arguments Rmn2(" << m << "," << n << "," << r << ")" << std::endl;
545  ;
546  return 0;
547  }
548 
549  // Calculate using the TMath functions from root.
550  // Rossegger Equation 5.33
551  // Rmn2(r) = Km(BetaN b)Im(BetaN r) - Im(BetaN b) Km(BetaN r)
552  double R = 0;
553  R = km_BetaN_b[m][n] * in(m, BetaN[n] * r) - im_BetaN_b[m][n] * kn(m, BetaN[n] * r);
554 
555  return R;
556 }
557 
558 double Rossegger::Rmn2_(int m, int n, double r)
559 {
560  // Check input arguments for sanity...
561  int error = 0;
562  if (m < 0 || m >= NumberOfOrders)
563  {
564  error = 1;
565  }
566  if (n < 0 || n >= NumberOfOrders)
567  {
568  error = 1;
569  }
570  if (r < a || r > b)
571  {
572  error = 1;
573  }
574  if (error)
575  {
576  std::cout << "Invalid arguments Rmn2(" << m << "," << n << "," << r << ")" << std::endl;
577  ;
578  return 0;
579  }
580 
581  // Calculate using the TMath functions from root.
582  // Rossegger Equation 5.33
583  // Rmn2(r) = Km(BetaN b)Im(BetaN r) - Im(BetaN b) Km(BetaN r)
584  double R = 0;
585  double BetaN_ = (n + 1) * pi / L;
586  R = kn(m, BetaN_ * b) * in(m, BetaN_ * r) - in(m, BetaN_ * b) * kn(m, BetaN_ * r);
587 
588  return R;
589 }
590 
591 double Rossegger::RPrime(int m, int n, double ref, double r)
592 {
593  // Check input arguments for sanity...
594  int error = 0;
595  if (m < 0 || m >= NumberOfOrders)
596  {
597  error = 1;
598  }
599  if (n < 0 || n >= NumberOfOrders)
600  {
601  error = 1;
602  }
603  if (ref < a || ref > b)
604  {
605  error = 1;
606  }
607  if (r < a || r > b)
608  {
609  error = 1;
610  }
611  if (error)
612  {
613  std::cout << "Invalid arguments RPrime(" << m << "," << n << "," << ref << "," << r << ")" << std::endl;
614  ;
615  return 0;
616  }
617 
618  double R = 0;
619  // Calculate using the TMath functions from root.
620  // Rossegger Equation 5.65
621  // Rmn2(ref,r) = BetaN/2* [ Km(BetaN ref) {Im-1(BetaN r) + Im+1(BetaN r)}
622  // - Im(BetaN ref) {Km-1(BetaN r) + Km+1(BetaN r)} ]
623  // NOTE: K-m(z) = Km(z) and I-m(z) = Im(z)... though boost handles negative orders.
624  //
625  // with: s -> ref, t -> r,
626  double BetaN_ = BetaN[n];
627  double term1 = kn(m, BetaN_ * ref) * (in(m - 1, BetaN_ * r) + in(m + 1, BetaN_ * r));
628  double term2 = in(m, BetaN_ * ref) * (kn(m - 1, BetaN_ * r) + kn(m + 1, BetaN_ * r));
629  R = BetaN_ / 2.0 * (term1 + term2);
630 
631  return R;
632 }
633 
634 double Rossegger::RPrime_(int m, int n, double ref, double r)
635 {
636  // Check input arguments for sanity...
637  int error = 0;
638  if (m < 0 || m >= NumberOfOrders)
639  {
640  error = 1;
641  }
642  if (n < 0 || n >= NumberOfOrders)
643  {
644  error = 1;
645  }
646  if (ref < a || ref > b)
647  {
648  error = 1;
649  }
650  if (r < a || r > b)
651  {
652  error = 1;
653  }
654  if (error)
655  {
656  std::cout << "Invalid arguments RPrime(" << m << "," << n << "," << ref << "," << r << ")" << std::endl;
657  ;
658  return 0;
659  }
660 
661  double R = 0;
662  // Rossegger Equation 5.65
663  // Rmn2(ref,r) = BetaN/2* [ Km(BetaN ref) {Im-1(BetaN r) + Im+1(BetaN r)}
664  // - Im(BetaN ref) {Km-1(BetaN r) + Km+1(BetaN r)} ]
665  // NOTE: K-m(z) = Km(z) and I-m(z) = Im(z)... though boost handles negative orders.
666  //
667  // with: s -> ref, t -> r,
668  double BetaN_ = (n + 1) * pi / L;
669  double term1 = kn(m, BetaN_ * ref) * (in(m - 1, BetaN_ * r) + in(m + 1, BetaN_ * r));
670  double term2 = in(m, BetaN_ * ref) * (kn(m - 1, BetaN_ * r) + kn(m + 1, BetaN_ * r));
671  R = BetaN_ / 2.0 * (term1 + term2);
672 
673  return R;
674 }
675 
676 double Rossegger::Rnk_for_zeroes(int n, double mu)
677 {
678  // unlike Rossegger, we count 'k' and 'n' from zero.
679  if (verbosity > 10)
680  {
681  printf("Rnk_for_zeroes called with n=%d,mu=%f\n", n, mu);
682  }
683  double betana = BetaN_a[n];
684  double betanb = BetaN_b[n];
685  // Rossegger Equation 5.46
686  // Rnk(r) = Limu_nk (BetaN a) Kimu_nk (BetaN b) - Kimu_nk(BetaN a) Limu_nk (BetaN b)
687 
688  return limu(mu, betana) * kimu(mu, betanb) - kimu(mu, betana) * limu(mu, betanb);
689 }
690 
691 double Rossegger::Rnk_for_zeroes_(int n, double mu)
692 {
693  // unlike Rossegger, we count 'k' and 'n' from zero.
694  if (verbosity > 10)
695  {
696  printf("Rnk_for_zeroes called with n=%d,mu=%f\n", n, mu);
697  }
698  double BetaN_ = (n + 1) * pi / L; // this is defined in the paragraph before 5.46
699  double betana = BetaN_ * a;
700  double betanb = BetaN_ * b;
701  // Rossegger Equation 5.46
702  // Rnk(r) = Limu_nk (BetaN a) Kimu_nk (BetaN b) - Kimu_nk(BetaN a) Limu_nk (BetaN b)
703 
704  return limu(mu, betana) * kimu(mu, betanb) - kimu(mu, betana) * limu(mu, betanb);
705 }
706 
707 double Rossegger::Rnk(int n, int k, double r)
708 {
709  // Check input arguments for sanity...
710  int error = 0;
711  if (n < 0 || n >= NumberOfOrders)
712  {
713  error = 1;
714  }
715  if (k < 0 || k >= NumberOfOrders)
716  {
717  error = 1;
718  }
719  if (r < a || r > b)
720  {
721  error = 1;
722  }
723  if (error)
724  {
725  std::cout << "Invalid arguments Rnk(" << n << "," << k << "," << r << ")" << std::endl;
726  ;
727  return 0;
728  }
729  // Rossegger Equation 5.45
730  // Rnk(r) = Limu_nk (BetaN a) Kimu_nk (BetaN r) - Kimu_nk(BetaN a) Limu_nk (BetaN r)
731 
732  return liMunk_BetaN_a[n][k] * kimu(Munk[n][k], BetaN[n] * r) - kiMunk_BetaN_a[n][k] * limu(Munk[n][k], BetaN[n] * r);
733 }
734 
735 double Rossegger::Rnk_(int n, int k, double r)
736 {
737  // Check input arguments for sanity...
738  int error = 0;
739  if (n < 0 || n >= NumberOfOrders)
740  {
741  error = 1;
742  }
743  if (k < 0 || k >= NumberOfOrders)
744  {
745  error = 1;
746  }
747  if (r < a || r > b)
748  {
749  error = 1;
750  }
751  if (error)
752  {
753  std::cout << "Invalid arguments Rnk(" << n << "," << k << "," << r << ")" << std::endl;
754  ;
755  return 0;
756  }
757  double BetaN_ = (n + 1) * pi / L;
758  // Rossegger Equation 5.45
759  // Rnk(r) = Limu_nk (BetaN a) Kimu_nk (BetaN r) - Kimu_nk(BetaN a) Limu_nk (BetaN r)
760 
761  return limu(Munk[n][k], BetaN_ * a) * kimu(Munk[n][k], BetaN_ * r) - kimu(Munk[n][k], BetaN_ * a) * limu(Munk[n][k], BetaN_ * r);
762 }
763 
764 double Rossegger::Ez(double r, double phi, double z, double r1, double phi1, double z1)
765 {
766  // rcc streamlined Ez
767  int error = 0;
768  if (r < a || r > b)
769  {
770  error = 1;
771  }
772  if (phi < 0 || phi > 2 * pi)
773  {
774  error = 1;
775  }
776  if (z < 0 || z > L)
777  {
778  error = 1;
779  }
780  if (r1 < a || r1 > b)
781  {
782  error = 1;
783  }
784  if (phi1 < 0 || phi1 > 2 * pi)
785  {
786  error = 1;
787  }
788  if (z1 < 0 || z1 > L)
789  {
790  error = 1;
791  }
792  if (error)
793  {
794  std::cout << "Invalid arguments Ez(";
795  std::cout << r << ",";
796  std::cout << phi << ",";
797  std::cout << z << ",";
798  std::cout << r1 << ",";
799  std::cout << phi1 << ",";
800  std::cout << z1;
801  std::cout << ")" << std::endl;
802  ;
803  return 0;
804  }
805  // Rossegger Equation 5.64
806  double G = 0;
807  for (int m = 0; m < NumberOfOrders; m++)
808  {
809  if (verbosity > 10)
810  {
811  std::cout << std::endl
812  << m;
813  }
814  for (int n = 0; n < NumberOfOrders; n++)
815  {
816  if (verbosity > 10)
817  {
818  std::cout << " " << n;
819  }
820  double term = 1; // unitless
821  if (verbosity > 10)
822  {
823  std::cout << " " << term;
824  }
825  term *= (2 - ((m == 0) ? 1 : 0)) * cos(m * (phi - phi1)); // unitless
826  if (verbosity > 10)
827  {
828  std::cout << " " << term;
829  }
830  term *= Rmn(m, n, r) * Rmn(m, n, r1) / N2mn[m][n]; // units of 1/[L]^2
831  if (verbosity > 10)
832  {
833  std::cout << " " << term;
834  }
835  if (z < z1)
836  {
837  term *= cosh(Betamn[m][n] * z) * sinh(Betamn[m][n] * (L - z1)) / sinh_Betamn_L[m][n]; // unitless
838  }
839  else
840  {
841  term *= -cosh(Betamn[m][n] * (L - z)) * sinh(Betamn[m][n] * z1) / sinh_Betamn_L[m][n]; // unitless
842  }
843  if (verbosity > 10)
844  {
845  std::cout << " " << term;
846  }
847  G += term;
848  if (verbosity > 10)
849  {
850  std::cout << " " << term << " " << G << std::endl;
851  }
852  }
853  }
854 
855  G = G / (2.0 * pi);
856  if (verbosity)
857  {
858  std::cout << "Ez = " << G << std::endl;
859  }
860 
861  return G;
862 }
863 
864 double Rossegger::Ez_(double r, double phi, double z, double r1, double phi1, double z1)
865 {
866  // if(fByFile && fabs(r-r1)>MinimumDR && fabs(z-z1)>MinimumDZ) return ByFileEZ(r,phi,z,r1,phi1,z1);
867  // Check input arguments for sanity...
868  int error = 0;
869  if (r < a || r > b)
870  {
871  error = 1;
872  }
873  if (phi < 0 || phi > 2 * pi)
874  {
875  error = 1;
876  }
877  if (z < 0 || z > L)
878  {
879  error = 1;
880  }
881  if (r1 < a || r1 > b)
882  {
883  error = 1;
884  }
885  if (phi1 < 0 || phi1 > 2 * pi)
886  {
887  error = 1;
888  }
889  if (z1 < 0 || z1 > L)
890  {
891  error = 1;
892  }
893  if (error)
894  {
895  std::cout << "Invalid arguments Ez(";
896  std::cout << r << ",";
897  std::cout << phi << ",";
898  std::cout << z << ",";
899  std::cout << r1 << ",";
900  std::cout << phi1 << ",";
901  std::cout << z1;
902  std::cout << ")" << std::endl;
903  ;
904  return 0;
905  }
906 
907  double G = 0;
908  for (int m = 0; m < NumberOfOrders; m++)
909  {
910  if (verbosity > 10)
911  {
912  std::cout << std::endl
913  << m;
914  }
915  for (int n = 0; n < NumberOfOrders; n++)
916  {
917  if (verbosity > 10)
918  {
919  std::cout << " " << n;
920  }
921  double term = 1 / (2.0 * pi);
922  if (verbosity > 10)
923  {
924  std::cout << " " << term;
925  }
926  term *= (2 - ((m == 0) ? 1 : 0)) * cos(m * (phi - phi1)); // unitless
927  if (verbosity > 10)
928  {
929  std::cout << " " << term;
930  }
931  term *= Rmn(m, n, r) * Rmn(m, n, r1) / N2mn[m][n]; // units of 1/[L]^2
932  if (verbosity > 10)
933  {
934  std::cout << " " << term;
935  }
936  if (z < z1)
937  {
938  term *= cosh(Betamn[m][n] * z) * sinh(Betamn[m][n] * (L - z1)) / sinh(Betamn[m][n] * L);
939  }
940  else
941  {
942  term *= -cosh(Betamn[m][n] * (L - z)) * sinh(Betamn[m][n] * z1) / sinh(Betamn[m][n] * L);
943  ;
944  }
945  if (verbosity > 10)
946  {
947  std::cout << " " << term;
948  }
949  G += term;
950  if (verbosity > 10)
951  {
952  std::cout << " " << term << " " << G << std::endl;
953  }
954  }
955  }
956  if (verbosity)
957  {
958  std::cout << "Ez = " << G << std::endl;
959  }
960 
961  return G;
962 }
963 
964 double Rossegger::Er(double r, double phi, double z, double r1, double phi1, double z1)
965 {
966  // rcc streamlined Er
967 
968  // as in Rossegger 5.65
969  // field at r, phi, z due to unit charge at r1, phi1, z1;
970  // if(fByFile && fabs(r-r1)>MinimumDR && fabs(z-z1)>MinimumDZ) return ByFileER(r,phi,z,r1,phi1,z1);
971  // Check input arguments for sanity...
972  int error = 0;
973  if (r < a || r > b)
974  {
975  error = 1;
976  }
977  if (phi < 0 || phi > 2 * pi)
978  {
979  error = 1;
980  }
981  if (z < 0 || z > L)
982  {
983  error = 1;
984  }
985  if (r1 < a || r1 > b)
986  {
987  error = 1;
988  }
989  if (phi1 < 0 || phi1 > 2 * pi)
990  {
991  error = 1;
992  }
993  if (z1 < 0 || z1 > L)
994  {
995  error = 1;
996  }
997  if (error)
998  {
999  std::cout << "Invalid arguments Er(";
1000  std::cout << r << ",";
1001  std::cout << phi << ",";
1002  std::cout << z << ",";
1003  std::cout << r1 << ",";
1004  std::cout << phi1 << ",";
1005  std::cout << z1;
1006  std::cout << ")" << std::endl;
1007  ;
1008  return 0;
1009  }
1010 
1011  double part = 0;
1012  double G = 0;
1013  for (int m = 0; m < NumberOfOrders; m++)
1014  {
1015  for (int n = 0; n < NumberOfOrders; n++)
1016  {
1017  double term = 1;
1018  part = (2 - ((m == 0) ? 1 : 0)) * cos(m * (phi - phi1)); // unitless
1019  if (verbosity > 10)
1020  {
1021  printf("(2 - ((m==0)?1:0))*cos(m*(phi-phi1)); = %f\n", part);
1022  }
1023  term *= part;
1024  part = sin(BetaN[n] * z) * sin(BetaN[n] * z1); // unitless
1025  if (verbosity > 10)
1026  {
1027  printf("sin(BetaN[n]*z)*sin(BetaN[n]*z1); = %f\n", part);
1028  }
1029  term *= part;
1030 
1031  if (r < r1)
1032  {
1033  term *= RPrime(m, n, a, r) * Rmn2(m, n, r1); // units of 1/[L]
1034  }
1035  else
1036  {
1037  term *= Rmn1(m, n, r1) * RPrime(m, n, b, r); // units of 1/[L]
1038  }
1039  term /= bessel_denominator[m][n]; // unitless
1040  G += term;
1041  }
1042  }
1043 
1044  G = G / (L * pi); // units of 1/[L] -- net is 1/[L]^2
1045  if (verbosity)
1046  {
1047  std::cout << "Er = " << G << std::endl;
1048  }
1049 
1050  return G;
1051 }
1052 
1053 double Rossegger::Er_(double r, double phi, double z, double r1, double phi1, double z1)
1054 {
1055  // doesn't take advantage of precalcs.
1056  // as in Rossegger 5.65
1057  // field at r, phi, z due to unit charge at r1, phi1, z1;
1058  // if(fByFile && fabs(r-r1)>MinimumDR && fabs(z-z1)>MinimumDZ) return ByFileER(r,phi,z,r1,phi1,z1);
1059  // Check input arguments for sanity...
1060  int error = 0;
1061  if (r < a || r > b)
1062  {
1063  error = 1;
1064  }
1065  if (phi < 0 || phi > 2 * pi)
1066  {
1067  error = 1;
1068  }
1069  if (z < 0 || z > L)
1070  {
1071  error = 1;
1072  }
1073  if (r1 < a || r1 > b)
1074  {
1075  error = 1;
1076  }
1077  if (phi1 < 0 || phi1 > 2 * pi)
1078  {
1079  error = 1;
1080  }
1081  if (z1 < 0 || z1 > L)
1082  {
1083  error = 1;
1084  }
1085  if (error)
1086  {
1087  std::cout << "Invalid arguments Er(";
1088  std::cout << r << ",";
1089  std::cout << phi << ",";
1090  std::cout << z << ",";
1091  std::cout << r1 << ",";
1092  std::cout << phi1 << ",";
1093  std::cout << z1;
1094  std::cout << ")" << std::endl;
1095  ;
1096  return 0;
1097  }
1098 
1099  double G = 0;
1100  for (int m = 0; m < NumberOfOrders; m++)
1101  {
1102  for (int n = 0; n < NumberOfOrders; n++)
1103  {
1104  double term = 1 / (L * pi);
1105  term *= (2 - ((m == 0) ? 1 : 0)) * cos(m * (phi - phi1));
1106  double BetaN_ = (n + 1) * pi / L;
1107  term *= sin(BetaN_ * z) * sin(BetaN_ * z1);
1108  if (r < r1)
1109  {
1110  term *= RPrime_(m, n, a, r) * Rmn2_(m, n, r1);
1111  }
1112  else
1113  {
1114  term *= Rmn1_(m, n, r1) * RPrime_(m, n, b, r);
1115  }
1116 
1117  term /= TMath::BesselI(m, BetaN_ * a) * TMath::BesselK(m, BetaN_ * b) - TMath::BesselI(m, BetaN_ * b) * TMath::BesselK(m, BetaN_ * a);
1118 
1119  G += term;
1120  }
1121  }
1122 
1123  if (verbosity)
1124  {
1125  std::cout << "Er = " << G << std::endl;
1126  }
1127 
1128  return G;
1129 }
1130 
1131 double Rossegger::Ephi(double r, double phi, double z, double r1, double phi1, double z1)
1132 {
1133  // rcc streamlined Ephi term
1134  // compute field at rphiz from charge at r1phi1z1
1135  // Check input arguments for sanity...
1136  int error = 0;
1137  if (r < a || r > b)
1138  {
1139  error = 1;
1140  }
1141  if (phi < 0 || phi > 2 * pi)
1142  {
1143  error = 1;
1144  }
1145  if (z < 0 || z > L)
1146  {
1147  error = 1;
1148  }
1149  if (r1 < a || r1 > b)
1150  {
1151  error = 1;
1152  }
1153  if (phi1 < 0 || phi1 > 2 * pi)
1154  {
1155  error = 1;
1156  }
1157  if (z1 < 0 || z1 > L)
1158  {
1159  error = 1;
1160  }
1161  if (error)
1162  {
1163  std::cout << "Invalid arguments Ephi(";
1164  std::cout << r << ",";
1165  std::cout << phi << ",";
1166  std::cout << z << ",";
1167  std::cout << r1 << ",";
1168  std::cout << phi1 << ",";
1169  std::cout << z1;
1170  std::cout << ")" << std::endl;
1171  ;
1172  return 0;
1173  }
1174 
1175  double G = 0;
1176  // Rossegger Eqn. 5.66:
1177  for (int k = 0; k < NumberOfOrders; k++)
1178  {
1179  for (int n = 0; n < NumberOfOrders; n++)
1180  {
1181  double term = 1;
1182  term *= sin(BetaN[n] * z) * sin(BetaN[n] * z1); // unitless
1183  term *= Rnk(n, k, r) * Rnk(n, k, r1) / N2nk[n][k]; // unitless?
1184 
1185  // the derivative of cosh(munk(pi-|phi-phi1|)
1186  if (phi > phi1)
1187  {
1188  term *= -sinh(Munk[n][k] * (pi - (phi - phi1))); // unitless
1189  }
1190  else
1191  {
1192  term *= sinh(Munk[n][k] * (pi - (phi1 - phi))); // unitless
1193  }
1194  term *= 1 / sinh_pi_Munk[n][k]; // unitless
1195  G += term;
1196  }
1197  }
1198 
1199  G = G / (L * r); // units of 1/[L]^2. r comes from the phi term in cylindrical gradient expression.
1200  if (verbosity)
1201  {
1202  std::cout << "Ephi = " << G << std::endl;
1203  }
1204 
1205  return G;
1206 }
1207 
1208 double Rossegger::Ephi_(double r, double phi, double z, double r1, double phi1, double z1)
1209 {
1210  // compute field at rphiz from charge at r1phi1z1
1211  // Check input arguments for sanity...
1212  int error = 0;
1213  if (r < a || r > b)
1214  {
1215  error = 1;
1216  }
1217  if (phi < 0 || phi > 2 * pi)
1218  {
1219  error = 1;
1220  }
1221  if (z < 0 || z > L)
1222  {
1223  error = 1;
1224  }
1225  if (r1 < a || r1 > b)
1226  {
1227  error = 1;
1228  }
1229  if (phi1 < 0 || phi1 > 2 * pi)
1230  {
1231  error = 1;
1232  }
1233  if (z1 < 0 || z1 > L)
1234  {
1235  error = 1;
1236  }
1237  if (error)
1238  {
1239  std::cout << "Invalid arguments Ephi(";
1240  std::cout << r << ",";
1241  std::cout << phi << ",";
1242  std::cout << z << ",";
1243  std::cout << r1 << ",";
1244  std::cout << phi1 << ",";
1245  std::cout << z1;
1246  std::cout << ")" << std::endl;
1247  ;
1248  return 0;
1249  }
1250 
1251  verbosity = 1;
1252  double G = 0;
1253  // Rossegger Eqn. 5.66:
1254  for (int k = 0; k < NumberOfOrders; k++) // off by one from Rossegger convention!
1255  {
1256  if (verbosity)
1257  {
1258  std::cout << "\nk=" << k;
1259  }
1260  for (int n = 0; n < NumberOfOrders; n++) // off by one from Rossegger convention!
1261  {
1262  if (verbosity)
1263  {
1264  std::cout << " n=" << n;
1265  }
1266  double BetaN_ = (n + 1) * pi / L;
1267  double term = 1 / (L * r);
1268  if (verbosity)
1269  {
1270  std::cout << " 1/L=" << term;
1271  }
1272  term *= sin(BetaN_ * z) * sin(BetaN_ * z1);
1273  if (verbosity)
1274  {
1275  std::cout << " *sinsin=" << term;
1276  }
1277  term *= Rnk_(n, k, r) * Rnk_(n, k, r1);
1278  if (verbosity)
1279  {
1280  std::cout << " *rnkrnk=" << term;
1281  }
1282  term /= N2nk[n][k];
1283  if (verbosity)
1284  {
1285  std::cout << " */nnknnk=" << term;
1286  }
1287 
1288  // the derivative of cosh(munk(pi-|phi-phi1|)
1289  if (phi > phi1)
1290  {
1291  term *= -sinh(Munk[n][k] * (pi - (phi - phi1)));
1292  // term *= Munk[n][k]*sinh(Munk[n][k]*pi*(phi1-phi));
1293  // this originally has a factor of Munk in front, but that cancels with one in the denominator
1294  }
1295  else
1296  {
1297  term *= sinh(Munk[n][k] * (pi - (phi1 - phi)));
1298  // term *= -Munk[n][k]*sinh(Munk[n][k]*pi*(phi-phi1));
1299  // this originally has a factor of Munk in front, but that cancels with one in the denominator
1300  }
1301  if (verbosity)
1302  {
1303  std::cout << " *sinh(mu*pi-phi-phi)=" << term;
1304  }
1305  term *= 1 / (sinh(pi * Munk[n][k]));
1306  // term *= 1/(Munk[n][k]*sinh(pi*Munk[n][k]));
1307  // this originally has a factor of Munk in front, but that cancels with one in the numerator
1308  G += term;
1309  if (verbosity)
1310  {
1311  std::cout << " /sinh=" << term << " G=" << G << std::endl;
1312  }
1313  }
1314  }
1315  if (verbosity)
1316  {
1317  std::cout << "Ephi = " << G << std::endl;
1318  }
1319  verbosity = 0;
1320 
1321  return G;
1322 }
1323 
1324 void Rossegger::SaveZeroes(const char *destfile)
1325 {
1326  TFile *output = TFile::Open(destfile, "RECREATE");
1327  output->cd();
1328 
1329  TTree *tInfo = new TTree("info", "Mu[n][k] values");
1330  int ord = NumberOfOrders;
1331  tInfo->Branch("order", &ord);
1332  tInfo->Branch("epsilon", &epsilon);
1333  tInfo->Fill();
1334 
1335  int n, k, m;
1336  double munk, betamn;
1337  double n2nk, n2mn;
1338  TTree *tmunk = new TTree("munk", "Mu[n][k] values");
1339  tmunk->Branch("n", &n);
1340  tmunk->Branch("k", &k);
1341  tmunk->Branch("munk", &munk);
1342  tmunk->Branch("n2nk", &n2nk);
1343  for (n = 0; n < ord; n++)
1344  {
1345  for (k = 0; k < ord; k++)
1346  {
1347  munk = Munk[n][k];
1348  n2nk = N2nk[n][k];
1349  tmunk->Fill();
1350  }
1351  }
1352 
1353  TTree *tbetamn = new TTree("betamn", "Beta[m][n] values");
1354  tbetamn->Branch("m", &m);
1355  tbetamn->Branch("n", &n);
1356  tbetamn->Branch("betamn", &betamn);
1357  tbetamn->Branch("n2mn", &n2mn);
1358  for (m = 0; m < ord; m++)
1359  {
1360  for (n = 0; n < ord; n++)
1361  {
1362  betamn = Betamn[m][n];
1363  n2mn = N2mn[m][n];
1364  tbetamn->Fill();
1365  }
1366  }
1367 
1368  tInfo->Write();
1369  tmunk->Write();
1370  tbetamn->Write();
1371  // output->Write();
1372  output->Close();
1373  return;
1374 }
1375 
1376 void Rossegger::LoadZeroes(const char *destfile)
1377 {
1378  TFile *f = TFile::Open(destfile, "READ");
1379  printf("reading rossegger zeroes from %s\n", destfile);
1380  TTree *tInfo = (TTree *) (f->Get("info"));
1381  int ord;
1382  tInfo->SetBranchAddress("order", &ord);
1383  tInfo->SetBranchAddress("epsilon", &epsilon);
1384  tInfo->GetEntry(0);
1385  printf("order=%d,epsilon=%f\n", ord, epsilon);
1386 
1387  int n, k, m;
1388  double munk, betamn;
1389  double n2nk, n2mn;
1390  TTree *tmunk = (TTree *) (f->Get("munk"));
1391  tmunk->SetBranchAddress("n", &n);
1392  tmunk->SetBranchAddress("k", &k);
1393  tmunk->SetBranchAddress("munk", &munk);
1394  tmunk->SetBranchAddress("n2nk", &n2nk);
1395  for (int i = 0; i < tmunk->GetEntries(); i++)
1396  {
1397  tmunk->GetEntry(i);
1398  Munk[n][k] = munk;
1399  N2nk[n][k] = n2nk;
1400  }
1401 
1402  TTree *tbetamn = (TTree *) (f->Get("betamn"));
1403  tbetamn->SetBranchAddress("m", &m);
1404  tbetamn->SetBranchAddress("n", &n);
1405  tbetamn->SetBranchAddress("betamn", &betamn);
1406  tbetamn->SetBranchAddress("n2mn", &n2mn);
1407  for (int i = 0; i < tbetamn->GetEntries(); i++)
1408  {
1409  tbetamn->GetEntry(i);
1410  Betamn[m][n] = betamn;
1411  N2mn[m][n] = n2mn;
1412  }
1413 
1414  f->Close();
1415  return;
1416 }