34 const int CollimatorPhysics::numpar_m = 13;
38 struct DegraderInsideTester:
public InsideTester {
51 struct CollimatorInsideTester:
public InsideTester {
64 struct FlexCollimatorInsideTester:
public InsideTester {
65 explicit FlexCollimatorInsideTester(
ElementBase * el) {
80 std::string &material,
81 bool enableRutherford):
103 enableRutherford_m(enableRutherford)
116 rGen_m = gsl_rng_alloc(gsl_rng_default);
123 mySeed = tv.tv_sec + tv.tv_usec;
143 "Unsupported element type");
150 dksbase_m.setAPI(
"Cuda", 4);
151 dksbase_m.setDevice(
"-gpu", 4);
152 dksbase_m.initDevice();
153 curandInitSet_m = -1;
171 clearCollimatorDKS();
185 Z_m = material->getAtomicNumber();
186 A_m = material->getAtomicMass();
187 rho_m = material->getMassDensity();
188 X0_m = material->getRadiationLength();
189 I_m = material->getMeanExcitationEnergy();
197 const std::pair<Vector_t, double> &boundingSphere,
198 size_t numParticlesInSimulation) {
224 applyDKS(bunch, boundingSphere, numParticlesInSimulation);
226 applyNonDKS(bunch, boundingSphere, numParticlesInSimulation);
229 applyNonDKS(bunch, boundingSphere, numParticlesInSimulation);
236 const std::pair<Vector_t, double> &boundingSphere,
237 size_t numParticlesInSimulation) {
248 if (onlyOneLoopOverParticles)
267 onlyOneLoopOverParticles =
true;
269 }
while (onlyOneLoopOverParticles ==
false);
280 for (
size_t i = 0; i <
locParts_m.size(); ++i) {
320 bool includeFluctuations)
const {
322 constexpr
double m2cm = 1e2;
323 constexpr
double GeV2keV = 1e6;
324 constexpr
double massElectron_keV =
Physics::m_e * GeV2keV;
325 constexpr
double massProton_keV =
Physics::m_p * GeV2keV;
331 const double gammaSqr =
std::pow(gamma, 2);
332 const double betaSqr = 1.0 - 1.0 / gammaSqr;
333 double beta =
sqrt(betaSqr);
334 double Ekin = (gamma - 1) * massProton_keV;
337 const double deltas = deltat * beta *
Physics::c;
338 const double deltasrho = deltas * m2cm *
rho_m;
341 constexpr
double eV2keV = 1
e-3;
343 double Tmax = (2.0 * massElectron_keV * betaSqr * gammaSqr /
344 (
std::pow(gamma + massRatio, 2) - (gammaSqr - 1.0)));
347 (0.5 *
std::log(2 * massElectron_keV * betaSqr * gammaSqr * Tmax /
std::pow(
I_m * eV2keV, 2)) - betaSqr));
349 Ekin += deltasrho * dEdx;
350 }
else if (Ekin > 10) {
351 const double Ts = Ekin / massProton_amu;
352 const double epsilon_low =
A2_c *
pow(Ts, 0.45);
353 const double epsilon_high = (
A3_c / Ts) *
log(1 + (
A4_c / Ts) + (
A5_c * Ts));
354 const double epsilon = (epsilon_low * epsilon_high) / (epsilon_low + epsilon_high);
357 Ekin += deltasrho * dEdx;
360 if (includeFluctuations) {
361 double sigma_E =
sqrt(K * massElectron_keV * rho_m * (
Z_m /
A_m) * deltas * m2cm);
362 Ekin += gsl_ran_gaussian(
rGen_m, sigma_E);
365 gamma = Ekin / massProton_keV + 1.0;
369 bool stopped = (Ekin < 10 || dEdx > 0);
385 R(0) =
R(0) + shift *
cos(Psixz);
386 R(2) =
R(2) - shift *
sin(Psixz);
390 P(0) = Px *
cos(thetacou) + P(2) *
sin(thetacou);
391 P(2) = -Px *
sin(thetacou) + P(2) *
cos(thetacou);
396 double thetaru = 2.5 /
sqrt(gsl_rng_uniform(
rGen_m)) * 2.0 * theta0;
399 double normPtrans =
sqrt(P(0) * P(0) + P(1) * P(1));
401 double CosT =
cos(Theta);
402 double SinT =
sin(Theta);
413 P = X * CosT +
cross(W, X) * SinT + W *
dot(W, X) * (1.0 - CosT);
423 constexpr
double GeV2eV = 1e9;
426 constexpr
double sqrtThreeInv = 0.57735026918962576451;
428 const double gammaSqr =
std::pow(normP, 2) + 1.0;
429 const double beta =
sqrt(1.0 - 1.0 / gammaSqr);
431 const double theta0 = (13.6e6 / (beta * normP * massProton_eV) *
432 chargeProton *
sqrt(deltas /
X0_m) *
433 (1.0 + 0.038 *
log(deltas /
X0_m)));
436 for (
unsigned int i = 0; i < 2; ++ i) {
441 double z1 = gsl_ran_gaussian(
rGen_m, 1.0);
442 double z2 = gsl_ran_gaussian(
rGen_m, 1.0);
445 z1 = gsl_ran_gaussian(
rGen_m, 1.0);
446 z2 = gsl_ran_gaussian(
rGen_m, 1.0);
449 double thetacou = z2 * theta0;
450 double shift = (z1 * sqrtThreeInv + z2) * deltas * theta0 * 0.5;
460 gsl_rng_uniform(
rGen_m) < 0.0047) {
471 unsigned int numLocalParticles = bunch->
getLocalNum();
474 for (
size_t i = 0; i < nL; ++ i) {
477 if (R[2] >= elementLength) {
486 bunch->
Bin[numLocalParticles] = 1;
487 bunch->
R[numLocalParticles] =
R;
488 bunch->
P[numLocalParticles] =
locParts_m[i].Pincol;
489 bunch->
Q[numLocalParticles] =
locParts_m[i].Qincol;
490 bunch->
Bf[numLocalParticles] = 0.0;
491 bunch->
Ef[numLocalParticles] = 0.0;
492 bunch->
dt[numLocalParticles] =
dT_m;
502 ++ numLocalParticles;
513 const std::pair<Vector_t, double> &boundingSphere)
519 double zmax = boundingSphere.first(2) + boundingSphere.second;
520 double zmin = boundingSphere.first(2) - boundingSphere.second;
527 std::set<size_t> partsToDel;
529 for (
size_t i = 0; i < nL; ++ i) {
530 if ((bunch->
Bin[i] == -1 || bunch->
Bin[i] == 1) &&
531 ((nL - ne) > minNumOfParticlesPerCore) &&
543 double tau = bunch->
R[i](2) / stepWidth;
564 partsToDel.insert(i);
568 for (
auto it = partsToDel.begin(); it != partsToDel.end(); ++ it) {
591 <<
"Particle Statistics @ " << time.
time() <<
"\n"
608 bool degraderAlive =
true;
622 if (bunchOrigin[2] > zBegin) {
623 degraderAlive =
false;
626 clearCollimatorDKS();
631 return degraderAlive;
652 if ((*inv).label == -1)
667 for (
size_t i = 0; i <
locParts_m.size(); ++i) {
685 for (
size_t i = 0; i <
locParts_m.size(); ++i) {
692 if (
R(2) < elementLength &&
693 R(2) + stepLength(2) > elementLength) {
695 double distance = elementLength -
R(2);
696 double tau = distance / stepLength(2);
707 for (
size_t i = 0; i <
locParts_m.size(); ++i) {
717 unsigned int locPartsInMat;
720 locPartsInMat = numparticles_m + dksParts_m.size();
727 constexpr
unsigned short numItems = 4;
728 unsigned int partStatistics[numItems] = {locPartsInMat,
733 allreduce(&(partStatistics[0]), numItems, std::plus<unsigned int>());
745 bool myCompFDKS(PART_DKS x, PART_DKS y) {
746 return x.label > y.label;
751 const std::pair<Vector_t, double> &boundingSphere,
752 size_t numParticlesInSimulation) {
756 setupCollimatorDKS(bunch, numParticlesInSimulation);
762 if (dksParts_m.size() > 0) {
764 dksbase_m.writeDataAsync<PART_DKS>(mem_ptr, &dksParts_m[0],
765 dksParts_m.size(), -1, numparticles_m);
768 numparticles_m += dksParts_m.size();
771 dksParts_m.erase(dksParts_m.begin(), dksParts_m.end());
775 if (numparticles_m > 0) {
776 dksbase_m.callCollimatorPhysics2(mem_ptr, par_ptr, numparticles_m);
781 if (numparticles_m > 0) {
782 dksbase_m.callCollimatorPhysicsSort(mem_ptr, numparticles_m, numaddback);
786 if (numaddback > 0) {
789 dksParts_m.resize(numaddback);
793 dksbase_m.readData<PART_DKS>(mem_ptr, &dksParts_m[0], numaddback,
794 numparticles_m - numaddback);
797 for (
unsigned int i = 0; i < dksParts_m.size(); ++i) {
798 if (dksParts_m[i].label == -2) {
799 addBackToBunchDKS(bunch, i);
803 lossDs_m->addParticle(dksParts_m[i].Rincol, dksParts_m[i].Pincol,
809 dksParts_m.erase(dksParts_m.begin(), dksParts_m.end());
812 numparticles_m -= numaddback;
817 if (onlyOneLoopOverParticles)
818 copyFromBunchDKS(bunch, boundingSphere);
828 onlyOneLoopOverParticles =
true;
831 }
while (onlyOneLoopOverParticles ==
false);
836 int id = dksParts_m[i].localID;
845 bunch->
Bin[last] = 1;
847 bunch->
R[last] = dksParts_m[i].Rincol;
848 bunch->
P[last] = dksParts_m[i].Pincol;
855 dksParts_m[i].label = -1.0;
862 const std::pair<Vector_t, double> &boundingSphere)
868 double zmax = boundingSphere.first(2) + boundingSphere.second;
869 double zmin = boundingSphere.first(2) - boundingSphere.second;
878 for (
unsigned int i = 0; i < nL; ++i) {
879 if ((bunch->
Bin[i] == -1 || bunch->
Bin[i] == 1) &&
880 ((nL - ne) > minNumOfParticlesPerCore) &&
897 x_gpu.label = x.
label;
903 dksParts_m.push_back(x_gpu);
921 size_t numParticlesInSimulation)
924 if (curandInitSet_m == -1) {
928 int size = numParticlesInSimulation;
931 par_ptr = dksbase_m.allocateMemory<
double>(numpar_m, ierr_m);
934 mem_ptr = dksbase_m.allocateMemory<PART_DKS>((int)size, ierr_m);
936 maxparticles_m = (int)size;
952 double params[numpar_m] = {zBegin, zEnd,
rho_m,
Z_m,
955 dksbase_m.writeDataAsync<
double>(par_ptr, params, numpar_m);
961 void CollimatorPhysics::clearCollimatorDKS() {
962 if (curandInitSet_m == 1) {
963 dksbase_m.freeMemory<
double>(par_ptr, numpar_m);
964 dksbase_m.freeMemory<PART_DKS>(mem_ptr, maxparticles_m);
965 curandInitSet_m = -1;
970 void CollimatorPhysics::deleteParticleFromLocalVectorDKS() {
976 sort(dksParts_m.begin(), dksParts_m.end(), myCompFDKS);
988 dksParts_m.erase(inv, dksParts_m.end());
int seed
The current random seed.
std::unique_ptr< InsideTester > hitTester_m
ParticleAttrib< Vector_t > P
virtual bool isInMaterial(double z)
CollimatorPhysics(const std::string &name, ElementBase *element, std::string &mat, bool enableRutherford)
PETE_TUTree< FnAbs, typename T::PETE_Expr_t > abs(const PETE_Expr< T > &l)
std::string toStringWithThousandSep(T value, char sep= '\'')
constexpr double e
The value of .
void destroy(size_t M, size_t I, bool doNow=false)
ParticleAttrib< Vector_t > Ef
IpplTimings::TimerRef DegraderDestroyTimer_m
Interface for basic beam line object.
void applyRotation(Vector_t &P, Vector_t &R, double xplane, double thetacou)
Vector_t rotateTo(const Vector_t &r) const
unsigned int getMinimumNumberOfParticlesPerCore() const
The base class for all OPAL exceptions.
Tps< T > sin(const Tps< T > &x)
Sine.
ParticleAttrib< double > Q
constexpr double two_pi
The value of .
void computeCoulombScattering(Vector_t &R, Vector_t &P, double dt)
std::vector< PART > locParts_m
IpplTimings::TimerRef DegraderApplyTimer_m
constexpr double m_p
The proton rest mass in GeV.
void apply(PartBunchBase< double, 3 > *bunch, const std::pair< Vector_t, double > &boundingSphere, size_t numParticlesInSimulation=0)
virtual void getDimensions(double &zBegin, double &zEnd) const
bool allParticleInMat_m
if all particles are in matter stay inside the particle matter interaction
virtual const std::string & getName() const
Get element name.
void deleteParticleFromLocalVector()
std::unique_ptr< LossDataSink > lossDs_m
PETE_TBTree< OpNE, Index::PETE_Expr_t, PETE_Scalar< double > > ne(const Index &idx, double x)
Tps< T > log(const Tps< T > &x)
Natural logarithm.
bool isStopped(const Vector_t &R, const Vector_t &P, double recpgamma)
double dot(const Vector3D &lhs, const Vector3D &rhs)
Vector dot product.
virtual ElementType getType() const =0
Get element type std::string.
T deg(T x)
Convert radians to degrees.
constexpr double r_e
The classical electron radius in m.
bool stillAlive(PartBunchBase< double, 3 > *bunch)
constexpr double m_e
The electron rest mass in GeV.
Inform & level2(Inform &inf)
unsigned int stoppedPartStat_m
double getGamma(Vector_t p)
IpplTimings::TimerRef DegraderLoopTimer_m
void setTimeStepForLeavingParticles()
constexpr double pi
The value of .
virtual double getElementLength() const
Get design length.
void allreduce(const T *input, T *output, int count, Op op)
PETE_TUTree< FnArcTan, typename T::PETE_Expr_t > atan(const PETE_Expr< T > &l)
constexpr double c
The velocity of light in m/s.
Vector3D cross(const Vector3D &lhs, const Vector3D &rhs)
Vector cross product.
Interface for cyclotron collimator.
unsigned int rediffusedStat_m
static void startTimer(TimerRef t)
PETE_TBTree< FnArcTan2, PETE_Scalar< Vektor< T1, Dim > >, typename T2::PETE_Expr_t > atan2(const Vektor< T1, Dim > &l, const PETE_Expr< T2 > &r)
unsigned int bunchToMatStat_m
Tps< T > pow(const Tps< T > &x, int y)
Integer power.
Vektor< double, 3 > Vector_t
Vector_t get_origin() const
PETE_TBTree< FnFmod, PETE_Scalar< Vektor< T1, Dim > >, typename T2::PETE_Expr_t > fmod(const Vektor< T1, Dim > &l, const PETE_Expr< T2 > &r)
size_t getLocalNum() const
void applyRandomRotation(Vector_t &P, double theta0)
Tps< T > sqrt(const Tps< T > &x)
Square root.
ParticleAttrib< double > dt
void configureMaterialParameters()
The material of the collimator.
void performDestroy(bool updateLocalNum=false)
std::string time() const
Return time.
void createWithID(unsigned id)
unsigned int totalPartsInMat_m
Tps< T > cos(const Tps< T > &x)
Cosine.
T euclidean_norm(const Vector< T > &)
Euclidean norm.
ElementBase::ElementType collshape_m
static std::shared_ptr< Material > getMaterial(const std::string &name)
Vector_t rotateFrom(const Vector_t &r) const
constexpr double amu
The atomic mass unit energy equivalent in GeV.
ParticleAttrib< int > Bin
std::ios_base::fmtflags FmtFlags_t
ParticleAttrib< Vector_t > Bf
std::string::iterator iterator
ElementBase * element_ref_m
constexpr double z_p
The charge of proton.
static TimerRef getTimer(const char *nm)
void applyNonDKS(PartBunchBase< double, 3 > *bunch, const std::pair< Vector_t, double > &boundingSphere, size_t numParticlesInSimulation)
static void stopTimer(TimerRef t)
constexpr double Avo
The Avogadro's number.
void computeInteraction()
int checkPoint(const double &x, const double &y) const
Checks if coordinate is within element.
void addBackToBunch(PartBunchBase< double, 3 > *bunch)
Inform & endl(Inform &inf)
void copyFromBunch(PartBunchBase< double, 3 > *bunch, const std::pair< Vector_t, double > &boundingSphere)
virtual bool computeEnergyLoss(Vector_t &P, const double deltat, bool includeFluctuations=true) const
Vector_t transformFrom(const Vector_t &r) const