File indexing completed on 2025-12-16 09:21:56
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023 #ifndef G4MAIN_ECOMUG_H
0024 #define G4MAIN_ECOMUG_H
0025
0026 #include <array>
0027 #include <functional>
0028 #include <random>
0029
0030
0031
0032
0033 class EMRandom
0034 {
0035 public:
0036 EMRandom()
0037 {
0038 std::random_device rd;
0039 std::mt19937 gen(rd());
0040 std::uniform_int_distribution<uint64_t> dis(0, std::numeric_limits<uint64_t>::max());
0041 s[0] = 12345.;
0042 s[1] = 12345;
0043 };
0044
0045 void SetSeed(uint64_t seed)
0046 {
0047 s[0] = seed;
0048 s[1] = seed;
0049 };
0050
0051 double GenerateRandomDouble()
0052 {
0053 uint64_t x = next();
0054 return to_double(x);
0055 };
0056
0057 double GenerateRandomDouble(double x1, double x2)
0058 {
0059 return (x2 - x1) * GenerateRandomDouble() + x1;
0060 };
0061
0062 int64_t rotl(const uint64_t x, int k)
0063 {
0064 return (x << k) | (x >> (64 - k));
0065 };
0066
0067 uint64_t next()
0068 {
0069 const uint64_t s0 = s[0];
0070 uint64_t s1 = s[1];
0071 const uint64_t result = s0 + s1;
0072 s1 ^= s0;
0073 s[0] = rotl(s0, 55) ^ s1 ^ (s1 << 14);
0074 s[1] = rotl(s1, 36);
0075 return result;
0076 };
0077
0078 double to_double(uint64_t x)
0079 {
0080 union U
0081 {
0082 uint64_t i;
0083 double d;
0084 };
0085 U u = {UINT64_C(0x3FF) << 52 | x >> 12};
0086 return u.d - 1.0;
0087 };
0088
0089 uint64_t s[2];
0090 };
0091
0092
0093
0094
0095
0096 class EMMaximization
0097 {
0098 private:
0099 EMRandom mRandom;
0100 size_t mPopSize;
0101 size_t mNIter;
0102 int mGenMethod;
0103 double m_a;
0104 double m_a2;
0105 std::vector<std::vector<double> > mRanges;
0106 std::vector<std::vector<double> > mPopulation;
0107 double mBestCost;
0108 std::vector<double> mBestSolution;
0109 std::function<double(double, double)> mFunc;
0110
0111 public:
0112 EMMaximization(const EMRandom& random, int genMethod)
0113 : mRandom(random)
0114 , mPopSize(200)
0115 , mNIter(500)
0116 , mGenMethod(genMethod)
0117 , m_a(0.)
0118 , m_a2(0.)
0119 , mBestCost(-1.)
0120 {
0121
0122 mFunc = &DefaultJ;
0123 };
0124
0125
0126 static double DefaultJ(double p, double theta)
0127 {
0128 double n = std::max(0.1, 2.856 - 0.655 * log(p));
0129 return 1600 * pow(p, 0.279) * pow(cos(theta), n);
0130 }
0131
0132
0133 void SetParameters(double minP, double maxP, double minTheta, double maxTheta)
0134 {
0135 mRanges.push_back({minP, maxP});
0136 mRanges.push_back({minTheta, maxTheta});
0137 }
0138
0139
0140 void SetParameters(double minP, double maxP, double minTheta, double maxTheta, double minPhi, double maxPhi)
0141 {
0142 mRanges.push_back({minP, maxP});
0143 mRanges.push_back({minTheta, maxTheta});
0144 mRanges.push_back({minPhi, maxPhi});
0145 mRanges.push_back({0, M_PI / 2.});
0146 }
0147
0148
0149 void SetFunction(std::function<double(double, double)> func)
0150 {
0151 mFunc = func;
0152 }
0153
0154
0155 double SkyFunc(double p, double theta)
0156 {
0157 return mFunc(p, theta) * cos(theta) * sin(theta);
0158 }
0159
0160
0161 double CylFunc(double p, double theta)
0162 {
0163 return mFunc(p, theta) * pow(sin(theta), 2);
0164 }
0165
0166
0167 double HSFunc(double p, double theta, double phi, double theta0)
0168 {
0169 return mFunc(p, theta) * (sin(theta0) * sin(theta) * cos(phi) + cos(theta0) * cos(theta)) * sin(theta);
0170 }
0171
0172
0173 double Evaluate(std::vector<double>& v)
0174 {
0175 if (mGenMethod == 0)
0176 {
0177 return SkyFunc(v[0], v[1]);
0178 }
0179 else if (mGenMethod == 1)
0180 {
0181 return CylFunc(v[0], v[1]);
0182 }
0183 else
0184 {
0185 return HSFunc(v[0], v[1], v[2], v[3]);
0186 }
0187 return -1;
0188 }
0189
0190
0191 void Evaluate()
0192 {
0193 double value;
0194 for (size_t i = 0; i < mPopSize; ++i)
0195 {
0196 value = Evaluate(mPopulation[i]);
0197 if (value > mBestCost)
0198 {
0199 mBestCost = value;
0200 mBestSolution = mPopulation[i];
0201 }
0202 }
0203 }
0204
0205
0206 void Init()
0207 {
0208 size_t dim = mRanges.size();
0209 mPopulation.resize(mPopSize);
0210 for (size_t i = 0; i < mPopSize; ++i)
0211 {
0212 mPopulation[i].resize(dim);
0213 for (size_t j = 0; j < dim; ++j)
0214 {
0215 mPopulation[i][j] = mRandom.GenerateRandomDouble(mRanges[j][0], mRanges[j][1]);
0216 }
0217 }
0218 }
0219
0220
0221 void UpdateParameters(size_t t)
0222 {
0223 m_a = 2. - t * (2. / mNIter);
0224 m_a2 = -1. + t * ((-1.) / mNIter);
0225 }
0226
0227
0228 void Move()
0229 {
0230 double r1, r2, A, C, b, l, rw, p, D_tmp, D_best, distance;
0231 std::vector<double> tmp;
0232 for (size_t i = 0; i < mPopulation.size(); ++i)
0233 {
0234 r1 = mRandom.GenerateRandomDouble();
0235 r2 = mRandom.GenerateRandomDouble();
0236 A = 2 * m_a * r1 - m_a;
0237 C = 2 * r2;
0238 b = 1.;
0239 l = (m_a2 - 1) * mRandom.GenerateRandomDouble() + 1;
0240 p = mRandom.GenerateRandomDouble();
0241
0242 for (size_t j = 0; j < mPopulation[0].size(); ++j)
0243 {
0244 if (p < 0.5)
0245 {
0246 if (fabs(A) >= 1)
0247 {
0248 rw = floor(mRandom.GenerateRandomDouble() * mPopulation.size());
0249 tmp = mPopulation[rw];
0250 D_tmp = fabs(C * tmp[j] - mPopulation[i][j]);
0251 mPopulation[i][j] = tmp[j] - A * D_tmp;
0252 }
0253 else
0254 {
0255 D_best = fabs(C * mBestSolution[j] - mPopulation[i][j]);
0256 mPopulation[i][j] = mBestSolution[j] - A * D_best;
0257 }
0258 }
0259 else
0260 {
0261 distance = fabs(mBestSolution[j] - mPopulation[i][j]);
0262 mPopulation[i][j] = distance * exp(b * l) * cos(l * 2 * M_PI) + mBestSolution[j];
0263 }
0264 if (mPopulation[i][j] < mRanges[j][0]) mPopulation[i][j] = mRanges[j][0];
0265 if (mPopulation[i][j] > mRanges[j][1]) mPopulation[i][j] = mRanges[j][1];
0266 }
0267 }
0268 }
0269
0270
0271 double Maximize()
0272 {
0273 Init();
0274 Evaluate();
0275 for (size_t iter = 1; iter < mNIter; ++iter)
0276 {
0277 UpdateParameters(iter);
0278 Move();
0279 Evaluate();
0280 }
0281 return mBestCost;
0282 }
0283 };
0284
0285
0286
0287
0288 class EcoMug
0289 {
0290 friend class EMRandom;
0291
0292 public:
0293
0294 enum EMGeometry
0295 {
0296 Sky,
0297 Cylinder,
0298 HSphere
0299 };
0300
0301 private:
0302 EMGeometry mGenMethod;
0303 std::array<double, 3> mGenerationPosition;
0304 double mGenerationTheta;
0305 double mGenerationPhi;
0306 double mGenerationMomentum;
0307 double mMinimumMomentum;
0308 double mMaximumMomentum;
0309 double mMinimumTheta;
0310 double mMaximumTheta;
0311 double mMinimumPhi;
0312 double mMaximumPhi;
0313 int mCharge;
0314 double mCylinderMinPositionPhi;
0315 double mCylinderMaxPositionPhi;
0316 double mHSphereMinPositionPhi;
0317 double mHSphereMaxPositionPhi;
0318 double mHSphereMinPositionTheta;
0319 double mHSphereMaxPositionTheta;
0320 double mHSphereCosMinPositionTheta;
0321 double mHSphereCosMaxPositionTheta;
0322 double mJPrime;
0323 double mN;
0324 double mRandAccRej;
0325 double mPhi0;
0326 double mTheta0;
0327 bool mAccepted;
0328 std::array<double, 2> mSkySize;
0329 std::array<double, 3> mSkyCenterPosition;
0330 double mCylinderHeight;
0331 double mCylinderRadius;
0332 std::array<double, 3> mCylinderCenterPosition;
0333 double mHSphereRadius;
0334
0335 std::array<double, 3> mHSphereCenterPosition;
0336 EMRandom mRandom;
0337 std::array<double, 3> mMaxJ;
0338 std::array<double, 3> mMaxCustomJ;
0339 std::function<double(double, double)> mJ;
0340
0341 public:
0342
0343 EcoMug()
0344 : mGenMethod(Sky)
0345 , mGenerationPosition({{0., 0., 0.}})
0346 , mGenerationTheta(0.)
0347 , mGenerationPhi(0.)
0348 , mGenerationMomentum(0.)
0349 , mMinimumMomentum(0.01)
0350 , mMaximumMomentum(1000.)
0351 , mMinimumTheta(0.)
0352 , mMaximumTheta(M_PI / 2.)
0353 , mMinimumPhi(0.)
0354 , mMaximumPhi(2. * M_PI)
0355 , mCharge(1)
0356 , mCylinderMinPositionPhi(0.)
0357 , mCylinderMaxPositionPhi(2. * M_PI)
0358 , mHSphereMinPositionPhi(0.)
0359 , mHSphereMaxPositionPhi(2. * M_PI)
0360 , mHSphereMinPositionTheta(0.)
0361 , mHSphereMaxPositionTheta(M_PI / 2.)
0362 , mHSphereCosMinPositionTheta(1.)
0363 , mHSphereCosMaxPositionTheta(0.)
0364 , mJPrime(0.)
0365 , mN(0.)
0366 , mRandAccRej(0.)
0367 , mPhi0(0.)
0368 , mTheta0(0.)
0369 , mAccepted(false)
0370 , mSkySize({{0., 0.}})
0371 , mSkyCenterPosition({{0., 0., 0.}})
0372 , mCylinderHeight(0.)
0373 , mCylinderRadius(0.)
0374 , mCylinderCenterPosition({{0., 0., 0.}})
0375 , mHSphereRadius(0.)
0376 ,
0377 mHSphereCenterPosition({{0., 0., 0.}})
0378 {
0379
0380 mMaxJ = {-1., -1., -1.};
0381
0382 mMaxCustomJ = {-1., -1., -1.};
0383 };
0384
0385
0386
0387
0388
0389 const std::array<double, 3>& GetGenerationPosition() const
0390 {
0391 return mGenerationPosition;
0392 };
0393
0394 double GetGenerationMomentum() const
0395 {
0396 return mGenerationMomentum;
0397 };
0398
0399 void GetGenerationMomentum(std::array<double, 3>& momentum) const
0400 {
0401 momentum = {
0402 mGenerationMomentum * sin(mGenerationTheta) * cos(mGenerationPhi),
0403 mGenerationMomentum * sin(mGenerationTheta) * sin(mGenerationPhi),
0404 mGenerationMomentum * cos(mGenerationTheta)};
0405 };
0406
0407 double GetGenerationTheta() const
0408 {
0409 return mGenerationTheta;
0410 };
0411
0412 double GetGenerationPhi() const
0413 {
0414 return mGenerationPhi;
0415 };
0416
0417 int GetCharge() const
0418 {
0419 return mCharge;
0420 };
0421
0422
0423
0424
0425
0426
0427 void SetUseSky()
0428 {
0429 mGenMethod = Sky;
0430 };
0431
0432 void SetUseCylinder()
0433 {
0434 mGenMethod = Cylinder;
0435 };
0436
0437 void SetUseHSphere()
0438 {
0439 mGenMethod = HSphere;
0440 };
0441
0442 void SetGenerationMethod(EMGeometry genM)
0443 {
0444 mGenMethod = genM;
0445 };
0446
0447
0448 EMGeometry GetGenerationMethod() const
0449 {
0450 return mGenMethod;
0451 };
0452
0453
0454
0455
0456
0457
0458
0459
0460 void SetDifferentialFlux(std::function<double(double, double)> J)
0461 {
0462 mJ = J;
0463 };
0464
0465 void SetSeed(uint64_t seed)
0466 {
0467 if (seed > 0) mRandom.SetSeed(seed);
0468 };
0469
0470 void SetMinimumMomentum(double momentum)
0471 {
0472 mMinimumMomentum = momentum;
0473 };
0474
0475 void SetMaximumMomentum(double momentum)
0476 {
0477 mMaximumMomentum = momentum;
0478 };
0479
0480 void SetMinimumTheta(double theta)
0481 {
0482 mMinimumTheta = theta;
0483 };
0484
0485 void SetMaximumTheta(double theta)
0486 {
0487 mMaximumTheta = theta;
0488 };
0489
0490 void SetMinimumPhi(double phi)
0491 {
0492 mMinimumPhi = phi;
0493 };
0494
0495 void SetMaximumPhi(double phi)
0496 {
0497 mMaximumPhi = phi;
0498 };
0499
0500
0501 double GetMinimumMomentum() const
0502 {
0503 return mMinimumMomentum;
0504 };
0505
0506 double GetMaximumMomentum() const
0507 {
0508 return mMaximumMomentum;
0509 };
0510
0511 double GetMinimumTheta() const
0512 {
0513 return mMinimumTheta;
0514 };
0515
0516 double GetMaximumTheta() const
0517 {
0518 return mMaximumTheta;
0519 };
0520
0521 double GetMinimumPhi() const
0522 {
0523 return mMinimumPhi;
0524 };
0525
0526 double GetMaximumPhi() const
0527 {
0528 return mMaximumPhi;
0529 };
0530
0531
0532
0533
0534
0535
0536 void SetSkySize(const std::array<double, 2>& size)
0537 {
0538 mSkySize = size;
0539 };
0540
0541
0542 void SetSkyCenterPosition(const std::array<double, 3>& position)
0543 {
0544 mSkyCenterPosition = position;
0545 };
0546
0547
0548
0549
0550
0551
0552 void SetCylinderRadius(double radius)
0553 {
0554 mCylinderRadius = radius;
0555 };
0556
0557 void SetCylinderHeight(double height)
0558 {
0559 mCylinderHeight = height;
0560 };
0561
0562 void SetCylinderCenterPosition(const std::array<double, 3>& position)
0563 {
0564 mCylinderCenterPosition = position;
0565 };
0566 void SetCylinderMinPositionPhi(double phi)
0567 {
0568 mCylinderMinPositionPhi = phi;
0569 };
0570 void SetCylinderMaxPositionPhi(double phi)
0571 {
0572 mCylinderMaxPositionPhi = phi;
0573 };
0574
0575 double GetCylinderRadius() const
0576 {
0577 return mCylinderRadius;
0578 };
0579
0580 double GetCylinderHeight() const
0581 {
0582 return mCylinderHeight;
0583 };
0584
0585 const std::array<double, 3>& GetCylinderCenterPosition() const
0586 {
0587 return mCylinderCenterPosition;
0588 };
0589
0590
0591
0592
0593
0594
0595 void SetHSphereRadius(double radius)
0596 {
0597 mHSphereRadius = radius;
0598 };
0599
0600 void SetHSphereCenterPosition(const std::array<double, 3>& position)
0601 {
0602 mHSphereCenterPosition = position;
0603 };
0604 void SetHSphereMinPositionPhi(double phi)
0605 {
0606 mHSphereMinPositionPhi = phi;
0607 };
0608 void SetHSphereMaxPositionPhi(double phi)
0609 {
0610 mHSphereMaxPositionPhi = phi;
0611 };
0612 void SetHSphereMinPositionTheta(double theta)
0613 {
0614 mHSphereMinPositionTheta = theta;
0615 mHSphereCosMinPositionTheta = cos(mHSphereMinPositionTheta);
0616 };
0617 void SetHSphereMaxPositionTheta(double theta)
0618 {
0619 mHSphereMaxPositionTheta = theta;
0620 mHSphereCosMaxPositionTheta = cos(mHSphereMaxPositionTheta);
0621 };
0622
0623 double GetHSphereRadius() const
0624 {
0625 return mHSphereRadius;
0626 };
0627
0628 const std::array<double, 3>& GetHSphereCenterPosition() const
0629 {
0630 return mHSphereCenterPosition;
0631 };
0632
0633
0634 private:
0635 double F1Cumulative(double x)
0636 {
0637 return 1. - 8.534790171171021 / pow(x + 2.68, 87. / 40.);
0638 };
0639
0640 double F1Inverse(double x)
0641 {
0642 return (2.68 - 2.68 * pow(1. - x, 40. / 87.)) / pow(1. - x, 40. / 87.);
0643 };
0644
0645 double maxSkyJFunc()
0646 {
0647 return 1600 * pow(mMaximumMomentum, 0.279) * pow(cos(0.76158), 1.1) * sin(0.76158);
0648 };
0649
0650 double maxCylJFunc()
0651 {
0652 return 1600 * pow(mMaximumMomentum, 0.279) * pow(cos(1.35081), 0.1) * pow(sin(1.35081), 2);
0653 };
0654
0655 double maxHSJFunc()
0656 {
0657 return 1600 * pow(mMaximumMomentum, 0.279) * pow(cos(1.26452), 0.1) * (sin(1.26452) * sin(1.26452) + cos(1.26452) * cos(1.26452)) * sin(1.26452);
0658 };
0659
0660 double GenerateMomentumF1()
0661 {
0662 double z = mRandom.GenerateRandomDouble(F1Cumulative(mMinimumMomentum), F1Cumulative(mMaximumMomentum));
0663 return F1Inverse(z);
0664 };
0665
0666 void GeneratePositionSky()
0667 {
0668 mGenerationPosition[0] = mRandom.GenerateRandomDouble(mSkyCenterPosition[0] - mSkySize[0] / 2., mSkyCenterPosition[0] + mSkySize[0] / 2.);
0669 mGenerationPosition[1] = mRandom.GenerateRandomDouble(mSkyCenterPosition[1] - mSkySize[1] / 2., mSkyCenterPosition[1] + mSkySize[1] / 2.);
0670 mGenerationPosition[2] = mSkyCenterPosition[2];
0671 };
0672
0673 void GeneratePositionCylinder()
0674 {
0675 mPhi0 = mRandom.GenerateRandomDouble(mCylinderMinPositionPhi, mCylinderMaxPositionPhi);
0676 mGenerationPosition[0] = mCylinderCenterPosition[0] + mCylinderRadius * cos(mPhi0);
0677 mGenerationPosition[1] = mCylinderCenterPosition[1] + mCylinderRadius * sin(mPhi0);
0678 mGenerationPosition[2] = mRandom.GenerateRandomDouble(mCylinderCenterPosition[2] - mCylinderHeight / 2., mCylinderCenterPosition[2] + mCylinderHeight / 2.);
0679 };
0680
0681 void ComputeMaximumCustomJ()
0682 {
0683 EMMaximization maximizer(mRandom, mGenMethod);
0684 maximizer.SetFunction(mJ);
0685 if (mGenMethod == 0 || mGenMethod == 1)
0686 {
0687 maximizer.SetParameters(mMinimumMomentum, mMaximumMomentum, mMinimumTheta, mMaximumTheta);
0688 }
0689 else
0690 {
0691 maximizer.SetParameters(mMinimumMomentum, mMaximumMomentum, mMinimumTheta, mMaximumTheta, mMinimumPhi, mMaximumPhi);
0692 }
0693 mMaxCustomJ[mGenMethod] = maximizer.Maximize();
0694 };
0695
0696 void ComputeMaximum()
0697 {
0698 EMMaximization maximizer(mRandom, mGenMethod);
0699 if (mGenMethod == 0 || mGenMethod == 1)
0700 {
0701 maximizer.SetParameters(mMinimumMomentum, mMaximumMomentum, mMinimumTheta, mMaximumTheta);
0702 }
0703 else
0704 {
0705 maximizer.SetParameters(mMinimumMomentum, mMaximumMomentum, mMinimumTheta, mMaximumTheta, mMinimumPhi, mMaximumPhi);
0706 }
0707 mMaxJ[mGenMethod] = maximizer.Maximize();
0708 };
0709
0710 public:
0711
0712
0713
0714 void Generate()
0715 {
0716 mAccepted = false;
0717
0718 if (mMaxJ[mGenMethod] < 0) ComputeMaximum();
0719
0720
0721 if (mGenMethod == Sky || mGenMethod == Cylinder)
0722 {
0723
0724 while (!mAccepted)
0725 {
0726 mRandAccRej = mRandom.GenerateRandomDouble();
0727 mGenerationTheta = mRandom.GenerateRandomDouble(mMinimumTheta, mMaximumTheta);
0728 mGenerationMomentum = GenerateMomentumF1();
0729 mN = 2.856 - 0.655 * log(mGenerationMomentum);
0730 if (mN < 0.1) mN = 0.1;
0731
0732 if (mGenMethod == Sky)
0733 {
0734 mJPrime = 1600 * pow(mGenerationMomentum, 0.279) * pow(cos(mGenerationTheta), mN + 1) * sin(mGenerationTheta);
0735 if (mMaxJ[mGenMethod] * mRandAccRej < mJPrime) mAccepted = true;
0736 }
0737
0738 if (mGenMethod == Cylinder)
0739 {
0740 mJPrime = 1600 * pow(mGenerationMomentum, 0.279) * pow(cos(mGenerationTheta), mN) * pow(sin(mGenerationTheta), 2);
0741 if (mMaxJ[mGenMethod] * mRandAccRej < mJPrime) mAccepted = true;
0742 }
0743 }
0744 mGenerationTheta = M_PI - mGenerationTheta;
0745
0746
0747 if (mGenMethod == Sky)
0748 {
0749 GeneratePositionSky();
0750 mGenerationPhi = mRandom.GenerateRandomDouble(mMinimumPhi, mMaximumPhi);
0751 }
0752 if (mGenMethod == Cylinder)
0753 {
0754 mAccepted = false;
0755 GeneratePositionCylinder();
0756 while (!mAccepted)
0757 {
0758 mRandAccRej = mRandom.GenerateRandomDouble();
0759 mGenerationPhi = mRandom.GenerateRandomDouble(mMinimumPhi, mMaximumPhi);
0760 if (mRandAccRej < fabs(cos(mGenerationPhi))) mAccepted = true;
0761 }
0762 mGenerationPhi = mGenerationPhi + mPhi0;
0763 if (mGenerationPhi >= 2. * M_PI) mGenerationPhi -= 2. * M_PI;
0764
0765
0766 if (sin(mGenerationTheta) * cos(mGenerationPhi) * mGenerationPosition[0] + sin(mGenerationTheta) * sin(mGenerationPhi) * mGenerationPosition[1] > 0) Generate();
0767 }
0768 }
0769
0770
0771 if (mGenMethod == HSphere)
0772 {
0773
0774 mPhi0 = mRandom.GenerateRandomDouble(mHSphereMinPositionPhi, mHSphereMaxPositionPhi);
0775 while (!mAccepted)
0776 {
0777 mRandAccRej = mRandom.GenerateRandomDouble();
0778 mTheta0 = acos(mRandom.GenerateRandomDouble(mHSphereCosMaxPositionTheta, mHSphereCosMinPositionTheta));
0779 mGenerationTheta = mRandom.GenerateRandomDouble(mMinimumTheta, mMaximumTheta);
0780 mGenerationPhi = mRandom.GenerateRandomDouble(mMinimumPhi, mMaximumPhi);
0781 mGenerationMomentum = GenerateMomentumF1();
0782 mN = 2.856 - 0.655 * log(mGenerationMomentum);
0783 if (mN < 0.1) mN = 0.1;
0784
0785 mJPrime = 1600 * pow(mGenerationMomentum, 0.279) * pow(cos(mGenerationTheta), mN) * (sin(mGenerationTheta) * sin(mTheta0) * cos(mGenerationPhi) + cos(mGenerationTheta) * cos(mTheta0)) * sin(mGenerationTheta);
0786 if (mMaxJ[mGenMethod] * mRandAccRej < mJPrime) mAccepted = true;
0787 }
0788
0789 mGenerationPosition[0] = mHSphereRadius * sin(mTheta0) * cos(mPhi0) + mHSphereCenterPosition[0];
0790 mGenerationPosition[1] = mHSphereRadius * sin(mTheta0) * sin(mPhi0) + mHSphereCenterPosition[1];
0791 mGenerationPosition[2] = mHSphereRadius * cos(mTheta0) + mHSphereCenterPosition[2];
0792
0793 mGenerationTheta = M_PI - mGenerationTheta;
0794 mGenerationPhi = mGenerationPhi + mPhi0;
0795 if (mGenerationPhi >= 2 * M_PI) mGenerationPhi -= 2 * M_PI;
0796
0797 mGenerationPhi += M_PI;
0798 if (mGenerationPhi >= 2 * M_PI) mGenerationPhi -= 2 * M_PI;
0799 }
0800
0801
0802 if (mRandom.GenerateRandomDouble(-100, 128) >= 0)
0803 mCharge = 1;
0804 else
0805 mCharge = -1;
0806 };
0807
0808
0809
0810
0811
0812 void GenerateFromCustomJ()
0813 {
0814 mAccepted = false;
0815
0816 if (mMaxCustomJ[mGenMethod] < 0) ComputeMaximumCustomJ();
0817
0818
0819 if (mGenMethod == Sky || mGenMethod == Cylinder)
0820 {
0821
0822 while (!mAccepted)
0823 {
0824 mRandAccRej = mRandom.GenerateRandomDouble();
0825 mGenerationTheta = mRandom.GenerateRandomDouble(mMinimumTheta, mMaximumTheta);
0826 mGenerationMomentum = mRandom.GenerateRandomDouble(mMinimumMomentum, mMaximumMomentum);
0827
0828 if (mGenMethod == Sky)
0829 {
0830 mJPrime = mJ(mGenerationMomentum, mGenerationTheta) * cos(mGenerationTheta) * sin(mGenerationTheta);
0831 if (mMaxCustomJ[mGenMethod] * mRandAccRej < mJPrime) mAccepted = true;
0832 }
0833
0834 if (mGenMethod == Cylinder)
0835 {
0836 mJPrime = mJ(mGenerationMomentum, mGenerationTheta) * pow(sin(mGenerationTheta), 2) * cos(mGenerationPhi);
0837 if (mMaxCustomJ[mGenMethod] * mRandAccRej < mJPrime) mAccepted = true;
0838 }
0839 }
0840 mGenerationTheta = M_PI - mGenerationTheta;
0841
0842
0843 if (mGenMethod == Sky)
0844 {
0845 GeneratePositionSky();
0846 mGenerationPhi = mRandom.GenerateRandomDouble(mMinimumPhi, mMaximumPhi);
0847 }
0848 if (mGenMethod == Cylinder)
0849 {
0850 mAccepted = false;
0851 GeneratePositionCylinder();
0852 while (!mAccepted)
0853 {
0854 mRandAccRej = mRandom.GenerateRandomDouble();
0855 mGenerationPhi = mRandom.GenerateRandomDouble(mMinimumPhi, mMaximumPhi);
0856 if (mRandAccRej < fabs(cos(mGenerationPhi))) mAccepted = true;
0857 }
0858 mGenerationPhi = mGenerationPhi + mPhi0;
0859 if (mGenerationPhi >= 2. * M_PI) mGenerationPhi -= 2. * M_PI;
0860
0861
0862 if (sin(mGenerationTheta) * cos(mGenerationPhi) * mGenerationPosition[0] + sin(mGenerationTheta) * sin(mGenerationPhi) * mGenerationPosition[1] > 0) Generate();
0863 }
0864 }
0865
0866
0867 if (mGenMethod == HSphere)
0868 {
0869
0870 mPhi0 = mRandom.GenerateRandomDouble(mHSphereMinPositionPhi, mHSphereMaxPositionPhi);
0871 while (!mAccepted)
0872 {
0873 mRandAccRej = mRandom.GenerateRandomDouble();
0874 mTheta0 = acos(mRandom.GenerateRandomDouble(mHSphereCosMaxPositionTheta, mHSphereCosMinPositionTheta));
0875 mGenerationTheta = mRandom.GenerateRandomDouble(mMinimumTheta, mMaximumTheta);
0876 mGenerationPhi = mRandom.GenerateRandomDouble(mMinimumPhi, mMaximumPhi);
0877 mGenerationMomentum = mRandom.GenerateRandomDouble(mMinimumMomentum, mMaximumMomentum);
0878
0879 mJPrime = mJ(mGenerationMomentum, mGenerationTheta) * (sin(mTheta0) * sin(mGenerationTheta) * cos(mGenerationPhi) + cos(mTheta0) * cos(mGenerationTheta)) * sin(mGenerationTheta);
0880 if (mMaxCustomJ[mGenMethod] * mRandAccRej < mJPrime) mAccepted = true;
0881 }
0882
0883 mGenerationPosition[0] = mHSphereRadius * sin(mTheta0) * cos(mPhi0) + mHSphereCenterPosition[0];
0884 mGenerationPosition[1] = mHSphereRadius * sin(mTheta0) * sin(mPhi0) + mHSphereCenterPosition[1];
0885 mGenerationPosition[2] = mHSphereRadius * cos(mTheta0) + mHSphereCenterPosition[2];
0886
0887 mGenerationTheta = M_PI - mGenerationTheta;
0888 mGenerationPhi = mGenerationPhi + mPhi0;
0889 if (mGenerationPhi >= 2 * M_PI) mGenerationPhi -= 2 * M_PI;
0890
0891 mGenerationPhi += M_PI;
0892 if (mGenerationPhi >= 2 * M_PI) mGenerationPhi -= 2 * M_PI;
0893 }
0894
0895
0896 if (mRandom.GenerateRandomDouble(-100, 128) >= 0)
0897 mCharge = 1;
0898 else
0899 mCharge = -1;
0900 };
0901
0902 };
0903
0904
0905
0906 #endif