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