41 #include <gsl/gsl_histogram.h>
42 #include <gsl/gsl_linalg.h>
43 #include <gsl/gsl_randist.h>
44 #include <gsl/gsl_rng.h>
45 #include <gsl/gsl_sf_erf.h>
47 #include <boost/regex.hpp>
48 #include <boost/numeric/odeint/stepper/runge_kutta4.hpp>
72 for (
unsigned int i = 0; i < 6u; ++i) {
82 "The DISTRIBUTION statement defines data for the 6D particle distribution."),
84 numberOfDistributions_m(1),
89 currentEmissionTime_m(0.0),
90 currentEnergyBin_m(1),
91 currentSampleBin_m(0),
92 numberOfEnergyBins_m(0),
93 numberOfSampleBins_m(0),
94 energyBins_m(nullptr),
95 energyBinHist_m(nullptr),
99 cathodeWorkFunc_m(0.0),
101 cathodeFermiEnergy_m(0.0),
103 emitEnergyUpperLimit_m(0.0),
104 totalNumberParticles_m(0),
105 totalNumberEmittedParticles_m(0),
110 tPulseLengthFWHM_m(0.0),
111 correlationMatrix_m(getUnit6x6()),
114 laserProfileFileName_m(
""),
115 laserImageName_m(
""),
116 laserIntensityCut_m(0.0),
117 laserProfile_m(nullptr),
124 defaultDistribution->
builtin =
true;
129 delete defaultDistribution;
133 randGen_m = gsl_rng_alloc(gsl_rng_default);
143 distT_m(parent->distT_m),
145 numberOfDistributions_m(parent->numberOfDistributions_m),
146 emitting_m(parent->emitting_m),
147 particleRefData_m(parent->particleRefData_m),
148 addedDistributions_m(parent->addedDistributions_m),
149 particlesPerDist_m(parent->particlesPerDist_m),
150 emissionModel_m(parent->emissionModel_m),
151 tEmission_m(parent->tEmission_m),
152 tBin_m(parent->tBin_m),
153 currentEmissionTime_m(parent->currentEmissionTime_m),
154 currentEnergyBin_m(parent->currentEnergyBin_m),
155 currentSampleBin_m(parent->currentSampleBin_m),
156 numberOfEnergyBins_m(parent->numberOfEnergyBins_m),
157 numberOfSampleBins_m(parent->numberOfSampleBins_m),
158 energyBins_m(nullptr),
159 energyBinHist_m(nullptr),
161 pTotThermal_m(parent->pTotThermal_m),
162 pmean_m(parent->pmean_m),
163 cathodeWorkFunc_m(parent->cathodeWorkFunc_m),
164 laserEnergy_m(parent->laserEnergy_m),
165 cathodeFermiEnergy_m(parent->cathodeFermiEnergy_m),
166 cathodeTemp_m(parent->cathodeTemp_m),
167 emitEnergyUpperLimit_m(parent->emitEnergyUpperLimit_m),
168 totalNumberParticles_m(parent->totalNumberParticles_m),
169 totalNumberEmittedParticles_m(parent->totalNumberEmittedParticles_m),
170 xDist_m(parent->xDist_m),
171 pxDist_m(parent->pxDist_m),
172 yDist_m(parent->yDist_m),
173 pyDist_m(parent->pyDist_m),
174 tOrZDist_m(parent->tOrZDist_m),
175 pzDist_m(parent->pzDist_m),
176 xWrite_m(parent->xWrite_m),
177 pxWrite_m(parent->pxWrite_m),
178 yWrite_m(parent->yWrite_m),
179 pyWrite_m(parent->pyWrite_m),
180 tOrZWrite_m(parent->tOrZWrite_m),
181 pzWrite_m(parent->pzWrite_m),
182 avrgpz_m(parent->avrgpz_m),
183 inputMoUnits_m(parent->inputMoUnits_m),
184 sigmaTRise_m(parent->sigmaTRise_m),
185 sigmaTFall_m(parent->sigmaTFall_m),
186 tPulseLengthFWHM_m(parent->tPulseLengthFWHM_m),
187 sigmaR_m(parent->sigmaR_m),
188 sigmaP_m(parent->sigmaP_m),
189 cutoffR_m(parent->cutoffR_m),
190 cutoffP_m(parent->cutoffP_m),
191 correlationMatrix_m(parent->correlationMatrix_m),
192 sepPeaks_m(parent->sepPeaks_m),
193 nPeaks_m(parent->nPeaks_m),
194 laserProfileFileName_m(parent->laserProfileFileName_m),
195 laserImageName_m(parent->laserImageName_m),
196 laserIntensityCut_m(parent->laserIntensityCut_m),
197 laserProfile_m(nullptr),
200 tRise_m(parent->tRise_m),
201 tFall_m(parent->tFall_m),
202 sigmaRise_m(parent->sigmaRise_m),
203 sigmaFall_m(parent->sigmaFall_m),
204 cutoff_m(parent->cutoff_m)
207 randGen_m = gsl_rng_alloc(gsl_rng_default);
234 if (myNode < remainder)
263 size_t numberOfLocalParticles = numberOfParticles;
265 numberOfLocalParticles = (numberOfParticles + 1) / 2;
273 mySeed = tv.tv_sec + tv.tv_usec;
278 *gmsg <<
level2 <<
"* Generation of distribution with seed = " << mySeed <<
" + core_id\n"
279 <<
"* is scalable with number of particles and cores." <<
endl;
282 *gmsg <<
level2 <<
"* Generation of distribution with seed = " << mySeed <<
"\n"
283 <<
"* isn't scalable with number of particles and cores." <<
endl;
312 "Unknown \"TYPE\" of \"DISTRIBUTION\"");
317 unsigned int numAdditionalRNsPerParticle = 0;
322 numAdditionalRNsPerParticle = 2;
325 numAdditionalRNsPerParticle = 40;
327 numAdditionalRNsPerParticle = 20;
331 int saveProcessor = -1;
336 for (
size_t partIndex = 0; partIndex < numberOfLocalParticles; ++ partIndex) {
340 if (saveProcessor >= numNodes)
343 if (scalable || myNode == saveProcessor) {
344 std::vector<double> rns;
345 for (
unsigned int i = 0; i < numAdditionalRNsPerParticle; ++ i) {
351 for (
unsigned int i = 0; i < numAdditionalRNsPerParticle; ++ i) {
383 size_t firstParticle = numParticlesPerNode *
Ippl::myNode();
384 size_t lastParticle = firstParticle + numParticlesPerNode - 1;
386 lastParticle = numParticles - 1;
389 numParticles = lastParticle - firstParticle + 1;
392 beam->
create(numParticles);
395 dataSource->
readStep(beam, firstParticle, lastParticle);
399 double actualT = beam->
getT();
405 *gmsg <<
"Total number of particles in the h5 file= " << beam->
getTotalNum() <<
"\n"
406 <<
"Global step= " << gtstep <<
"; Local step= " << ltstep <<
"; "
407 <<
"restart step= " << restartStep <<
"\n"
414 const int specifiedNumBunch,
419 INFOMSG(
"---------------- Start reading hdf5 file----------------" <<
endl);
424 size_t firstParticle = numParticlesPerNode *
Ippl::myNode();
425 size_t lastParticle = firstParticle + numParticlesPerNode - 1;
427 lastParticle = numParticles - 1;
430 numParticles = lastParticle - firstParticle + 1;
433 beam->
create(numParticles);
436 dataSource->
readStep(beam, firstParticle, lastParticle);
446 INFOMSG(
"total number of particles = " << globalN <<
endl);
447 INFOMSG(
"* Restart Energy = " << meanE <<
" (MeV), Path lenght = " << beam->
get_sPos() <<
" (m)" <<
endl);
454 INFOMSG(
"* Gamma = " << gamma <<
", Beta = " << beta <<
endl);
457 INFOMSG(
"Restart from hdf5 file generated by OPAL-cycl" <<
endl);
458 if (specifiedNumBunch > 1) {
465 INFOMSG(
"Restart from hdf5 file generated by OPAL-t" <<
endl);
470 for (
unsigned int i = 0; i < newLocalN; ++i) {
471 for (
int d = 0; d < 3; ++d) {
472 meanR(d) += beam->
R[i](d);
473 meanP(d) += beam->
P[i](d);
480 INFOMSG(
"Rmean = " << meanR <<
"[m], Pmean=" << meanP <<
endl);
482 for (
unsigned int i = 0; i < newLocalN; ++i) {
488 INFOMSG(
"---------------Finished reading hdf5 file---------------" <<
endl);
496 throw OpalException(
"Distribution::find()",
"Distribution \"" + name +
"\" not found.");
521 double inv_erf08 = 0.906193802436823;
523 double t = a - sqr2 * sig * inv_erf08;
526 for (
int i = 0; i < 10; ++ i) {
527 sig = (t +
tRise_m - a) / (sqr2 * inv_erf08);
528 t = a - 0.5 * sqr2 * (sig + tmps) * inv_erf08;
529 sig = (0.5 * (t + tmpt) +
tRise_m - a) / (sqr2 * inv_erf08);
549 <<
"* ************* D I S T R I B U T I O N ********************************************" <<
endl;
552 os <<
"* In restart. Distribution read in from .h5 file." <<
endl;
555 os <<
"* Main Distribution" << endl
556 <<
"-----------------" <<
endl;
563 size_t distCount = 1;
566 os <<
"* Added Distribution #" << distCount <<
endl;
567 os <<
"* ----------------------" <<
endl;
581 os <<
"* Distribution is emitted. " <<
endl;
588 os <<
"* Distribution is injected." <<
endl;
592 os <<
"*\n* Write initial distribution to file '" <<
outFilename_m <<
"'" <<
endl;
596 os <<
"* **********************************************************************************" <<
endl;
613 for (
double dist : (*addedDistIt)->getXDist()) {
616 (*addedDistIt)->eraseXDist();
618 for (
double dist : (*addedDistIt)->getBGxDist()) {
621 (*addedDistIt)->eraseBGxDist();
623 for (
double dist : (*addedDistIt)->getYDist()) {
626 (*addedDistIt)->eraseYDist();
628 for (
double dist : (*addedDistIt)->getBGyDist()) {
631 (*addedDistIt)->eraseBGyDist();
633 for (
double dist : (*addedDistIt)->getTOrZDist()) {
636 (*addedDistIt)->eraseTOrZDist();
638 for (
double dist : (*addedDistIt)->getBGzDist()) {
641 (*addedDistIt)->eraseBGzDist();
682 std::vector<double> &additionalRNs) {
690 unsigned int counter = 0;
693 double randFuncValue = additionalRNs[counter++];
695 double funcValue = ((1.0
696 - 1.0 / (1.0 + expRelativeEnergy * expRelativeLaserEnergy)) /
697 (1.0 + expRelativeEnergy));
699 if (randFuncValue <= funcValue)
702 if (counter == additionalRNs.size()) {
703 for (
unsigned int i = 0; i < counter; ++ i) {
704 additionalRNs[i] = gsl_rng_uniform(
randGen_m);
711 while (additionalRNs.size() - counter < 2) {
713 additionalRNs[counter] = gsl_rng_uniform(
randGen_m);
718 double energyExternal = energy - lowEnergyLimit;
720 double thetaInMax =
std::acos(
std::sqrt((lowEnergyLimit + laserEnergy_m) / (energyInternal)));
721 double thetaIn = additionalRNs[counter++] * thetaInMax;
722 double sinThetaOut =
std::sin(thetaIn) *
std::sqrt(energyInternal / energyExternal);
726 double betaGammaExternal
729 bgx = betaGammaExternal * sinThetaOut *
std::cos(phi);
730 bgy = betaGammaExternal * sinThetaOut *
std::sin(phi);
742 std::map<unsigned int, size_t> nPartFromFiles;
743 double totalWeight = 0.0;
750 std::ifstream inputFile;
753 inputFile.open(fileName.c_str());
756 nPartFromFiles.insert(std::make_pair(i, nPart));
757 if (nPart > numberOfParticles) {
759 "Number of particles is too small");
762 numberOfParticles -= nPart;
768 size_t numberOfCommittedPart = 0;
777 size_t particlesCurrentDist = numberOfParticles * currDist->
getWeight() / totalWeight;
779 numberOfCommittedPart += particlesCurrentDist;
784 if (numberOfParticles != numberOfCommittedPart) {
785 size_t diffNumber = numberOfParticles - numberOfCommittedPart;
797 if (diffNumber != 0) {
799 "Particles can't be distributed to distributions in array");
815 if (emissionSteps == 0)
846 size_t numberOfDistParticles =
tOrZDist_m.size();
849 if (numberOfDistParticles == 0) {
851 "Zero particles in the distribution! "
852 "The number of particles needs to be specified.");
857 "A single particle distribution works serially on single node");
860 if (numberOfDistParticles != numberOfParticles) {
862 "The number of particles in the initial\n"
864 std::to_string(numberOfDistParticles) +
"\n"
865 "is different from the number of particles\n"
866 "defined by the BEAM command\n" +
867 std::to_string(numberOfParticles) +
".\n"
868 "This often happens when using a FROMFILE type\n"
869 "distribution and not matching the number of\n"
870 "particles in the input distribution file(s) with\n"
871 "the number given in the BEAM command.");
878 if (momentumTol > 0 &&
881 "The z-momentum of the particle distribution\n" +
882 std::to_string(
pmean_m[2]) +
"\n"
883 "is different from the momentum given in the \"BEAM\" command\n" +
885 "When using a \"FROMFILE\" type distribution\n"
886 "the momentum in the \"BEAM\" command should be\n"
887 "the same as the momentum of the particles in the file.");
895 static const std::map<std::string, InputMomentumUnits> stringInputMomentumUnits_s = {
901 if (inputUnits.empty()) {
934 int saveProcessor = -1;
941 for (
size_t partIndex = 0; partIndex < numberOfParticles; partIndex++) {
942 double x = 0.0, y = 0.0, tOrZ = 0.0;
943 double px = 0.0, py = 0.0, pz = 0.0;
953 double randNums[2] = {0.0, 0.0};
955 if (quasiRandGen2D !=
nullptr) {
956 gsl_qrng_get(quasiRandGen2D, randNums);
958 randNums[0] = gsl_rng_uniform(
randGen_m);
959 randNums[1] = gsl_rng_uniform(
randGen_m);
965 for (
unsigned i = 0; i <
nPeaks_m; i++)
967 allow = (r <= proba);
988 if (saveProcessor >= numNodes)
991 if (scalable || myNode == saveProcessor) {
1001 gsl_qrng_free(quasiRandGen2D);
1006 size_t numberOfParticlesRead = 0;
1008 const boost::regex commentExpr(
"[[:space:]]*#.*");
1009 const std::string repl(
"");
1011 std::stringstream linestream;
1015 std::getline(inputFile, line);
1016 line = boost::regex_replace(line, commentExpr, repl);
1017 }
while (line.length() == 0 && !inputFile.fail());
1019 linestream.str(line);
1020 linestream >> tempInt;
1022 throw OpalException(
"Distribution::getNumberOfParticlesInFile",
1025 "' does not seem to be an ASCII file containing a distribution.");
1027 numberOfParticlesRead =
static_cast<size_t>(tempInt);
1031 return numberOfParticlesRead;
1036 std::ifstream inputFile;
1038 if (!std::filesystem::exists(fileName)) {
1040 "Distribution::createDistributionFromFile",
1041 "Open file operation failed, please check if '" + fileName +
"' really exists.");
1044 inputFile.open(fileName.c_str());
1052 unsigned int saveProcessor = 0;
1056 unsigned int distributeFrequency = 1000;
1057 size_t singleDataSize = 6;
1058 unsigned int dataSize = distributeFrequency * singleDataSize;
1059 std::vector<double> data(dataSize);
1062 constexpr
unsigned int bufferSize = 1024;
1063 char lineBuffer[bufferSize];
1064 unsigned int numParts = 0;
1066 while (!inputFile.eof()) {
1067 inputFile.getline(lineBuffer, bufferSize);
1071 std::istringstream line(lineBuffer);
1091 if (saveProcessor > 0u) {
1092 currentPosition =
std::copy(&(R[0]), &(R[0]) + 3, currentPosition);
1093 currentPosition =
std::copy(&(P[0]), &(P[0]) + 3, currentPosition);
1095 if (currentPosition == data.end()) {
1097 MPI_Bcast(&(data[0]), dataSize, MPI_DOUBLE, 0,
Ippl::getComm());
1099 currentPosition = data.begin();
1115 (numberOfParticlesRead == numParts ? currentPosition - data.begin()
1119 if (numberOfParticlesRead != numParts) {
1121 "Distribution::createDistributionFromFile",
1122 "Found " + std::to_string(numParts) +
" particles in file '" + fileName
1123 +
"' instead of " + std::to_string(numberOfParticlesRead));
1125 MPI_Bcast(&(data[0]), dataSize, MPI_DOUBLE, 0,
Ippl::getComm());
1132 "Distribution::createDistributionFromFile",
1133 "Couldn't find " + std::to_string(numberOfParticlesRead)
1134 +
" particles in file '" + fileName +
"'");
1136 MPI_Bcast(&(data[0]), dataSize, MPI_DOUBLE, 0,
Ippl::getComm());
1139 while (i < dataSize) {
1141 const double* tmp = &(data[i]);
1149 i += singleDataSize;
1156 }
while (dataSize == distributeFrequency * singleDataSize);
1159 pmean_m /= numberOfParticlesRead;
1177 if (lineName.empty())
return;
1180 if (lineSequence ==
nullptr)
1181 throw OpalException(
"Distribution::CreateMatchedGaussDistribution",
1182 "didn't find any Cyclotron element in line");
1186 size_t NumberOfCyclotrons = CyclotronVisitor.size();
1188 if (NumberOfCyclotrons > 1) {
1189 throw OpalException(
"Distribution::createMatchedGaussDistribution",
1190 "I am confused, found more than one Cyclotron element in line");
1192 if (NumberOfCyclotrons == 0) {
1193 throw OpalException(
"Distribution::createMatchedGaussDistribution",
1194 "didn't find any Cyclotron element in line");
1207 throw OpalException(
"Distribution::createMatchedGaussDistribution()",
1208 "Negative number of integration steps");
1211 throw OpalException(
"Distribution::createMatchedGaussDistribution()",
1212 "Negative number of sectors");
1214 if ( Nsectors > 1 && full ==
false )
1215 throw OpalException(
"Distribution::createMatchedGaussDistribution()",
1216 "Averaging over sectors can only be done with SECTOR=FALSE");
1218 *gmsg <<
"* ----------------------------------------------------" <<
endl;
1219 *gmsg <<
"* About to find closed orbit and matched distribution " <<
endl;
1225 *gmsg <<
"* SECTOR: " <<
"match using all sectors, with" << endl
1226 <<
"* NSECTORS = " << Nsectors <<
" to average the field over" <<
endl;
1229 *gmsg <<
"* SECTOR: " <<
"match using single sector" <<
endl;
1231 *gmsg <<
"* NSTEPS = " << Nint << endl
1234 <<
"* FIELD MAP = " << CyclotronElement->
getFieldMapFN() << endl
1235 <<
"* ----------------------------------------------------" <<
endl;
1237 if ( CyclotronElement->
getFMLowE() < 0 ||
1240 throw OpalException(
"Distribution::createMatchedGaussDistribution()",
1241 "Missing attributes 'FMLOWE' and/or 'FMHIGHE' in "
1242 "'CYCLOTRON' definition.");
1245 std::size_t maxitCOF =
1254 if ( denergy < 0.0 )
1255 throw OpalException(
"Distribution:createMatchedGaussDistribution()",
1262 *gmsg <<
"* Stopping after closed orbit and tune calculation" <<
endl;
1263 typedef std::vector<double> container_t;
1264 typedef boost::numeric::odeint::runge_kutta4<container_t> rk4_t;
1267 cof_t cof(massIneV *
Units::eV2MeV, charge, Nint, CyclotronElement, full, Nsectors);
1268 cof.findOrbit(accuracy, maxitCOF,
E_m * Units::eV2MeV, denergy, rguess,
true);
1271 "Do only tune calculation.");
1274 bool writeMap =
true;
1276 std::unique_ptr<SigmaGenerator> siggen = std::unique_ptr<SigmaGenerator>(
1279 Attributes::getReal(
itsAttr[Attrib::Distribution::EY]) *
Units::m2mm * Units::rad2mrad,
1280 Attributes::getReal(
itsAttr[Attrib::Distribution::ET]) *
Units::m2mm * Units::rad2mrad,
1282 massIneV * Units::eV2MeV,
1290 if (siggen->match(accuracy,
1298 std::array<double,3> Emit = siggen->getEmittances();
1301 *gmsg <<
"* RGUESS " << rguess <<
" (m) " <<
endl;
1303 *gmsg <<
"* Converged (Ex, Ey, Ez) = (" << Emit[0] <<
", " << Emit[1] <<
", "
1304 << Emit[2] <<
") pi mm mrad for E= " <<
E_m * Units::eV2MeV <<
" (MeV)" <<
endl;
1305 *gmsg <<
"* Sigma-Matrix " <<
endl;
1307 for (
unsigned int i = 0; i < siggen->getSigma().size1(); ++ i) {
1308 *gmsg << std::setprecision(4) << std::setw(11) << siggen->getSigma()(i,0);
1309 for (
unsigned int j = 1; j < siggen->getSigma().size2(); ++ j) {
1310 if (
std::abs(siggen->getSigma()(i,j)) < 1.0e-15) {
1311 *gmsg <<
" & " << std::setprecision(4) << std::setw(11) << 0.0;
1314 *gmsg <<
" & " << std::setprecision(4) << std::setw(11) << siggen->getSigma()(i,j);
1317 *gmsg <<
" \\\\" <<
endl;
1323 CyclotronElement->
setRinit(siggen->getInjectionRadius());
1324 CyclotronElement->
setPRinit(siggen->getInjectionMomentum());
1327 *gmsg <<
"* Not converged for " <<
E_m * Units::eV2MeV <<
" MeV" <<
endl;
1329 throw OpalException(
"Distribution::CreateMatchedGaussDistribution",
1330 "didn't find any matched distribution.");
1347 size_t numberOfParticles,
1348 double current,
const Beamline &) {
1356 size_t numberOfPartToCreate = numberOfParticles;
1409 std::vector<Distribution *> addedDistributions,
1410 size_t &numberOfParticles) {
1417 size_t &numberOfParticles) {
1440 addedDist->setDistType();
1466 size_t distCount = 1;
1523 std::vector<std::vector<double> > mirrored;
1531 std::vector<double> tmp;
1532 tmp.push_back((*it).front());
1533 tmp.push_back((*it).back() + 0.5);
1534 mirrored.push_back(tmp);
1539 std::vector<double> tmp((*it).begin() + numAdditionals, (*it).end());
1540 mirrored.push_back(tmp);
1541 (*it).erase((*it).begin() + numAdditionals, (*it).end());
1586 size_t numberOfEmittedParticles = beam->
getLocalNum();
1587 size_t oldNumberOfEmittedParticles = numberOfEmittedParticles;
1596 std::vector<size_t> particlesToBeErased;
1602 for (
size_t particleIndex = 0; particleIndex <
tOrZDist_m.size(); particleIndex++) {
1610 particlesToBeErased.push_back(particleIndex);
1613 double deltaT =
tOrZDist_m.at(particleIndex);
1614 beam->
dt[numberOfEmittedParticles] = deltaT;
1616 double oneOverCDt = 1.0 / (
Physics::c * deltaT);
1618 double px =
pxDist_m.at(particleIndex);
1619 double py =
pyDist_m.at(particleIndex);
1620 double pz =
pzDist_m.at(particleIndex);
1621 std::vector<double> additionalRNs;
1626 "not enough additional particles");
1630 double particleGamma
1636 beam->
R[numberOfEmittedParticles]
1638 + px * deltaT *
Physics::c / (2.0 * particleGamma)),
1639 oneOverCDt * (
yDist_m.at(particleIndex)
1640 + py * deltaT *
Physics::c / (2.0 * particleGamma)),
1641 pz / (2.0 * particleGamma));
1642 beam->
P[numberOfEmittedParticles]
1647 beam->
Ef[numberOfEmittedParticles] =
Vector_t(0.0);
1648 beam->
Bf[numberOfEmittedParticles] =
Vector_t(0.0);
1651 beam->
TriID[numberOfEmittedParticles] = 0;
1652 numberOfEmittedParticles++;
1668 std::vector<size_t>::reverse_iterator ptbErasedIt;
1669 for (ptbErasedIt = particlesToBeErased.rbegin();
1670 ptbErasedIt < particlesToBeErased.rend();
1710 <<
" has emitted all particles (new emit)." <<
endl);
1738 size_t currentEmittedParticles = numberOfEmittedParticles - oldNumberOfEmittedParticles;
1742 return currentEmittedParticles;
1773 double randNums[2] = {0.0, 0.0};
1775 if (quasiRandGen2D !=
nullptr)
1776 gsl_qrng_get(quasiRandGen2D, randNums);
1778 randNums[0] = gsl_rng_uniform(
randGen_m);
1779 randNums[1] = gsl_rng_uniform(
randGen_m);
1782 x1 = 2 * randNums[0] - 1;
1783 x2 = 2 * randNums[1] - 1;
1794 const size_t numberOfParticles =
tOrZDist_m.size();
1795 for (
size_t partIndex = 0; partIndex < numberOfParticles; partIndex++) {
1809 for (
size_t particleIndex = 0; particleIndex <
tOrZDist_m.size(); particleIndex++) {
1811 std::vector<double> partCoord;
1813 partCoord.push_back(
xDist_m.at(particleIndex));
1814 partCoord.push_back(
yDist_m.at(particleIndex));
1815 partCoord.push_back(
tOrZDist_m.at(particleIndex));
1816 partCoord.push_back(
pxDist_m.at(particleIndex));
1817 partCoord.push_back(
pyDist_m.at(particleIndex));
1818 partCoord.push_back(
pzDist_m.at(particleIndex));
1819 partCoord.push_back(0.0);
1849 gsl_qrng *quasiRandGen = gsl_qrng_alloc(gsl_qrng_halton, 2);
1851 int numberOfSampleBins
1853 int numberOfEnergyBins
1856 int binTotal = numberOfSampleBins * numberOfEnergyBins;
1858 double *distributionTable =
new double[binTotal + 1];
1862 double inv_erf08 = 0.906193802436823;
1864 double t = a - sqr2 * sig * inv_erf08;
1868 for (
int i = 0; i < 10; ++ i) {
1869 sig = (t +
tRise_m - a) / (sqr2 * inv_erf08);
1870 t = a - 0.5 * sqr2 * (sig + tmps) * inv_erf08;
1871 sig = (0.5 * (t + tmpt) +
tRise_m - a) / (sqr2 * inv_erf08);
1883 double lo = -
tBin_m / 2.0 * numberOfEnergyBins;
1884 double hi =
tBin_m / 2.0 * numberOfEnergyBins;
1885 double dx =
tBin_m / numberOfSampleBins;
1888 double weight = 2.0;
1891 for (
int i = 0; i < binTotal + 1; ++ i, x += dx, weight = 6. - weight) {
1892 distributionTable[i] = gsl_sf_erf((x + a) / (sqr2 * sig)) - gsl_sf_erf((x - a) / (sqr2 * sig));
1893 tot += distributionTable[i] * weight;
1895 tot -= distributionTable[binTotal] * (5. - weight);
1896 tot -= distributionTable[0];
1898 int saveProcessor = -1;
1902 double tCoord = 0.0;
1904 int effectiveNumParticles = 0;
1906 std::vector<int> numParticlesInBin(numberOfEnergyBins,0);
1907 for (
int k = 0; k < numberOfEnergyBins; ++ k) {
1908 double loc_fraction = -distributionTable[numberOfSampleBins * k] / tot;
1911 for (
int i = numberOfSampleBins * k; i < numberOfSampleBins * (k + 1) + 1;
1912 ++ i, weight = 6. - weight) {
1913 loc_fraction += distributionTable[i] * weight / tot;
1915 loc_fraction -= distributionTable[numberOfSampleBins * (k + 1)]
1916 * (5. - weight) / tot;
1917 numParticlesInBin[k] =
static_cast<int>(std::round(loc_fraction * numberOfParticles));
1918 effectiveNumParticles += numParticlesInBin[k];
1919 if (numParticlesInBin[k] > numParticlesInBin[largestBin]) largestBin = k;
1922 numParticlesInBin[largestBin] += (numberOfParticles - effectiveNumParticles);
1924 for (
int k = 0; k < numberOfEnergyBins; ++ k) {
1925 gsl_ran_discrete_t *table
1926 = gsl_ran_discrete_preproc(numberOfSampleBins,
1927 &(distributionTable[numberOfSampleBins * k]));
1929 for (
int i = 0; i < numParticlesInBin[k]; i++) {
1931 gsl_qrng_get(quasiRandGen, xx);
1932 tCoord = hi * (xx[1] +
static_cast<int>(gsl_ran_discrete(
randGen_m, table))
1933 - binTotal / 2 + k * numberOfSampleBins) / (binTotal / 2);
1936 if (saveProcessor >= numNodes)
1939 if (scalable || myNode == saveProcessor) {
1944 gsl_ran_discrete_free(table);
1947 gsl_qrng_free(quasiRandGen);
1948 delete [] distributionTable;
1976 for (
unsigned int index = 0; index < 3; index++) {
1980 if (
std::abs(emittance(index)) > std::numeric_limits<double>::epsilon()) {
1988 *
std::sqrt(beta(index) * gamma(index));
1995 for (
unsigned int index = 0; index < 3; index++) {
1999 SINCHI[index] = -
alpha(index) * COSCHI[index];
2000 CHI[index] =
std::atan2(SINCHI[index], COSCHI[index]);
2002 M[index] =
std::sqrt(emittance(index) * beta(index));
2003 PM[index] =
std::sqrt(emittance(index) * gamma(index));
2008 X[index] = L[index];
2009 PX[index] = PL[index];
2012 X[index] = M[index];
2013 PX[index] = PM[index];
2018 int saveProcessor = -1;
2039 for (
size_t partIndex = 0; partIndex < numberOfParticles; partIndex++) {
2043 double Ux = 0.0, U = 0.0;
2044 double Vx = 0.0, V = 0.0;
2046 A = splitter[0]->get(gsl_rng_uniform(
randGen_m));
2051 p[0] = PX[0] * (Ux * SINCHI[0] + Vx * COSCHI[0]);
2053 A = splitter[1]->get(gsl_rng_uniform(
randGen_m));
2058 p[1] = PX[1] * (U * SINCHI[1] + V * COSCHI[1]);
2060 A = splitter[2]->get(gsl_rng_uniform(
randGen_m));
2069 if (saveProcessor >= numNodes)
2072 if (scalable || myNode == saveProcessor) {
2082 for (
unsigned int index = 0; index < 3; index++) {
2083 delete splitter[index];
2089 int saveProcessor = -1;
2094 for (
size_t partIndex = 0; partIndex < numberOfParticles; partIndex++) {
2105 if (saveProcessor >= numNodes)
2108 if (scalable || myNode == saveProcessor) {
2111 yDist_m.push_back(y * sigmaR_m[1]);
2127 int saveProcessor = -1;
2131 for (
size_t partIndex = 0; partIndex < numberOfParticles; partIndex++) {
2144 if (saveProcessor >= numNodes)
2147 if (scalable || myNode == saveProcessor) {
2156 gsl_qrng_free(quasiRandGen2D);
2170 int saveProcessor = -1;
2175 for (
size_t partIndex = 0; partIndex < numberOfParticles; partIndex++) {
2188 if (quasiRandGen1D !=
nullptr)
2189 gsl_qrng_get(quasiRandGen1D, &z);
2197 if (saveProcessor >= numNodes)
2200 if (scalable || myNode == saveProcessor) {
2210 gsl_qrng_free(quasiRandGen1D);
2211 gsl_qrng_free(quasiRandGen2D);
2216 gsl_matrix * corMat = gsl_matrix_alloc (6, 6);
2217 gsl_vector * rx = gsl_vector_alloc(6);
2218 gsl_vector * ry = gsl_vector_alloc(6);
2220 for (
unsigned int i = 0; i < 6; ++ i) {
2222 for (
unsigned int j = 0; j < i; ++ j) {
2230 *gmsg <<
"* m before gsl_linalg_cholesky_decomp" <<
endl;
2231 for (
int i = 0; i < 6; i++) {
2232 for (
int j = 0; j < 6; j++) {
2234 *gmsg <<
"* r(" << std::setprecision(1) << i <<
", : ) = "
2235 << std::setprecision(4) << std::setw(10) << gsl_matrix_get (corMat, i, j);
2237 *gmsg <<
" & " << std::setprecision(4) << std::setw(10) << gsl_matrix_get (corMat, i, j);
2239 *gmsg <<
" \\\\" <<
endl;
2246 int errcode = gsl_linalg_cholesky_decomp(corMat);
2275 if (errcode == GSL_EDOM) {
2277 "gsl_linalg_cholesky_decomp failed");
2280 for (
int i = 0; i < 5; ++ i) {
2281 for (
int j = i+1; j < 6 ; ++ j) {
2282 gsl_matrix_set (corMat, i, j, 0.0);
2287 *gmsg <<
"* m after gsl_linalg_cholesky_decomp" <<
endl;
2288 for (
int i = 0; i < 6; i++) {
2289 for (
int j = 0; j < 6; j++) {
2291 *gmsg <<
"* r(" << std::setprecision(1) << i <<
", : ) = "
2292 << std::setprecision(4) << std::setw(10) << gsl_matrix_get (corMat, i, j);
2294 *gmsg <<
" & " << std::setprecision(4) << std::setw(10) << gsl_matrix_get (corMat, i, j);
2296 *gmsg <<
" \\\\" <<
endl;
2300 int saveProcessor = -1;
2305 for (
size_t partIndex = 0; partIndex < numberOfParticles; partIndex++) {
2316 gsl_vector_set(rx, 0, gsl_ran_gaussian(
randGen_m, 1.0));
2317 gsl_vector_set(rx, 1, gsl_ran_gaussian(
randGen_m, 1.0));
2318 gsl_vector_set(rx, 2, gsl_ran_gaussian(
randGen_m, 1.0));
2319 gsl_vector_set(rx, 3, gsl_ran_gaussian(
randGen_m, 1.0));
2320 gsl_vector_set(rx, 4, gsl_ran_gaussian(
randGen_m, 1.0));
2321 gsl_vector_set(rx, 5, gsl_ran_gaussian(
randGen_m, 1.0));
2323 gsl_blas_dgemv(CblasNoTrans, 1.0, corMat, rx, 0.0, ry);
2325 x = gsl_vector_get(ry, 0);
2326 px = gsl_vector_get(ry, 1);
2327 y = gsl_vector_get(ry, 2);
2328 py = gsl_vector_get(ry, 3);
2329 z = gsl_vector_get(ry, 4);
2330 pz = gsl_vector_get(ry, 5);
2338 allow = (xAndYOk && pxAndPyOk && zOk && pzOk);
2350 if (saveProcessor >= numNodes)
2353 if (scalable || myNode == saveProcessor) {
2365 gsl_vector_free(rx);
2366 gsl_vector_free(ry);
2367 gsl_matrix_free(corMat);
2371 size_t numberOfParticles,
double massIneV)
2384 for (
unsigned int i = 0; i < 3; ++ i) {
2385 if ( sigma(2 * i, 2 * i) < 0 || sigma(2 * i + 1, 2 * i + 1) < 0 )
2387 "Negative value on the diagonal of the sigma matrix.");
2424 A(0, 0) = sigma(0, 0);
2425 A(1, 1) = sigma(1, 1);
2426 A(2, 2) = sigma(4, 4);
2427 A(3, 3) = sigma(5, 5);
2429 A(0, 1) = sigma(0, 1);
2430 A(0, 2) = sigma(0, 4);
2431 A(0, 3) = sigma(0, 5);
2432 A(1, 0) = sigma(1, 0);
2433 A(2, 0) = sigma(4, 0);
2434 A(3, 0) = sigma(5, 0);
2436 A(1, 2) = sigma(1, 4);
2437 A(2, 1) = sigma(4, 1);
2438 A(1, 3) = sigma(1, 5);
2439 A(3, 1) = sigma(5, 1);
2440 A(2, 3) = sigma(4, 5);
2441 A(3, 2) = sigma(5, 4);
2448 for (
int i = 0; i < 4; ++i) {
2458 A(2, 2) = sigma(2, 2);
2459 A(3, 3) = sigma(3, 3);
2460 A(2, 3) = sigma(2, 3);
2461 A(3, 2) = sigma(3, 2);
2465 for (
int i = 0; i < 4; ++i) {
2469 int saveProcessor = -1;
2475 for (
size_t i = 0; i < numberOfParticles; i++) {
2476 for (
int j = 0; j < 4; j++) {
2477 p1(j) = gsl_ran_gaussian(
randGen_m, 1.0) * variances(j);
2478 p2(j) = gsl_ran_gaussian(
randGen_m, 1.0) * variances(4 + j);
2486 if (saveProcessor >= numNodes)
2489 if (scalable || myNode == saveProcessor) {
2505 if (flattopTime < 0.0)
2509 double distArea = flattopTime
2513 size_t numRise = numberOfParticles *
sigmaTRise_m * normalizedFlankArea / distArea;
2514 size_t numFall = numberOfParticles *
sigmaTFall_m * normalizedFlankArea / distArea;
2515 size_t numFlat = numberOfParticles - numRise - numFall;
2518 int saveProcessor = -1;
2523 for (
size_t partIndex = 0; partIndex < numFall; partIndex++) {
2539 if (saveProcessor >= numNodes)
2542 if (scalable || myNode == saveProcessor) {
2553 if (modulationAmp > 1.0)
2554 modulationAmp = 1.0;
2555 double numModulationPeriods
2557 double modulationPeriod = 0.0;
2558 if (numModulationPeriods != 0.0)
2559 modulationPeriod = flattopTime / numModulationPeriods;
2564 for (
size_t partIndex = 0; partIndex < numFlat; partIndex++) {
2569 if (modulationAmp == 0.0 || numModulationPeriods == 0.0) {
2571 if (quasiRandGen1D !=
nullptr)
2572 gsl_qrng_get(quasiRandGen1D, &t);
2576 t = flattopTime * t;
2581 double randNums[2] = {0.0, 0.0};
2583 if (quasiRandGen2D !=
nullptr) {
2584 gsl_qrng_get(quasiRandGen2D, randNums);
2586 randNums[0]= gsl_rng_uniform(
randGen_m);
2587 randNums[1]= gsl_rng_uniform(
randGen_m);
2589 t = randNums[0] * flattopTime;
2591 double funcValue = (1.0 + modulationAmp
2595 allow = (randNums[1] <= funcValue);
2603 if (saveProcessor >= numNodes)
2606 if (scalable || myNode == saveProcessor) {
2613 for (
size_t partIndex = 0; partIndex < numRise; partIndex++) {
2629 if (saveProcessor >= numNodes)
2632 if (scalable || myNode == saveProcessor) {
2638 gsl_qrng_free(quasiRandGen1D);
2639 gsl_qrng_free(quasiRandGen2D);
2645 gsl_matrix * corMat = gsl_matrix_alloc (4, 4);
2646 gsl_vector * rx = gsl_vector_alloc(4);
2647 gsl_vector * ry = gsl_vector_alloc(4);
2649 for (
unsigned int i = 0; i < 4; ++ i) {
2651 for (
unsigned int j = 0; j < i; ++ j) {
2657 int errcode = gsl_linalg_cholesky_decomp(corMat);
2659 if (errcode == GSL_EDOM) {
2660 throw OpalException(
"Distribution::GenerateTransverseGauss",
2661 "gsl_linalg_cholesky_decomp failed");
2664 for (
int i = 0; i < 3; ++ i) {
2665 for (
int j = i+1; j < 4 ; ++ j) {
2666 gsl_matrix_set (corMat, i, j, 0.0);
2670 int saveProcessor = -1;
2675 for (
size_t partIndex = 0; partIndex < numberOfParticles; partIndex++) {
2685 gsl_vector_set(rx, 0, gsl_ran_gaussian (
randGen_m,1.0));
2686 gsl_vector_set(rx, 1, gsl_ran_gaussian (
randGen_m,1.0));
2687 gsl_vector_set(rx, 2, gsl_ran_gaussian (
randGen_m,1.0));
2688 gsl_vector_set(rx, 3, gsl_ran_gaussian (
randGen_m,1.0));
2690 gsl_blas_dgemv(CblasNoTrans, 1.0, corMat, rx, 0.0, ry);
2691 x = gsl_vector_get(ry, 0);
2692 px = gsl_vector_get(ry, 1);
2693 y = gsl_vector_get(ry, 2);
2694 py = gsl_vector_get(ry, 3);
2699 allow = (xAndYOk && pxAndPyOk);
2709 if (saveProcessor >= numNodes)
2712 if (scalable || myNode == saveProcessor) {
2720 gsl_matrix_free(corMat);
2721 gsl_vector_free(rx);
2722 gsl_vector_free(ry);
2744 bool hasID1 = !id1.empty();
2745 bool hasID2 = !id2.empty();
2747 if (hasID1 || hasID2)
2748 *gmsg <<
"* Use special ID1 or ID2 particle in distribution" <<
endl;
2751 size_t numberOfParticles =
tOrZDist_m.size();
2752 beam->
create(numberOfParticles);
2753 for (
size_t partIndex = 0; partIndex < numberOfParticles; partIndex++) {
2769 beam->
TriID[partIndex] = 0;
2772 beam->
Bin[partIndex] = binNumber;
2775 beam->
Bin[partIndex] = 0;
2778 if (beam->
ID[partIndex] == 1) {
2779 beam->
R[partIndex] =
Vector_t(id1[0],id1[1],id1[2]);
2780 beam->
P[partIndex] =
Vector_t(id1[3],id1[4],id1[5]);
2785 if (beam->
ID[partIndex] == 2) {
2786 beam->
R[partIndex] =
Vector_t(id2[0],id2[1],id2[2]);
2787 beam->
P[partIndex] =
Vector_t(id2[3],id2[4],id2[5]);
2883 if (numberOfParticles > 0) {
2886 os <<
"* Number of particles: "
2892 os <<
"* Distribution input momentum units: ";
2895 os <<
"[Beta Gamma]" <<
"\n* " <<
endl;
2899 os <<
"[eV/c]" <<
"\n* " <<
endl;
2904 "Unknown \"INPUTMOUNITS\" for \"DISTRIBUTION\" command");
2930 "Unknown \"TYPE\" of \"DISTRIBUTION\"");
2936 os <<
"* Distribution type: BINOMIAL" <<
endl;
2941 os <<
"* SIGMAT = " <<
sigmaR_m[2] <<
" [sec]" <<
endl;
2944 os <<
"* SIGMAPX = " <<
sigmaP_m[0] <<
" [Beta Gamma]" <<
endl;
2945 os <<
"* SIGMAPY = " <<
sigmaP_m[1] <<
" [Beta Gamma]" <<
endl;
2946 os <<
"* SIGMAPZ = " <<
sigmaP_m[2] <<
" [Beta Gamma]" <<
endl;
2967 os <<
"* Distribution type: ASTRAFLATTOPTH" <<
endl;
2971 os <<
"* Distribution type: GUNGAUSSFLATTOPTH" <<
endl;
2975 os <<
"* Distribution type: FLATTOP" <<
endl;
2983 os <<
"* Transverse profile determined by laser image: " << endl
3000 os <<
"* Time Rise = " <<
tRise_m
3001 <<
" [sec]" <<
endl;
3003 <<
" [sec]" <<
endl;
3007 <<
" [sec]" <<
endl;
3009 <<
" [sec]" <<
endl;
3011 <<
" [sec]" <<
endl;
3012 os <<
"* Longitudinal cutoff = " <<
cutoffR_m[2]
3013 <<
" [units of Sigma Time]" <<
endl;
3014 os <<
"* Flat top modulation amplitude = "
3016 <<
" [Percent of distribution amplitude]" <<
endl;
3017 os <<
"* Flat top modulation periods = "
3029 os <<
"* Distribution type: MULTIGAUSS" <<
endl;
3036 std::string longUnits;
3038 longUnits =
" [sec]";
3042 os <<
"* SIGMAZ = " <<
sigmaR_m[2] << longUnits <<
endl;
3043 os <<
"* CUTOFFLONG = " <<
cutoffR_m[2] <<
" [units of SIGMAZ]" <<
endl;
3048 os <<
"* SIGMAPX = " <<
sigmaP_m[0] <<
" [Beta Gamma]" <<
endl;
3049 os <<
"* SIGMAPY = " <<
sigmaP_m[1] <<
" [Beta Gamma]" <<
endl;
3050 os <<
"* SIGMAPZ = " <<
sigmaP_m[2] <<
" [Beta Gamma]" <<
endl;
3051 os <<
"* CUTOFFPX = " <<
cutoffP_m[0] <<
" [units of SIGMAPX]" <<
endl;
3052 os <<
"* CUTOFFPY = " <<
cutoffP_m[1] <<
" [units of SIGMAPY]" <<
endl;
3053 os <<
"* CUTOFFPZ = " <<
cutoffP_m[2] <<
" [units of SIGMAPZ]" <<
endl;
3058 os <<
"* Distribution type: FROMFILE" <<
endl;
3060 os <<
"* Input file: '"
3066 os <<
"* Distribution type: MATCHEDGAUSS" <<
endl;
3070 os <<
"* SIGMAPX = " <<
sigmaP_m[0] <<
" [Beta Gamma]" <<
endl;
3071 os <<
"* SIGMAPY = " <<
sigmaP_m[1] <<
" [Beta Gamma]" <<
endl;
3072 os <<
"* SIGMAPZ = " <<
sigmaP_m[2] <<
" [Beta Gamma]" <<
endl;
3091 os <<
"* Distribution type: GAUSS" <<
endl;
3095 <<
" [sec]" <<
endl;
3097 <<
" [sec]" <<
endl;
3099 <<
" [sec]" <<
endl;
3100 os <<
"* Longitudinal cutoff = " <<
cutoffR_m[2]
3101 <<
" [units of Sigma Time]" <<
endl;
3102 os <<
"* Flat top modulation amplitude = "
3104 <<
" [Percent of distribution amplitude]" <<
endl;
3105 os <<
"* Flat top modulation periods = "
3110 os <<
"* SIGMAPX = " <<
sigmaP_m[0]
3111 <<
" [Beta Gamma]" <<
endl;
3112 os <<
"* SIGMAPY = " <<
sigmaP_m[1]
3113 <<
" [Beta Gamma]" <<
endl;
3117 <<
" [units of SIGMAX]" <<
endl;
3119 <<
" [units of SIGMAY]" <<
endl;
3121 <<
" [units of SIGMAPX]" <<
endl;
3123 <<
" [units of SIGMAPY]" <<
endl;
3128 os <<
"* SIGMAPX = " <<
sigmaP_m[0] <<
" [Beta Gamma]" <<
endl;
3129 os <<
"* SIGMAPY = " <<
sigmaP_m[1] <<
" [Beta Gamma]" <<
endl;
3130 os <<
"* SIGMAPZ = " <<
sigmaP_m[2] <<
" [Beta Gamma]" <<
endl;
3131 os <<
"* AVRGPZ = " <<
avrgpz_m <<
" [Beta Gamma]" <<
endl;
3140 os <<
"* CUTOFFX = " <<
cutoffR_m[0] <<
" [units of SIGMAX]" <<
endl;
3141 os <<
"* CUTOFFY = " <<
cutoffR_m[1] <<
" [units of SIGMAY]" <<
endl;
3142 os <<
"* CUTOFFLONG = " <<
cutoffR_m[2] <<
" [units of SIGMAZ]" <<
endl;
3143 os <<
"* CUTOFFPX = " <<
cutoffP_m[0] <<
" [units of SIGMAPX]" <<
endl;
3144 os <<
"* CUTOFFPY = " <<
cutoffP_m[1] <<
" [units of SIGMAPY]" <<
endl;
3145 os <<
"* CUTOFFPZ = " <<
cutoffP_m[2] <<
" [units of SIGMAPY]" <<
endl;
3151 os <<
"* ------------- THERMAL EMITTANCE MODEL --------------------------------------------" <<
endl;
3168 os <<
"* ----------------------------------------------------------------------------------" <<
endl;
3173 os <<
"* THERMAL EMITTANCE in ASTRA MODE" <<
endl;
3174 os <<
"* Kinetic energy (thermal emittance) = "
3176 <<
" [eV] " <<
endl;
3180 os <<
"* THERMAL EMITTANCE in NONE MODE" <<
endl;
3181 os <<
"* Kinetic energy added to longitudinal momentum = "
3183 <<
" [eV] " <<
endl;
3187 os <<
"* THERMAL EMITTANCE in NONEQUIL MODE" <<
endl;
3201 binIndex * numberOfSampleBins_m + sampleIndex);
3204 <<
" contains " << sum <<
" particles" <<
endl;
3229 for (
size_t partIndex = 0; partIndex < currentNumPart; partIndex++) {
3242 (numberOfParticles + 1) / 2 != numberOfParticles / 2) {
3264 for (
size_t particleIndex = 0; particleIndex <
tOrZDist_m.size(); ++ particleIndex) {
3265 xDist_m.at(particleIndex) *= xmult;
3266 pxDist_m.at(particleIndex) *= pxmult;
3267 yDist_m.at(particleIndex) *= ymult;
3268 pyDist_m.at(particleIndex) *= pymult;
3270 pzDist_m.at(particleIndex) *= pzmult;
3276 gsl_qrng *quasiRandGen =
nullptr;
3280 quasiRandGen = gsl_qrng_alloc(gsl_qrng_halton, dimension);
3282 quasiRandGen = gsl_qrng_alloc(gsl_qrng_sobol, dimension);
3284 quasiRandGen = gsl_qrng_alloc(gsl_qrng_niederreiter_2, dimension);
3287 quasiRandGen = gsl_qrng_alloc(gsl_qrng_halton, dimension);
3290 return quasiRandGen;
3301 "GUNGAUSSFLATTOPTH",
3309 =
Attributes::makeReal(
"EX",
"Projected normalized emittance EX (m-rad), used to create matched distribution ", 1E-6);
3311 =
Attributes::makeReal(
"EY",
"Projected normalized emittance EY (m-rad) used to create matched distribution ", 1E-6);
3313 =
Attributes::makeReal(
"ET",
"Projected normalized emittance ET (m-rad) used to create matched distribution ", 1E-6);
3317 =
Attributes::makeReal(
"RESIDUUM",
"Residuum for the closed orbit finder and sigma matrix generator ", 1
e-8);
3326 " (false: using all sectors) (default: true)",
3329 =
Attributes::makeReal(
"NSTEPS",
"Number of integration steps of closed orbit finder (matched gauss)"
3330 " (default: 720)", 720);
3339 =
Attributes::makeReal(
"NSECTORS",
"Number of sectors to average field, for closed orbit finder ", 1);
3351 "distribution list.", 1.0);
3359 "an injected beam.",
false);
3366 {
"NONE",
"ASTRA",
"NONEQUIL"},
"NONE");
3369 "model (eV). (Thermal energy added in with random "
3370 "number generator.)", 1.0);
3373 "emission. (Default 255 nm light.)", 4.86);
3376 " (Default atomically clean copper.)", 4.31);
3379 " (Default atomically clean copper.)", 7.0);
3382 " (Default 300 K.)", 300.0);
3385 "charge solve.", 0.0);
3431 "Gaussian peaks in MultiGauss "
3432 "distribution.", 0.0);
3434 " pulses in MultiGauss "
3435 "distribution.", 0.0);
3438 "0.0 ... infinity.", 10001.0);
3441 "0.0 ... infinity.", 10001.0);
3444 "0.0 ... infinity.", 10001.0);
3447 "0.0 ... infinity.", 10001.0);
3450 "direction in units of sigma.", 3.0);
3452 "direction in units of sigma.", 3.0);
3454 "direction in units of sigma.", 3.0);
3457 "units of sigma.", 3.0);
3459 "dimension in units of sigma.", 3.0);
3461 "dimension in units of sigma.", 3.0);
3463 "dimension in units of sigma.", 3.0);
3467 "on flat top portion of emitted GAUSS "
3468 "distribtuion (in percent of flat top "
3472 "flat top portion of emitted GAUSS "
3473 "distribution", 0.0);
3512 "profile (x,y).",
"");
3517 "image profile, in % of max intensity.",
3524 =
Attributes::makeBool(
"ROTATE90",
"Rotate laser profile 90 degrees counter clockwise",
false);
3526 =
Attributes::makeBool(
"ROTATE180",
"Rotate laser profile 180 degrees counter clockwise",
false);
3528 =
Attributes::makeBool(
"ROTATE270",
"Rotate laser profile 270 degrees counter clockwise",
false);
3542 "respect of number of particles and number of cores",
false);
3556 "when emitting a distribution.", 100.0);
3606 "The attribute \"DISTRIBUTION\" isn't supported any more, use \"TYPE\" instead");
3609 static const std::map<std::string, DistributionType> typeStringToDistType_s = {
3624 "The attribute \"TYPE\" isn't set for the \"DISTRIBUTION\"!");
3652 WARNMSG(
"The attribute SIGMAPT may be removed in a future version\n"
3653 <<
"use SIGMAPZ instead" <<
endl);
3690 double deltaT = maxT - minT;
3704 double deltaT = maxT - minT;
3721 throw OpalException(
"Distribution::setDistParametersBinomial",
3722 "Attribute R is not supported for binomial distribution\n"
3723 "use CORR[X|Y|Z] and R51, R52, R61, R62 instead");
3884 if (cr.size() == 15) {
3885 *gmsg <<
"* Use r to specify correlations" <<
endl;
3887 for (
unsigned int i = 0; i < 5; ++ i) {
3888 for (
unsigned int j = i + 1; j < 6; ++ j, ++ k) {
3896 "Inconsistent set of correlations specified, check manual");
3950 for (
int i=0; i<3; i++) {
3960 static const std::map<std::string, EmissionModel> stringEmissionModel_s = {
3967 if (model.empty()) {
4009 size_t numParticles =
pzDist_m.size();
4012 avgPz /= numParticles;
4059 "PT is obsolete. The moments of the beam is defined with OFFSETPZ");
4062 const double pz = beam->
getP()/beam->
getM();
4063 double gamma = std::hypot(pz, 1.0);
4108 double avgZ[] = {0.0, 1.0 *
tOrZDist_m.size()};
4115 for (
double& tOrZ : tOrZDist_m)
4129 size_t startIdx = 0;
4144 "Attribute T isn't supported anymore; use OFFSETZ instead");
4147 double deltaTOrZ = 0.0;
4157 WARNMSG(
"PT & PZ are obsolete and will be ignored. The moments of the beam is defined with PC" <<
endl);
4167 for (
size_t particleIndex = startIdx; particleIndex < endIdx; ++ particleIndex) {
4168 xDist_m.at(particleIndex) += deltaX;
4169 pxDist_m.at(particleIndex) += deltaPx;
4170 yDist_m.at(particleIndex) += deltaY;
4171 pyDist_m.at(particleIndex) += deltaPy;
4173 pzDist_m.at(particleIndex) += deltaPz;
4197 if (outputFile.bad()) {
4200 outputFile.
setf(std::ios::left);
4202 outputFile.width(17);
4203 outputFile <<
"x [m]";
4204 outputFile.width(17);
4205 outputFile <<
"px [betax gamma]";
4206 outputFile.width(17);
4207 outputFile <<
"y [m]";
4208 outputFile.width(17);
4209 outputFile <<
"py [betay gamma]";
4211 outputFile.width(17);
4212 outputFile <<
"t [s]";
4214 outputFile.width(17);
4215 outputFile <<
"z [m]";
4217 outputFile.width(17);
4218 outputFile <<
"pz [betaz gamma]" ;
4220 outputFile.width(17);
4221 outputFile <<
"Bin Number" <<
std::endl;
4224 outputFile.
width(17);
4225 outputFile <<
"Bin Number";
4229 outputFile <<
"# " << totalNum <<
std::endl;
4250 std::vector<char> msgbuf;
4251 const size_t bitsPerParticle = (6 *
sizeof(double) +
sizeof(
size_t));
4252 size_t totalSendBits =
xWrite_m.size() * bitsPerParticle;
4266 if (totalSendBits > 0) {
4267 msgbuf.reserve(totalSendBits);
4269 for (
size_t idx = 0; idx <
xWrite_m.size(); ++ idx) {
4270 buffer =
reinterpret_cast<const char*
>(&(
xWrite_m[idx]));
4271 msgbuf.insert(msgbuf.end(), buffer, buffer +
sizeof(double));
4272 buffer =
reinterpret_cast<const char*
>(&(
pxWrite_m[idx]));
4273 msgbuf.insert(msgbuf.end(), buffer, buffer +
sizeof(double));
4274 buffer =
reinterpret_cast<const char*
>(&(
yWrite_m[idx]));
4275 msgbuf.insert(msgbuf.end(), buffer, buffer +
sizeof(double));
4276 buffer =
reinterpret_cast<const char*
>(&(
pyWrite_m[idx]));
4277 msgbuf.insert(msgbuf.end(), buffer, buffer +
sizeof(double));
4278 buffer =
reinterpret_cast<const char*
>(&(
tOrZWrite_m[idx]));
4279 msgbuf.insert(msgbuf.end(), buffer, buffer +
sizeof(double));
4280 buffer =
reinterpret_cast<const char*
>(&(
pzWrite_m[idx]));
4281 msgbuf.insert(msgbuf.end(), buffer, buffer +
sizeof(double));
4282 buffer =
reinterpret_cast<const char*
>(&(
binWrite_m[idx]));
4283 msgbuf.insert(msgbuf.end(), buffer, buffer +
sizeof(size_t));
4290 if (outputFile.bad()) {
4293 if (numberOfBits[node] == 0)
continue;
4294 char *recvbuf =
new char[numberOfBits[node]];
4300 outputFile.precision(9);
4301 outputFile.setf(std::ios::scientific);
4302 outputFile.setf(std::ios::right);
4304 for (
size_t partIndex = 0; partIndex <
xWrite_m.size(); partIndex++) {
4306 outputFile << std::setw(17) <<
xWrite_m.at(partIndex)
4307 << std::setw(17) <<
pxWrite_m.at(partIndex)
4308 << std::setw(17) <<
yWrite_m.at(partIndex)
4309 << std::setw(17) <<
pyWrite_m.at(partIndex)
4311 << std::setw(17) <<
pzWrite_m.at(partIndex)
4317 if (numberOfBits[i] > 0) numSenders ++;
4320 for (
int i = 0; i < numSenders; ++ i) {
4326 while (j < bufsize) {
4327 const double *dbuffer =
reinterpret_cast<const double*
>(recvbuf + j);
4328 const size_t *sbuffer =
reinterpret_cast<const size_t*
>(recvbuf + j + 6 *
sizeof(double));
4329 outputFile << std::setw(17) << dbuffer[0]
4330 << std::setw(17) << dbuffer[1]
4331 << std::setw(17) << dbuffer[2]
4332 << std::setw(17) << dbuffer[3]
4333 << std::setw(17) << dbuffer[4]
4334 << std::setw(17) << dbuffer[5]
4335 << std::setw(17) << sbuffer[0]
4337 j += bitsPerParticle;
4365 for (
int nodeIndex = 0; nodeIndex <
Ippl::getNodes(); nodeIndex++) {
4368 size_t numberOfParticles = 0;
4371 if (outputFile.bad()) {
4372 *gmsg <<
"Node " <<
Ippl::myNode() <<
" unable to write"
4377 outputFile.setf(std::ios::scientific);
4378 outputFile.setf(std::ios::right);
4381 for (
size_t partIndex = 0; partIndex < numberOfParticles; partIndex++) {
4383 outputFile.width(17);
4384 outputFile <<
xDist_m.at(partIndex);
4385 outputFile.width(17);
4386 outputFile <<
pxDist_m.at(partIndex);
4387 outputFile.width(17);
4388 outputFile <<
yDist_m.at(partIndex);
4389 outputFile.width(17);
4390 outputFile <<
pyDist_m.at(partIndex);
4391 outputFile.width(17);
4393 outputFile.width(17);
4394 outputFile <<
pzDist_m.at(partIndex);
4397 outputFile.width(17);
4398 outputFile << binNumber;
4439 for (
unsigned int i = 0; i <
pzDist_m.size(); ++ i) {
4445 allreduce(&(avrg[0]), 6, std::plus<double>());
4451 for (
unsigned int i = 0; i <
pzDist_m.size(); ++ i) {
std::string laserProfileFileName_m
Attribute makeReal(const std::string &name, const std::string &help)
Make real attribute.
virtual double get(double rand)
double cathodeFermiEnergy_m
Laser photon energy (eV).
static OpalData * getInstance()
boost::numeric::ublas::matrix< double > matrix_t
void applyEmissModelNonEquil(double eZ, double &px, double &py, double &pz, std::vector< double > &additionalRNs)
void setupEnergyBins(double maxTOrZ, double minTOrZ)
bool builtin
Built-in flag.
Tps< T > sqrt(const Tps< T > &x)
Square root.
std::vector< double > & getBGzDist()
constexpr double c
The velocity of light in m/s.
void generateBinomial(size_t numberOfParticles)
double laserEnergy_m
Cathode material work function (eV).
void generateGaussZ(size_t numberOfParticles)
virtual double getFMHighE() const
int seed
The current random seed.
size_t getNumberOfEmissionSteps()
and give any other recipients of the Program a copy of this License along with the Program You may charge a fee for the physical act of transferring a copy
double convertMomentumEVoverCToBetaGamma(double p, double mass)
std::vector< double > pyWrite_m
size_t getNumParticles() const
void setDistToEmitted(bool emitted)
ParticleAttrib< ParticleOrigin > POrigin
The base class for all OPAL objects.
double tPulseLengthFWHM_m
double getGlobalPhaseShift()
units: (sec)
void applyEmissModelNone(double &pz)
boost::numeric::ublas::vector< double, std::vector< double > > vector_t
Dense vector type definition.
virtual bool raw_send(void *, int, int, int)
double getEnergyBinDeltaT()
void writeOutFileEmission()
void setPBins(PartBins *pbin)
ParticleAttrib< int > TriID
and that you know you can do these things To protect your we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights These restrictions translate to certain responsibilities for you if you distribute copies of the or if you modify it For if you distribute copies of such a whether gratis or for a you must give the recipients all the rights that you have You must make sure that receive or can get the source code And you must show them these terms so they know their rights We protect your rights with two distribute and or modify the software for each author s protection and we want to make certain that everyone understands that there is no warranty for this free software If the software is modified by someone else and passed we want its recipients to know that what they have is not the so that any problems introduced by others will not reflect on the original authors reputations any free program is threatened constantly by software patents We wish to avoid the danger that redistributors of a free program will individually obtain patent in effect making the program proprietary To prevent we have made it clear that any patent must be licensed for everyone s free use or not licensed at all The precise terms and conditions for distribution and modification follow GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR DISTRIBUTION AND MODIFICATION This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License The refers to any such program or and a work based on the Program means either the Program or any derivative work under copyright a work containing the Program or a portion of it
PETE_TBTree< FnCopysign, PETE_Scalar< Vektor< T1, Dim > >, typename T2::PETE_Expr_t > copysign(const Vektor< T1, Dim > &l, const PETE_Expr< T2 > &r)
std::string getString(const Attribute &attr)
Get string value.
constexpr double two_pi
The value of .
void reflectDistribution(size_t &numberOfParticles)
std::string rngtype
random number generator
void printDistMatchedGauss(Inform &os) const
void printEmissionModel(Inform &os) const
double tRise_m
time binned distribution with thermal energy
std::vector< double > & getYDist()
void setPRinit(double prinit)
PETE_TUTree< FnAbs, typename T::PETE_Expr_t > abs(const PETE_Expr< T > &l)
virtual void execute()
Execute the algorithm on the attached beam line.
void define(Object *newObject)
Define a new object.
ParticleAttrib< Vector_t > P
size_t emitParticles(PartBunchBase< double, 3 > *beam, double eZ)
constexpr double epsilon_0
The permittivity of vacuum in As/Vm.
ParticleAttrib< ParticleType > PType
std::vector< double > & getXDist()
static MPI_Comm getComm()
void generateAstraFlattopT(size_t numberOfParticles)
virtual std::string getFieldMapFN() const
DistributionType distrTypeT_m
Distribution type strings.
bool cZero
If true create symmetric distribution.
boost::numeric::ublas::matrix< double > matrix_t
Dense matrix type definition.
Vektor< double, 3 > Vector_t
bool cloTuneOnly
Do closed orbit and tune calculation only.
int getLastEmittedEnergyBin()
IpplTimings::TimerRef distrCreate_m
void setDistParametersBinomial(double massIneV)
void setGamma(double gamma)
ParticleAttrib< Vector_t > Ef
static BeamSequence * find(const std::string &name)
Find a BeamSequence by name.
void printEmissionModelNonEquil(Inform &os) const
RealDiracMatrix::matrix_t matrix_t
Type for storing maps.
std::vector< double > & getBGyDist()
int next_tag(int t, int s=1000)
std::vector< double > pzWrite_m
ParticleAttrib< double > M
void printDistFlattop(Inform &os) const
long long getLocalTrackStep() const
std::vector< double > pzDist_m
void adjustPhaseSpace(double massIneV)
void diagonalize(matrix_t &, sparse_matrix_t &, sparse_matrix_t &)
void generateFlattopT(size_t numberOfParticles)
LaserProfile * laserProfile_m
constexpr double SMALLESTCUTOFF
An abstract sequence of beam line components.
FmtFlags_t setf(FmtFlags_t setbits, FmtFlags_t field)
void createOpalT(PartBunchBase< double, 3 > *beam, std::vector< Distribution * > addedDistributions, size_t &numberOfParticles)
Tps< T > exp(const Tps< T > &x)
Exponential.
void generateTransverseGauss(size_t numberOfParticles)
constexpr double rad2mrad
void printEmissionModelAstra(Inform &os) const
void printEnergyBins(Inform &os) const
std::vector< double > getRealArray(const Attribute &attr)
Get array value.
void chooseInputMomentumUnits(InputMomentumUnits inputMoUnits)
void generateFlattopLaserProfile(size_t numberOfParticles)
double getQ() const
Access to reference data.
constexpr double pi
The value of .
Attribute makeRealArray(const std::string &name, const std::string &help)
Create real array attribute.
virtual Beamline * fetchLine() const =0
Return the embedded CLASSIC beam line.
size_t getNumberOfParticlesInFile(std::ifstream &inputFile)
Inform & endl(Inform &inf)
virtual void readStep(PartBunchBase< double, 3 > *, h5_ssize_t firstParticle, h5_ssize_t lastParticle)=0
std::vector< size_t > binWrite_m
PETE_TBTree< FnArcTan2, PETE_Scalar< Vektor< T1, Dim > >, typename T2::PETE_Expr_t > atan2(const Vektor< T1, Dim > &l, const PETE_Expr< T2 > &r)
T::PETE_Expr_t::PETE_Return_t min(const PETE_Expr< T > &expr, NDIndex< D > &loc)
double getEmissionDeltaT()
std::vector< double > & getBGxDist()
T::PETE_Expr_t::PETE_Return_t max(const PETE_Expr< T > &expr, NDIndex< D > &loc)
void setTEmission(double t)
void printDist(Inform &os, size_t numberOfParticles) const
InputMomentumUnits inputMoUnits_m
void createDistributionGauss(size_t numberOfParticles, double massIneV)
ParticleAttrib< Vector_t > Bf
void writeOutFileInjection()
clearpage the user may choose between constant or variable radius This model includes fringe fields L
void createMatchedGaussDistribution(size_t numberOfParticles, double massIneV, double charge)
double getEmissionTimeShift() const
bool getBool(const Attribute &attr)
Return logical value.
static Distribution * find(const std::string &name)
size_t totalNumberEmittedParticles_m
static void startTimer(TimerRef t)
std::string::iterator iterator
void createDistributionMultiGauss(size_t numberOfParticles, double massIneV)
void printDistMultiGauss(Inform &os) const
Attribute makeBool(const std::string &name, const std::string &help)
Make logical attribute.
std::vector< double > xWrite_m
void shiftDistCoordinates(double massIneV)
double getInitialGamma() const
std::vector< double > tOrZWrite_m
void registerOwnership(const AttributeHandler::OwnerType &itsClass) const
T::PETE_Expr_t::PETE_Return_t sum(const PETE_Expr< T > &expr)
size_t getTotalNum() const
void initializeBeam(PartBunchBase< double, 3 > *beam)
static Communicate * Comm
The base class for all OPAL exceptions.
std::string getAuxiliaryOutputDirectory() const
get the name of the the additional data directory
std::string laserImageName_m
void setupParticleBins(double massIneV, PartBunchBase< double, 3 > *beam)
void createDistributionBinomial(size_t numberOfParticles, double massIneV)
void scaleDistCoordinates()
void setEnergyBins(int numberOfEnergyBins)
ParticleType getPType() const
size_t getLocalNum() const
Attribute makePredefinedString(const std::string &name, const std::string &help, const std::initializer_list< std::string > &predefinedStrings)
Make predefined string attribute.
int getNumberOfEnergyBins()
T::PETE_Expr_t::PETE_Return_t prod(const PETE_Expr< T > &expr)
The base class for all OPAL beam lines and sequences.
std::vector< double > yDist_m
void generateLongFlattopT(size_t numberOfParticles)
void setDistParametersGauss(double massIneV)
IpplTimings::TimerRef distrReload_m
timer for IC, can not be in Distribution.h
std::vector< std::vector< double > > additionalRNs_m
Upper limit on emission energy distribution (eV).
std::string outFilename_m
void checkFileMomentum(double momentumTol)
void generateMatchedGauss(const SigmaGenerator::matrix_t &, size_t numberOfParticles, double massIneV)
void printDistBinomial(Inform &os) const
virtual int raw_receive(char *, int, int &, int &)
double currentEmissionTime_m
Attribute makeString(const std::string &name, const std::string &help)
Make string attribute.
void allreduce(const T *input, T *output, int count, Op op)
long long getGlobalTrackStep() const
void calcPartPerDist(size_t numberOfParticles)
boost::numeric::ublas::compressed_matrix< double, boost::numeric::ublas::row_major > sparse_matrix_t
Sparse matrix type definition.
unsigned int numberOfDistributions_m
List of Distribution types.
gsl_histogram * energyBinHist_m
Distribution energy bins.
std::vector< double > pxDist_m
ParticleAttrib< double > Q
virtual Distribution * clone(const std::string &name)
Return a clone.
void fill(std::vector< double > &p)
Add a particle to the temporary container.
constexpr double kB
Boltzman's constant in eV/K.
void doRestartOpalT(PartBunchBase< double, 3 > *p, size_t Np, int restartStep, H5PartWrapper *h5wrapper)
void injectBeam(PartBunchBase< double, 3 > *beam)
virtual int raw_probe_receive(char *&, int &, int &)
constexpr double q_e
The elementary charge in As.
void create(size_t &numberOfParticles, double massIneV, double charge)
size_t getNumOfLocalParticlesToCreate(size_t n)
void applyEmissModelAstra(double &px, double &py, double &pz, std::vector< double > &additionalRNs)
void setupEmissionModelAstra(PartBunchBase< double, 3 > *beam)
ParticleAttrib< double > dt
const std::string & getOpalName() const
Return object name.
void printDistGauss(Inform &os) const
virtual void readHeader()=0
void sampleUniformDisk(gsl_qrng *quasiRandGen2D, double &x1, double &x2)
void setDistParametersFlattop(double massIneV)
std::vector< Attribute > itsAttr
The object attributes.
double getChargePerParticle() const
get the macro particle charge
double getMassPerParticle() const
Tps< T > cos(const Tps< T > &x)
Cosine.
PETE_TUTree< FnArcCos, typename T::PETE_Expr_t > acos(const PETE_Expr< T > &l)
std::vector< double > yWrite_m
constexpr double alpha
The fine structure constant, no dimension.
constexpr double m_e
The electron rest mass in GeV.
Tps< T > log(const Tps< T > &x)
Natural logarithm.
size_t totalNumberParticles_m
std::string combineFilePath(std::initializer_list< std::string > ilist)
void generateFlattopZ(size_t numberOfParticles)
void setNumBunch(short n)
void setRinit(double rinit)
std::vector< double > xDist_m
size_t findEBin(double tOrZ)
std::vector< double > pyDist_m
double getReal(const Attribute &attr)
Return real value.
void checkParticleNumber(size_t &numberOfParticles)
void setupEmissionModelNonEquil()
void addProblemCharacteristicValue(const std::string &name, unsigned int value)
double laserIntensityCut_m
virtual double getCyclHarm() const
void getXY(double &x, double &y)
std::string getInputBasename()
get input file name without extension
void createOpalCycl(PartBunchBase< double, 3 > *beam, size_t numberOfParticles, double current, const Beamline &bl)
void setEmissionTime(double &maxT, double &minT)
The base class for all OPAL definitions.
void createDistributionFromFile(size_t numberOfParticles, double massIneV)
void createDistributionFlattop(size_t numberOfParticles, double massIneV)
Inform & level3(Inform &inf)
Object * find(const std::string &name)
Find entry.
virtual double getPHIinit() const
constexpr double e
The value of .
void iterateEmittedBin(int binNumber)
Inform & level2(Inform &inf)
PETE_TUTree< FnCeil, typename T::PETE_Expr_t > ceil(const PETE_Expr< T > &l)
void shiftBeam(double &maxTOrZ, double &minTOrZ)
Vector_t pmean_m
Total thermal momentum.
void setDistParametersMultiGauss(double massIneV)
ParticleAttrib< int > Bin
void doRestartOpalCycl(PartBunchBase< double, 3 > *p, size_t Np, int restartStep, const int specifiedNumBunch, H5PartWrapper *h5wrapper)
short getNumBunch() const
PETE_TUTree< FnArcSin, typename T::PETE_Expr_t > asin(const PETE_Expr< T > &l)
void setSigmaP_m(double massIneV)
void printDistFromFile(Inform &os) const
double emitEnergyUpperLimit_m
Cathode temperature (K).
void applyEmissionModel(double lowEnergyLimit, double &px, double &py, double &pz, std::vector< double > &additionalRNs)
Tps< T > pow(const Tps< T > &x, int y)
Integer power.
virtual void update()
Update this object.
Tps< T > sin(const Tps< T > &x)
Sine.
virtual void execute()
Execute the command.
static void stopTimer(TimerRef t)
gsl_qrng * selectRandomGenerator(std::string, unsigned int dimension)
Select and allocate gsl random number generator.
std::vector< size_t > particlesPerDist_m
void writeOutFileHeader()
EmissionModel emissionModel_m
Emission Model.
void printEmissionModelNone(Inform &os) const
void setupEmissionModelNone(PartBunchBase< double, 3 > *beam)
void checkEmissionParameters()
matrix_t correlationMatrix_m
Inform & level1(Inform &inf)
virtual bool predecessorIsSameFlavour() const =0
static const double percentTEmission_m
double pTotThermal_m
Random number generator.
std::vector< double > tOrZDist_m
std::vector< double > pxWrite_m
void setupEmissionModel(PartBunchBase< double, 3 > *beam)
double getBetaGamma(double Ekin, double mass)
std::vector< double > & getTOrZDist()
double cathodeTemp_m
Cathode material Fermi energy (eV).
std::vector< Distribution * > addedDistributions_m
Vector of distributions to be added to this distribution.
double getMomentumTolerance() const
bool reduce(Communicate &, InputIterator, InputIterator, OutputIterator, const ReduceOp &, bool *IncludeVal=0)
int getSteptoLastInj() const
virtual bool canReplaceBy(Object *object)
Distribution can only be replaced by another distribution.
virtual double get(double rand)
virtual double getFMLowE() const
Inform & printInfo(Inform &os) const
double tEmission_m
Emission parameters.