683{
  686 
  688 
  690  double        bequerel;
  691  JRange_t      D_m;
  693  double        QE;
  694  ULong_t       seed;
  696  double        focus;
  697  int           Aefftype;
  698  bool          exclusive;
  700 
  701  try {
  702 
  703    JParser<> zap(
"Example program to calculate multiples rate.");
 
  704 
  708    zap[
'D'] = 
make_field(D_m)             =  JRange_t(0.216, 10);
 
  717 
  718    zap(argc, argv);
  719  }
  720  catch(const exception &error) {
  721    FATAL(error.what() << endl);
 
  722  }
  723 
  724  gRandom->SetSeed(seed);
  725 
  726  using namespace NAMESPACE;
  727 
  728 
  729  const int     id     = 1;
  730  const JModule module = getModule<JKM3NeT_t>(
id);
 
  731 
  732  DEBUG(module << endl);
 
  733 
  734  bequerel /= focus;           
  735 
  736  const double  R_m = 17.0 * 2.54 * 0.5e-2;                
  737  const double  A   = PI * R_m * R_m;                      
  738 
  739  const double wmin = 280.0;   
  740  const double wmax = 700.0;   
  741  double       ng   =  37.0;   
  742 
  743  const double WAVELENGTH_EXPANSION =  (wmax-wmin) / (wmin*wmax) * (300.0*600.0)/(600.0-300.0);
  744 
  745  JGenerator* enigma = NULL;         
  746 
  748 
  749  case +2: enigma = new JEnigma<+2>(D_m); break;
  750  case  0: enigma = new JEnigma< 0>(D_m); break;
  751  case -2: enigma = new JEnigma<-2>(D_m); break;
  752 
  754  }
  755 
  756  const double vmin = 1.0 / wmax;    
  757  const double vmax = 1.0 / wmin;    
  758 
  759  double QEmax = 0.0;
  760 
  761  for (double w = wmin; w <= wmax; w += 1.0) {
  762    if (
getQE(w) > QEmax) {
 
  764    }
  765  }
  766 
  767  NOTICE(
"Maximal QE                  " << 
FIXED(5,3) << QEmax                << endl);
 
  768  NOTICE(
"Wavelength expansion        " << 
FIXED(5,3) << WAVELENGTH_EXPANSION << endl);
 
  769  NOTICE(
"Number of photons per decay " << 
FIXED(5,2) << ng                   << endl);
 
  770 
  771  typedef JManager<int, TH1D>  JManager_t;
  772 
  773  JManager_t H1(new TH1D("M[%]", NULL, 100, D_m.getLowerLimit(), D_m.getUpperLimit()));
  774 
  775  H1->Sumw2();
  776 
  777  TH1D pmt("pmt", NULL, 1000, -1.0, +1.0);
  778 
  779  for (Int_t i = 1; i != pmt.GetNbinsX(); ++i) {
  780 
  781    const double dot = pmt.GetBinCenter(i);
  782    
  784 
  785    switch (Aefftype) {
  786      
  787    case 1:
  789      break;
  790      
  791    case 3:
  792      y = get_angular_acceptance(dot);
 
  793      break;
  794    }
  795 
  796    pmt.SetBinContent(i, y);
  797  }
  798 
  799 
  802 
  803 
  806  
  807  for (
counter_type event_count = 0; event_count != numberOfEvents; ++event_count) {
 
  808 
  809    if (event_count%10000 == 0) {
  810      STATUS(
"event: " << setw(10) << event_count << 
'\r'); 
DEBUG(endl);
 
  811    }
  812 
  813    const JResult& 
result = enigma->next();
 
  814 
  815    const double D = 
result.D;
 
  816    const double V = 
result.V;
 
  817 
  818    
  819    
  820 
  821    double W = A / (4*PI*(D-R_m)*(D-R_m));
  822 
  823    if (W > 0.5) {
  824      W = 0.5;
  825    }
  826 
  827    
  828    double x = gRandom->Rndm();      
 
  830 
  831    if      ((x -= k40_beta_decay      .getBranchingRatio()) <= 0.0)
  832      y = k40_beta_decay      (gRandom->Rndm());
 
  833    else if ((x -= k40_electron_capture.getBranchingRatio()) <= 0.0)
  834      y = k40_electron_capture(gRandom->Rndm());
 
  835    
  836    const int N = gRandom->Poisson(y  * WAVELENGTH_EXPANSION * QE * W * QEmax * focus);
  837    
  838    
  839
  840
  841    if (N >= 2) {
  842 
  843      
  844 
  845      const double ct  = gRandom->Uniform(-1.0, +1.0);
  846      const double phi = gRandom->Uniform(-PI,  +PI);
  847      
  848      const double st  = sqrt((1.0 - ct) * (1.0 + ct));    
  849 
  851                               D * st * sin(phi),
  852                               D * ct);
  853      
  854      buffer.clear();
  855 
  856      for (int i = 0; i != N; ++i) {
  857 
  858        
  859 
  860        const double v     = gRandom->Uniform(vmin, vmax);
  861        const double w     = 1.0 / v;
  862        
  864 
  865        double P = 0.0;
  866 
  867        for (size_t pmt = 0; pmt != module.size(); ++pmt) {
  868 
  870 
  871          pos -= vertex;
  872        
  873          const double d   = pos.getLength();
  874 
  875          pos /= d;                
  876 
  877          if (d < D - R_m) {
  878            ERROR(
"Distance " << d << 
" < " << D << endl);
 
  879          }
  880 
  882 
  884 
  885          double p = 0.0;
  886 
  887          switch (Aefftype) {
  888 
  889          case 1:
  891            break;
  892 
  893          case 2:
  895            break;
  896 
  897          case 3:
  898            p = get_angular_acceptance(dot) * 
getQE(w);
 
  899            break;
  900          }
  901 
  902          P += pi[pmt] = U * p * exp(-d/l_abs);
  903        }
  904 
  905        if (P > W) {
  906          ERROR(
"Probability " << P << 
" > " << W << endl);
 
  907        }
  908         
  909        if (W * QEmax * gRandom->Rndm() < P) {
  910 
  911          int    pmt = 0;
  912          double y   = gRandom->Uniform(P);
 
  913          
  914          for (vector<double>::const_iterator i = pi.begin(); i != pi.end() && (y -= *i) > 0.0; ++i, ++pmt) {}
  915 
  916          buffer.push_back(pmt);
  917        }
  918      }
  919 
  920      if (!buffer.empty()) {
  921 
  922        int M = buffer.size();
  923 
  924        if (exclusive) {
  925 
  926          sort(buffer.begin(), buffer.end());
  927 
  928          M = 
distance(buffer.begin(), unique(buffer.begin(), buffer.end()));
 
  929        }
  930 
  931        h1[M].put(V);
  932        H1[M]->Fill(D, V);
  933 
  934        for (int i = 2; i <= M; ++i) {
  935          P2[i].put((double) (buffer.size() - M) / (double) M, V);
  936        }
  937 
  938      }
  939    }
  940  }
  942 
  943  for (JManager_t::iterator i = H1.begin(); i != H1.end(); ++i) {
  944    i->second->Scale(bequerel / (double) numberOfEvents);
  945  }
  946 
  947  for (size_t M = 2; M != 7; ++M) {
  948    cout << "Rate[" << M << "] = "
  949         << 
FIXED(8,3) << bequerel * h1[M].getTotal() / (double) numberOfEvents
 
  950         << " +/- "
  951         << 
FIXED(7,3) << bequerel * h1[M].getError() / (double) numberOfEvents
 
  952         << " Hz" << endl;
  953  }
  954 
  955  for (size_t M = 2; M != 7; ++M) {
  957      cout << "P2[" << M << "] = " << P2[M].getMean() << endl;
  958    }
  959  }
  960 
  962 
  963  out << H1 << pmt;
  964 
  965  out.Write();
  966  out.Close();
  967}
double getAngularAcceptance(const double x)
Angular acceptence of PMT.
 
double getAbsorptionLength(const double lambda)
 
#define DEBUG(A)
Message macros.
 
#define make_field(A,...)
macro to convert parameter to JParserTemplateElement object
 
std::vector< T >::difference_type distance(typename std::vector< T >::const_iterator first, typename PhysicsEvent::const_iterator< T > second)
Specialisation of STL distance.
 
Data structure for a composite optical module.
 
Data structure for position in three dimensions.
 
Utility class to parse command line options.
 
double getPhotocathodeArea()
Get photo-cathode area of PMT.
 
JDirection3D getDirection(const Vec &dir)
Get direction.
 
JPosition3D getPosition(const Vec &pos)
Get position.
 
double getDot(const JNeutrinoDirection &first, const JNeutrinoDirection &second)
Dot product.
 
double getQE(const double R, const double mu)
Get QE for given ratio of hit probabilities and expectation value of the number of photo-electrons.
 
size_t getCount(const array_type< T > &buffer, const JCompare_t &compare)
Count number of unique values.
 
This name space includes all other name spaces (except KM3NETDAQ, KM3NET and ANTARES).
 
Long64_t counter_type
Type definition for counter.
 
static const JPhotocathodeArea2D getPhotocathodeArea2D
Function object for effective photo-cathode area of PMT.
 
Auxiliary data structure for floating point format specification.
 
Description of Monte Carlo event generation applications.