49 #include <gsl/gsl_histogram.h>
50 #include <gsl/gsl_linalg.h>
51 #include <gsl/gsl_randist.h>
52 #include <gsl/gsl_rng.h>
53 #include <gsl/gsl_sf_erf.h>
57 #include <boost/filesystem.hpp>
58 #include <boost/regex.hpp>
59 #include <boost/numeric/odeint/stepper/runge_kutta4.hpp>
74 for (
unsigned int i = 0; i < 6u; ++ i) {
84 "The DISTRIBUTION statement defines data for the 6D particle distribution."),
86 numberOfDistributions_m(1),
91 currentEmissionTime_m(0.0),
92 currentEnergyBin_m(1),
93 currentSampleBin_m(0),
94 numberOfEnergyBins_m(0),
95 numberOfSampleBins_m(0),
97 energyBinHist_m(NULL),
101 cathodeWorkFunc_m(0.0),
103 cathodeFermiEnergy_m(0.0),
105 emitEnergyUpperLimit_m(0.0),
106 totalNumberParticles_m(0),
107 totalNumberEmittedParticles_m(0),
112 tPulseLengthFWHM_m(0.0),
113 correlationMatrix_m(getUnit6x6()),
116 laserProfileFileName_m(
""),
117 laserImageName_m(
""),
118 laserIntensityCut_m(0.0),
119 laserProfile_m(NULL),
126 defaultDistribution->
builtin =
true;
131 delete defaultDistribution;
135 randGen_m = gsl_rng_alloc(gsl_rng_default);
145 distT_m(parent->distT_m),
147 numberOfDistributions_m(parent->numberOfDistributions_m),
148 emitting_m(parent->emitting_m),
149 particleRefData_m(parent->particleRefData_m),
150 addedDistributions_m(parent->addedDistributions_m),
151 particlesPerDist_m(parent->particlesPerDist_m),
152 emissionModel_m(parent->emissionModel_m),
153 tEmission_m(parent->tEmission_m),
154 tBin_m(parent->tBin_m),
155 currentEmissionTime_m(parent->currentEmissionTime_m),
156 currentEnergyBin_m(parent->currentEnergyBin_m),
157 currentSampleBin_m(parent->currentSampleBin_m),
158 numberOfEnergyBins_m(parent->numberOfEnergyBins_m),
159 numberOfSampleBins_m(parent->numberOfSampleBins_m),
161 energyBinHist_m(NULL),
163 pTotThermal_m(parent->pTotThermal_m),
164 pmean_m(parent->pmean_m),
165 cathodeWorkFunc_m(parent->cathodeWorkFunc_m),
166 laserEnergy_m(parent->laserEnergy_m),
167 cathodeFermiEnergy_m(parent->cathodeFermiEnergy_m),
168 cathodeTemp_m(parent->cathodeTemp_m),
169 emitEnergyUpperLimit_m(parent->emitEnergyUpperLimit_m),
170 totalNumberParticles_m(parent->totalNumberParticles_m),
171 totalNumberEmittedParticles_m(parent->totalNumberEmittedParticles_m),
172 xDist_m(parent->xDist_m),
173 pxDist_m(parent->pxDist_m),
174 yDist_m(parent->yDist_m),
175 pyDist_m(parent->pyDist_m),
176 tOrZDist_m(parent->tOrZDist_m),
177 pzDist_m(parent->pzDist_m),
178 xWrite_m(parent->xWrite_m),
179 pxWrite_m(parent->pxWrite_m),
180 yWrite_m(parent->yWrite_m),
181 pyWrite_m(parent->pyWrite_m),
182 tOrZWrite_m(parent->tOrZWrite_m),
183 pzWrite_m(parent->pzWrite_m),
184 avrgpz_m(parent->avrgpz_m),
185 inputMoUnits_m(parent->inputMoUnits_m),
186 sigmaTRise_m(parent->sigmaTRise_m),
187 sigmaTFall_m(parent->sigmaTFall_m),
188 tPulseLengthFWHM_m(parent->tPulseLengthFWHM_m),
189 sigmaR_m(parent->sigmaR_m),
190 sigmaP_m(parent->sigmaP_m),
191 cutoffR_m(parent->cutoffR_m),
192 cutoffP_m(parent->cutoffP_m),
193 correlationMatrix_m(parent->correlationMatrix_m),
194 sepPeaks_m(parent->sepPeaks_m),
195 nPeaks_m(parent->nPeaks_m),
196 laserProfileFileName_m(parent->laserProfileFileName_m),
197 laserImageName_m(parent->laserImageName_m),
198 laserIntensityCut_m(parent->laserIntensityCut_m),
199 laserProfile_m(NULL),
202 tRise_m(parent->tRise_m),
203 tFall_m(parent->tFall_m),
204 sigmaRise_m(parent->sigmaRise_m),
205 sigmaFall_m(parent->sigmaFall_m),
206 cutoff_m(parent->cutoff_m)
209 randGen_m = gsl_rng_alloc(gsl_rng_default);
236 if (myNode < remainder)
265 size_t numberOfLocalParticles = numberOfParticles;
267 numberOfLocalParticles = (numberOfParticles + 1) / 2;
275 mySeed = tv.tv_sec + tv.tv_usec;
280 *
gmsg <<
level2 <<
"* Generation of distribution with seed = " << mySeed <<
" + core_id\n"
281 <<
"* is scalable with number of particles and cores." <<
endl;
284 *
gmsg <<
level2 <<
"* Generation of distribution with seed = " << mySeed <<
"\n"
285 <<
"* isn't scalable with number of particles and cores." <<
endl;
319 unsigned int numAdditionalRNsPerParticle = 0;
324 numAdditionalRNsPerParticle = 2;
327 numAdditionalRNsPerParticle = 40;
329 numAdditionalRNsPerParticle = 20;
333 int saveProcessor = -1;
338 for (
size_t partIndex = 0; partIndex < numberOfLocalParticles; ++ partIndex) {
342 if (saveProcessor >= numNodes)
345 if (scalable || myNode == saveProcessor) {
346 std::vector<double> rns;
347 for (
unsigned int i = 0; i < numAdditionalRNsPerParticle; ++ i) {
353 for (
unsigned int i = 0; i < numAdditionalRNsPerParticle; ++ i) {
385 size_t firstParticle = numParticlesPerNode *
Ippl::myNode();
386 size_t lastParticle = firstParticle + numParticlesPerNode - 1;
388 lastParticle = numParticles - 1;
391 numParticles = lastParticle - firstParticle + 1;
394 beam->
create(numParticles);
397 dataSource->
readStep(beam, firstParticle, lastParticle);
401 double actualT = beam->
getT();
407 *
gmsg <<
"Total number of particles in the h5 file= " << beam->
getTotalNum() <<
"\n"
408 <<
"Global step= " << gtstep <<
"; Local step= " << ltstep <<
"; "
409 <<
"restart step= " << restartStep <<
"\n"
416 const int specifiedNumBunch,
421 INFOMSG(
"---------------- Start reading hdf5 file----------------" <<
endl);
426 size_t firstParticle = numParticlesPerNode *
Ippl::myNode();
427 size_t lastParticle = firstParticle + numParticlesPerNode - 1;
429 lastParticle = numParticles - 1;
432 numParticles = lastParticle - firstParticle + 1;
435 beam->
create(numParticles);
438 dataSource->
readStep(beam, firstParticle, lastParticle);
448 INFOMSG(
"total number of particles = " << globalN <<
endl);
449 INFOMSG(
"* Restart Energy = " << meanE <<
" (MeV), Path lenght = " << beam->
get_sPos() <<
" (m)" <<
endl);
453 double gamma = 1 + meanE / beam->
getM() * 1.0e6;
456 INFOMSG(
"* Gamma = " << gamma <<
", Beta = " << beta <<
endl);
459 INFOMSG(
"Restart from hdf5 file generated by OPAL-cycl" <<
endl);
460 if (specifiedNumBunch > 1) {
467 INFOMSG(
"Restart from hdf5 file generated by OPAL-t" <<
endl);
472 for (
unsigned int i = 0; i < newLocalN; ++i) {
473 for (
int d = 0; d < 3; ++d) {
474 meanR(d) += beam->
R[i](d);
475 meanP(d) += beam->
P[i](d);
482 INFOMSG(
"Rmean = " << meanR <<
"[m], Pmean=" << meanP <<
endl);
484 for (
unsigned int i = 0; i < newLocalN; ++i) {
490 INFOMSG(
"---------------Finished reading hdf5 file---------------" <<
endl);
498 throw OpalException(
"Distribution::find()",
"Distribution \"" +
name +
"\" not found.");
523 double inv_erf08 = 0.906193802436823;
525 double t =
a - sqr2 * sig * inv_erf08;
528 for (
int i = 0; i < 10; ++ i) {
529 sig = (t +
tRise_m -
a) / (sqr2 * inv_erf08);
530 t =
a - 0.5 * sqr2 * (sig + tmps) * inv_erf08;
531 sig = (0.5 * (t + tmpt) +
tRise_m -
a) / (sqr2 * inv_erf08);
551 <<
"* ************* D I S T R I B U T I O N ********************************************" <<
endl;
554 os <<
"* In restart. Distribution read in from .h5 file." <<
endl;
557 os <<
"* Main Distribution" <<
endl
558 <<
"-----------------" <<
endl;
565 size_t distCount = 1;
568 os <<
"* Added Distribution #" << distCount <<
endl;
569 os <<
"* ----------------------" <<
endl;
583 os <<
"* Distribution is emitted. " <<
endl;
590 os <<
"* Distribution is injected." <<
endl;
594 os <<
"* **********************************************************************************" <<
endl;
611 for (
double dist : (*addedDistIt)->getXDist()) {
614 (*addedDistIt)->eraseXDist();
616 for (
double dist : (*addedDistIt)->getBGxDist()) {
619 (*addedDistIt)->eraseBGxDist();
621 for (
double dist : (*addedDistIt)->getYDist()) {
624 (*addedDistIt)->eraseYDist();
626 for (
double dist : (*addedDistIt)->getBGyDist()) {
629 (*addedDistIt)->eraseBGyDist();
631 for (
double dist : (*addedDistIt)->getTOrZDist()) {
634 (*addedDistIt)->eraseTOrZDist();
636 for (
double dist : (*addedDistIt)->getBGzDist()) {
639 (*addedDistIt)->eraseBGzDist();
680 std::vector<double> &additionalRNs) {
688 unsigned int counter = 0;
691 double randFuncValue = additionalRNs[counter++];
693 double funcValue = ((1.0
694 - 1.0 / (1.0 + expRelativeEnergy * expRelativeLaserEnergy)) /
695 (1.0 + expRelativeEnergy));
697 if (randFuncValue <= funcValue)
700 if (counter == additionalRNs.size()) {
701 for (
unsigned int i = 0; i < counter; ++ i) {
702 additionalRNs[i] = gsl_rng_uniform(
randGen_m);
709 while (additionalRNs.size() - counter < 2) {
711 additionalRNs[counter] = gsl_rng_uniform(
randGen_m);
716 double energyExternal = energy - lowEnergyLimit;
719 double thetaIn = additionalRNs[counter++] * thetaInMax;
720 double sinThetaOut =
std::sin(thetaIn) *
std::sqrt(energyInternal / energyExternal);
724 double betaGammaExternal
727 bgx = betaGammaExternal * sinThetaOut *
std::cos(phi);
728 bgy = betaGammaExternal * sinThetaOut *
std::sin(phi);
740 std::map<unsigned int, size_t> nPartFromFiles;
741 double totalWeight = 0.0;
748 std::ifstream inputFile;
751 inputFile.open(fileName.c_str());
754 nPartFromFiles.insert(std::make_pair(i, nPart));
755 if (nPart > numberOfParticles) {
757 "Number of particles is too small");
760 numberOfParticles -= nPart;
766 size_t numberOfCommittedPart = 0;
775 size_t particlesCurrentDist = numberOfParticles * currDist->
getWeight() / totalWeight;
777 numberOfCommittedPart += particlesCurrentDist;
782 if (numberOfParticles != numberOfCommittedPart) {
783 size_t diffNumber = numberOfParticles - numberOfCommittedPart;
795 if (diffNumber != 0) {
797 "Particles can't be distributed to distributions in array");
813 if (emissionSteps == 0)
844 size_t numberOfDistParticles =
tOrZDist_m.size();
847 if (numberOfDistParticles == 0) {
849 "Zero particles in the distribution! "
850 "The number of particles needs to be specified.");
853 if (numberOfDistParticles != numberOfParticles) {
855 "The number of particles in the initial\n"
857 std::to_string(numberOfDistParticles) +
"\n"
858 "is different from the number of particles\n"
859 "defined by the BEAM command " +
860 std::to_string(numberOfParticles) +
".\n"
861 "This often happens when using a FROMFILE type\n"
862 "distribution and not matching the number of\n"
863 "particles in the input distribution file(s) with\n"
864 "the number given in the BEAM command.");
874 if (inputUnits ==
"NONE")
876 else if (inputUnits ==
"EVOVERC")
878 else if (inputUnits ==
"") {
879 *
gmsg <<
"No momentum units were specified, using default units (see manual)." <<
endl;
910 int saveProcessor = -1;
917 for (
size_t partIndex = 0; partIndex < numberOfParticles; partIndex++) {
918 double x = 0.0, y = 0.0, tOrZ = 0.0;
919 double px = 0.0, py = 0.0, pz = 0.0;
929 double randNums[2] = {0.0, 0.0};
931 if (quasiRandGen2D != NULL) {
932 gsl_qrng_get(quasiRandGen2D, randNums);
934 randNums[0] = gsl_rng_uniform(
randGen_m);
935 randNums[1] = gsl_rng_uniform(
randGen_m);
941 for (
unsigned i = 0; i <
nPeaks_m; i++)
943 allow = (r <= proba);
964 if (saveProcessor >= numNodes)
967 if (scalable || myNode == saveProcessor) {
977 gsl_qrng_free(quasiRandGen2D);
982 size_t numberOfParticlesRead = 0;
984 const boost::regex commentExpr(
"[[:space:]]*#.*");
985 const std::string repl(
"");
987 std::stringstream linestream;
991 std::getline(inputFile, line);
992 line = boost::regex_replace(line, commentExpr, repl);
993 }
while (line.length() == 0 && !inputFile.fail());
995 linestream.str(line);
996 linestream >> tempInt;
998 throw OpalException(
"Distribution::getNumberOfParticlesInFile",
1001 "' does not seem to be an ASCII file containing a distribution.");
1003 numberOfParticlesRead =
static_cast<size_t>(tempInt);
1007 return numberOfParticlesRead;
1012 std::ifstream inputFile;
1014 if (!boost::filesystem::exists(fileName)) {
1016 "Distribution::createDistributionFromFile",
1017 "Open file operation failed, please check if \"" + fileName +
"\" really exists.");
1020 inputFile.open(fileName.c_str());
1028 unsigned int saveProcessor = 0;
1032 unsigned int distributeFrequency = 1000;
1033 size_t singleDataSize = 6;
1034 unsigned int dataSize = distributeFrequency * singleDataSize;
1035 std::vector<double> data(dataSize);
1038 constexpr
unsigned int bufferSize = 1024;
1039 char lineBuffer[bufferSize];
1040 unsigned int numParts = 0;
1042 while (!inputFile.eof()) {
1043 inputFile.getline(lineBuffer, bufferSize);
1047 std::istringstream line(lineBuffer);
1068 if (saveProcessor > 0u) {
1069 currentPosition = std::copy(&(
R[0]), &(
R[0]) + 3, currentPosition);
1070 currentPosition = std::copy(&(P[0]), &(P[0]) + 3, currentPosition);
1072 if (currentPosition == data.end()) {
1074 MPI_Bcast(&(data[0]), dataSize, MPI_DOUBLE, 0,
Ippl::getComm());
1076 currentPosition = data.begin();
1092 (numberOfParticlesRead == numParts ? currentPosition - data.begin()
1096 if (numberOfParticlesRead != numParts) {
1098 "Distribution::createDistributionFromFile",
1099 "Found " + std::to_string(numParts) +
" particles in file '" + fileName
1100 +
"' instead of " + std::to_string(numberOfParticlesRead));
1102 MPI_Bcast(&(data[0]), dataSize, MPI_DOUBLE, 0,
Ippl::getComm());
1109 "Distribution::createDistributionFromFile",
1110 "Couldn't find " + std::to_string(numberOfParticlesRead)
1111 +
" particles in file '" + fileName +
"'");
1113 MPI_Bcast(&(data[0]), dataSize, MPI_DOUBLE, 0,
Ippl::getComm());
1116 while (i < dataSize) {
1118 const double* tmp = &(data[i]);
1126 i += singleDataSize;
1133 }
while (dataSize == distributeFrequency * singleDataSize);
1136 pmean_m /= numberOfParticlesRead;
1154 if (LineName ==
"")
return;
1158 if (LineSequence == NULL)
1159 throw OpalException(
"Distribution::CreateMatchedGaussDistribution",
1160 "didn't find any Cyclotron element in line");
1164 size_t NumberOfCyclotrons = CyclotronVisitor.
size();
1166 if (NumberOfCyclotrons > 1) {
1167 throw OpalException(
"Distribution::createMatchedGaussDistribution",
1168 "I am confused, found more than one Cyclotron element in line");
1170 if (NumberOfCyclotrons == 0) {
1171 throw OpalException(
"Distribution::createMatchedGaussDistribution",
1172 "didn't find any Cyclotron element in line");
1185 throw OpalException(
"Distribution::createMatchedGaussDistribution()",
1186 "Negative number of integration steps");
1189 throw OpalException(
"Distribution::createMatchedGaussDistribution()",
1190 "Negative number of sectors");
1192 if ( Nsectors > 1 && full ==
false )
1193 throw OpalException(
"Distribution::createMatchedGaussDistribution()",
1194 "Averaging over sectors can only be done with SECTOR=FALSE");
1196 *
gmsg <<
"* ----------------------------------------------------" <<
endl;
1197 *
gmsg <<
"* About to find closed orbit and matched distribution " <<
endl;
1198 *
gmsg <<
"* I= " <<
I_m*1E3 <<
" (mA) E= " <<
E_m*1E-6 <<
" (MeV)" <<
endl;
1203 *
gmsg <<
"* SECTOR: " <<
"match using all sectors, with" <<
endl
1204 <<
"* NSECTORS = " << Nsectors <<
" to average the field over" <<
endl;
1207 *
gmsg <<
"* SECTOR: " <<
"match using single sector" <<
endl;
1209 *
gmsg <<
"* NSTEPS = " << Nint <<
endl
1213 <<
"* ----------------------------------------------------" <<
endl;
1215 if ( CyclotronElement->
getFMLowE() < 0 ||
1218 throw OpalException(
"Distribution::createMatchedGaussDistribution()",
1219 "Missing attributes 'FMLOWE' and/or 'FMHIGHE' in "
1220 "'CYCLOTRON' definition.");
1223 std::size_t maxitCOF =
1229 double denergy = 1000.0 *
1232 if ( denergy < 0.0 )
1233 throw OpalException(
"Distribution:createMatchedGaussDistribution()",
1240 *
gmsg <<
"* Stopping after closed orbit and tune calculation" <<
endl;
1241 typedef std::vector<double> container_t;
1242 typedef boost::numeric::odeint::runge_kutta4<container_t> rk4_t;
1245 cof_t cof(massIneV*1E-6, charge, Nint, CyclotronElement, full, Nsectors);
1246 cof.findOrbit(accuracy, maxitCOF,
E_m*1E-6, denergy, rguess,
true);
1249 "Do only tune calculation.");
1252 bool writeMap =
true;
1254 std::unique_ptr<SigmaGenerator> siggen = std::unique_ptr<SigmaGenerator>(
1268 if (siggen->match(accuracy,
1276 std::array<double,3> Emit = siggen->getEmittances();
1279 *
gmsg <<
"* RGUESS " << rguess <<
" (m) " <<
endl;
1281 *
gmsg <<
"* Converged (Ex, Ey, Ez) = (" << Emit[0] <<
", " << Emit[1] <<
", "
1282 << Emit[2] <<
") pi mm mrad for E= " <<
E_m*1E-6 <<
" (MeV)" <<
endl;
1283 *
gmsg <<
"* Sigma-Matrix " <<
endl;
1285 for (
unsigned int i = 0; i < siggen->getSigma().size1(); ++ i) {
1286 *
gmsg << std::setprecision(4) << std::setw(11) << siggen->getSigma()(i,0);
1287 for (
unsigned int j = 1; j < siggen->getSigma().size2(); ++ j) {
1288 if (
std::abs(siggen->getSigma()(i,j)) < 1.0e-15) {
1289 *
gmsg <<
" & " << std::setprecision(4) << std::setw(11) << 0.0;
1292 *
gmsg <<
" & " << std::setprecision(4) << std::setw(11) << siggen->getSigma()(i,j);
1302 CyclotronElement->
setRinit(siggen->getInjectionRadius() * 1.0e3);
1303 CyclotronElement->
setPRinit(siggen->getInjectionMomentum());
1306 *
gmsg <<
"* Not converged for " <<
E_m*1E-6 <<
" MeV" <<
endl;
1308 throw OpalException(
"Distribution::CreateMatchedGaussDistribution",
1309 "didn't find any matched distribution.");
1326 size_t numberOfParticles,
1327 double current,
const Beamline &) {
1341 size_t numberOfPartToCreate = numberOfParticles;
1394 std::vector<Distribution *> addedDistributions,
1395 size_t &numberOfParticles) {
1402 size_t &numberOfParticles) {
1425 addedDist->setDistType();
1451 size_t distCount = 1;
1505 std::vector<std::vector<double> > mirrored;
1513 std::vector<double> tmp;
1514 tmp.push_back((*it).front());
1515 tmp.push_back((*it).back() + 0.5);
1516 mirrored.push_back(tmp);
1521 std::vector<double> tmp((*it).begin() + numAdditionals, (*it).end());
1522 mirrored.push_back(tmp);
1523 (*it).erase((*it).begin() + numAdditionals, (*it).end());
1568 size_t numberOfEmittedParticles = beam->
getLocalNum();
1569 size_t oldNumberOfEmittedParticles = numberOfEmittedParticles;
1578 std::vector<size_t> particlesToBeErased;
1584 for (
size_t particleIndex = 0; particleIndex <
tOrZDist_m.size(); particleIndex++) {
1592 particlesToBeErased.push_back(particleIndex);
1595 double deltaT =
tOrZDist_m.at(particleIndex);
1596 beam->
dt[numberOfEmittedParticles] = deltaT;
1598 double oneOverCDt = 1.0 / (
Physics::c * deltaT);
1600 double px =
pxDist_m.at(particleIndex);
1601 double py =
pyDist_m.at(particleIndex);
1602 double pz =
pzDist_m.at(particleIndex);
1603 std::vector<double> additionalRNs;
1608 "not enough additional particles");
1612 double particleGamma
1618 beam->
R[numberOfEmittedParticles]
1620 + px * deltaT *
Physics::c / (2.0 * particleGamma)),
1621 oneOverCDt * (
yDist_m.at(particleIndex)
1622 + py * deltaT *
Physics::c / (2.0 * particleGamma)),
1623 pz / (2.0 * particleGamma));
1624 beam->
P[numberOfEmittedParticles]
1629 beam->
Ef[numberOfEmittedParticles] =
Vector_t(0.0);
1630 beam->
Bf[numberOfEmittedParticles] =
Vector_t(0.0);
1633 beam->
TriID[numberOfEmittedParticles] = 0;
1634 numberOfEmittedParticles++;
1650 std::vector<size_t>::reverse_iterator ptbErasedIt;
1651 for (ptbErasedIt = particlesToBeErased.rbegin();
1652 ptbErasedIt < particlesToBeErased.rend();
1692 <<
" has emitted all particles (new emit)." <<
endl);
1720 size_t currentEmittedParticles = numberOfEmittedParticles - oldNumberOfEmittedParticles;
1724 return currentEmittedParticles;
1755 double randNums[2] = {0.0, 0.0};
1757 if (quasiRandGen2D != NULL)
1758 gsl_qrng_get(quasiRandGen2D, randNums);
1760 randNums[0] = gsl_rng_uniform(
randGen_m);
1761 randNums[1] = gsl_rng_uniform(
randGen_m);
1764 x1 = 2 * randNums[0] - 1;
1765 x2 = 2 * randNums[1] - 1;
1776 const size_t numberOfParticles =
tOrZDist_m.size();
1777 for (
size_t partIndex = 0; partIndex < numberOfParticles; partIndex++) {
1791 for (
size_t particleIndex = 0; particleIndex <
tOrZDist_m.size(); particleIndex++) {
1793 std::vector<double> partCoord;
1795 partCoord.push_back(
xDist_m.at(particleIndex));
1796 partCoord.push_back(
yDist_m.at(particleIndex));
1797 partCoord.push_back(
tOrZDist_m.at(particleIndex));
1798 partCoord.push_back(
pxDist_m.at(particleIndex));
1799 partCoord.push_back(
pyDist_m.at(particleIndex));
1800 partCoord.push_back(
pzDist_m.at(particleIndex));
1801 partCoord.push_back(0.0);
1831 gsl_qrng *quasiRandGen = gsl_qrng_alloc(gsl_qrng_halton, 2);
1833 int numberOfSampleBins
1835 int numberOfEnergyBins
1838 int binTotal = numberOfSampleBins * numberOfEnergyBins;
1840 double *distributionTable =
new double[binTotal + 1];
1844 double inv_erf08 = 0.906193802436823;
1846 double t =
a - sqr2 * sig * inv_erf08;
1850 for (
int i = 0; i < 10; ++ i) {
1851 sig = (t +
tRise_m -
a) / (sqr2 * inv_erf08);
1852 t =
a - 0.5 * sqr2 * (sig + tmps) * inv_erf08;
1853 sig = (0.5 * (t + tmpt) +
tRise_m -
a) / (sqr2 * inv_erf08);
1865 double lo = -
tBin_m / 2.0 * numberOfEnergyBins;
1866 double hi =
tBin_m / 2.0 * numberOfEnergyBins;
1867 double dx =
tBin_m / numberOfSampleBins;
1870 double weight = 2.0;
1873 for (
int i = 0; i < binTotal + 1; ++ i, x += dx, weight = 6. - weight) {
1874 distributionTable[i] = gsl_sf_erf((x +
a) / (sqr2 * sig)) - gsl_sf_erf((x -
a) / (sqr2 * sig));
1875 tot += distributionTable[i] * weight;
1877 tot -= distributionTable[binTotal] * (5. - weight);
1878 tot -= distributionTable[0];
1880 int saveProcessor = -1;
1884 double tCoord = 0.0;
1886 int effectiveNumParticles = 0;
1888 std::vector<int> numParticlesInBin(numberOfEnergyBins,0);
1889 for (
int k = 0; k < numberOfEnergyBins; ++ k) {
1890 double loc_fraction = -distributionTable[numberOfSampleBins * k] / tot;
1893 for (
int i = numberOfSampleBins * k; i < numberOfSampleBins * (k + 1) + 1;
1894 ++ i, weight = 6. - weight) {
1895 loc_fraction += distributionTable[i] * weight / tot;
1897 loc_fraction -= distributionTable[numberOfSampleBins * (k + 1)]
1898 * (5. - weight) / tot;
1899 numParticlesInBin[k] =
static_cast<int>(std::round(loc_fraction * numberOfParticles));
1900 effectiveNumParticles += numParticlesInBin[k];
1901 if (numParticlesInBin[k] > numParticlesInBin[largestBin]) largestBin = k;
1904 numParticlesInBin[largestBin] += (numberOfParticles - effectiveNumParticles);
1906 for (
int k = 0; k < numberOfEnergyBins; ++ k) {
1907 gsl_ran_discrete_t *table
1908 = gsl_ran_discrete_preproc(numberOfSampleBins,
1909 &(distributionTable[numberOfSampleBins * k]));
1911 for (
int i = 0; i < numParticlesInBin[k]; i++) {
1913 gsl_qrng_get(quasiRandGen, xx);
1914 tCoord = hi * (xx[1] +
static_cast<int>(gsl_ran_discrete(
randGen_m, table))
1915 - binTotal / 2 + k * numberOfSampleBins) / (binTotal / 2);
1918 if (saveProcessor >= numNodes)
1921 if (scalable || myNode == saveProcessor) {
1926 gsl_ran_discrete_free(table);
1929 gsl_qrng_free(quasiRandGen);
1930 delete [] distributionTable;
1958 for (
unsigned int index = 0; index < 3; index++) {
1962 if (
std::abs(emittance(index)) > std::numeric_limits<double>::epsilon()) {
1970 *
std::sqrt(beta(index) * gamma(index));
1977 for (
unsigned int index = 0; index < 3; index++) {
1981 SINCHI[index] = -
alpha(index) * COSCHI[index];
1982 CHI[index] =
std::atan2(SINCHI[index], COSCHI[index]);
1984 M[index] =
std::sqrt(emittance(index) * beta(index));
1985 PM[index] =
std::sqrt(emittance(index) * gamma(index));
1990 X[index] = L[index];
1991 PX[index] = PL[index];
1994 X[index] = M[index];
1995 PX[index] =
PM[index];
2000 int saveProcessor = -1;
2021 for (
size_t partIndex = 0; partIndex < numberOfParticles; partIndex++) {
2025 double Ux = 0.0, U = 0.0;
2026 double Vx = 0.0, V = 0.0;
2028 A = splitter[0]->get(gsl_rng_uniform(
randGen_m));
2033 p[0] = PX[0] * (Ux * SINCHI[0] + Vx * COSCHI[0]);
2035 A = splitter[1]->get(gsl_rng_uniform(
randGen_m));
2040 p[1] = PX[1] * (U * SINCHI[1] + V * COSCHI[1]);
2042 A = splitter[2]->get(gsl_rng_uniform(
randGen_m));
2051 if (saveProcessor >= numNodes)
2054 if (scalable || myNode == saveProcessor) {
2064 for (
unsigned int index = 0; index < 3; index++) {
2065 delete splitter[index];
2071 int saveProcessor = -1;
2076 for (
size_t partIndex = 0; partIndex < numberOfParticles; partIndex++) {
2087 if (saveProcessor >= numNodes)
2090 if (scalable || myNode == saveProcessor) {
2109 int saveProcessor = -1;
2113 for (
size_t partIndex = 0; partIndex < numberOfParticles; partIndex++) {
2126 if (saveProcessor >= numNodes)
2129 if (scalable || myNode == saveProcessor) {
2138 gsl_qrng_free(quasiRandGen2D);
2152 int saveProcessor = -1;
2157 for (
size_t partIndex = 0; partIndex < numberOfParticles; partIndex++) {
2170 if (quasiRandGen1D != NULL)
2171 gsl_qrng_get(quasiRandGen1D, &z);
2179 if (saveProcessor >= numNodes)
2182 if (scalable || myNode == saveProcessor) {
2192 gsl_qrng_free(quasiRandGen1D);
2193 gsl_qrng_free(quasiRandGen2D);
2198 gsl_matrix * corMat = gsl_matrix_alloc (6, 6);
2199 gsl_vector * rx = gsl_vector_alloc(6);
2200 gsl_vector * ry = gsl_vector_alloc(6);
2202 for (
unsigned int i = 0; i < 6; ++ i) {
2204 for (
unsigned int j = 0; j < i; ++ j) {
2212 *
gmsg <<
"* m before gsl_linalg_cholesky_decomp" <<
endl;
2213 for (
int i = 0; i < 6; i++) {
2214 for (
int j = 0; j < 6; j++) {
2216 *
gmsg <<
"* r(" << std::setprecision(1) << i <<
", : ) = "
2217 << std::setprecision(4) << std::setw(10) << gsl_matrix_get (corMat, i, j);
2219 *
gmsg <<
" & " << std::setprecision(4) << std::setw(10) << gsl_matrix_get (corMat, i, j);
2228 int errcode = gsl_linalg_cholesky_decomp(corMat);
2257 if (errcode == GSL_EDOM) {
2259 "gsl_linalg_cholesky_decomp failed");
2262 for (
int i = 0; i < 5; ++ i) {
2263 for (
int j = i+1; j < 6 ; ++ j) {
2264 gsl_matrix_set (corMat, i, j, 0.0);
2269 *
gmsg <<
"* m after gsl_linalg_cholesky_decomp" <<
endl;
2270 for (
int i = 0; i < 6; i++) {
2271 for (
int j = 0; j < 6; j++) {
2273 *
gmsg <<
"* r(" << std::setprecision(1) << i <<
", : ) = "
2274 << std::setprecision(4) << std::setw(10) << gsl_matrix_get (corMat, i, j);
2276 *
gmsg <<
" & " << std::setprecision(4) << std::setw(10) << gsl_matrix_get (corMat, i, j);
2282 int saveProcessor = -1;
2287 for (
size_t partIndex = 0; partIndex < numberOfParticles; partIndex++) {
2298 gsl_vector_set(rx, 0, gsl_ran_gaussian(
randGen_m, 1.0));
2299 gsl_vector_set(rx, 1, gsl_ran_gaussian(
randGen_m, 1.0));
2300 gsl_vector_set(rx, 2, gsl_ran_gaussian(
randGen_m, 1.0));
2301 gsl_vector_set(rx, 3, gsl_ran_gaussian(
randGen_m, 1.0));
2302 gsl_vector_set(rx, 4, gsl_ran_gaussian(
randGen_m, 1.0));
2303 gsl_vector_set(rx, 5, gsl_ran_gaussian(
randGen_m, 1.0));
2305 gsl_blas_dgemv(CblasNoTrans, 1.0, corMat, rx, 0.0, ry);
2307 x = gsl_vector_get(ry, 0);
2308 px = gsl_vector_get(ry, 1);
2309 y = gsl_vector_get(ry, 2);
2310 py = gsl_vector_get(ry, 3);
2311 z = gsl_vector_get(ry, 4);
2312 pz = gsl_vector_get(ry, 5);
2320 allow = (xAndYOk && pxAndPyOk && zOk && pzOk);
2332 if (saveProcessor >= numNodes)
2335 if (scalable || myNode == saveProcessor) {
2347 gsl_vector_free(rx);
2348 gsl_vector_free(ry);
2349 gsl_matrix_free(corMat);
2353 size_t numberOfParticles,
double massIneV)
2366 for (
unsigned int i = 0; i < 3; ++ i) {
2367 if ( sigma(2 * i, 2 * i) < 0 || sigma(2 * i + 1, 2 * i + 1) < 0 )
2369 "Negative value on the diagonal of the sigma matrix.");
2406 A(0, 0) = sigma(0, 0);
2407 A(1, 1) = sigma(1, 1);
2408 A(2, 2) = sigma(4, 4);
2409 A(3, 3) = sigma(5, 5);
2411 A(0, 1) = sigma(0, 1);
2412 A(0, 2) = sigma(0, 4);
2413 A(0, 3) = sigma(0, 5);
2414 A(1, 0) = sigma(1, 0);
2415 A(2, 0) = sigma(4, 0);
2416 A(3, 0) = sigma(5, 0);
2418 A(1, 2) = sigma(1, 4);
2419 A(2, 1) = sigma(4, 1);
2420 A(1, 3) = sigma(1, 5);
2421 A(3, 1) = sigma(5, 1);
2422 A(2, 3) = sigma(4, 5);
2423 A(3, 2) = sigma(5, 4);
2430 for (
int i = 0; i < 4; ++i) {
2440 A(2, 2) = sigma(2, 2);
2441 A(3, 3) = sigma(3, 3);
2442 A(2, 3) = sigma(2, 3);
2443 A(3, 2) = sigma(3, 2);
2447 for (
int i = 0; i < 4; ++i) {
2451 int saveProcessor = -1;
2457 for (
size_t i = 0; i < numberOfParticles; i++) {
2458 for (
int j = 0; j < 4; j++) {
2459 p1(j) = gsl_ran_gaussian(
randGen_m, 1.0) * variances(j);
2460 p2(j) = gsl_ran_gaussian(
randGen_m, 1.0) * variances(4 + j);
2468 if (saveProcessor >= numNodes)
2471 if (scalable || myNode == saveProcessor) {
2487 if (flattopTime < 0.0)
2491 double distArea = flattopTime
2495 size_t numRise = numberOfParticles *
sigmaTRise_m * normalizedFlankArea / distArea;
2496 size_t numFall = numberOfParticles *
sigmaTFall_m * normalizedFlankArea / distArea;
2497 size_t numFlat = numberOfParticles - numRise - numFall;
2500 int saveProcessor = -1;
2505 for (
size_t partIndex = 0; partIndex < numFall; partIndex++) {
2521 if (saveProcessor >= numNodes)
2524 if (scalable || myNode == saveProcessor) {
2535 if (modulationAmp > 1.0)
2536 modulationAmp = 1.0;
2537 double numModulationPeriods
2539 double modulationPeriod = 0.0;
2540 if (numModulationPeriods != 0.0)
2541 modulationPeriod = flattopTime / numModulationPeriods;
2546 for (
size_t partIndex = 0; partIndex < numFlat; partIndex++) {
2551 if (modulationAmp == 0.0 || numModulationPeriods == 0.0) {
2553 if (quasiRandGen1D != NULL)
2554 gsl_qrng_get(quasiRandGen1D, &t);
2558 t = flattopTime * t;
2563 double randNums[2] = {0.0, 0.0};
2565 if (quasiRandGen2D != NULL) {
2566 gsl_qrng_get(quasiRandGen2D, randNums);
2568 randNums[0]= gsl_rng_uniform(
randGen_m);
2569 randNums[1]= gsl_rng_uniform(
randGen_m);
2571 t = randNums[0] * flattopTime;
2573 double funcValue = (1.0 + modulationAmp
2577 allow = (randNums[1] <= funcValue);
2585 if (saveProcessor >= numNodes)
2588 if (scalable || myNode == saveProcessor) {
2595 for (
size_t partIndex = 0; partIndex < numRise; partIndex++) {
2611 if (saveProcessor >= numNodes)
2614 if (scalable || myNode == saveProcessor) {
2620 gsl_qrng_free(quasiRandGen1D);
2621 gsl_qrng_free(quasiRandGen2D);
2627 gsl_matrix * corMat = gsl_matrix_alloc (4, 4);
2628 gsl_vector * rx = gsl_vector_alloc(4);
2629 gsl_vector * ry = gsl_vector_alloc(4);
2631 for (
unsigned int i = 0; i < 4; ++ i) {
2633 for (
unsigned int j = 0; j < i; ++ j) {
2639 int errcode = gsl_linalg_cholesky_decomp(corMat);
2641 if (errcode == GSL_EDOM) {
2642 throw OpalException(
"Distribution::GenerateTransverseGauss",
2643 "gsl_linalg_cholesky_decomp failed");
2646 for (
int i = 0; i < 3; ++ i) {
2647 for (
int j = i+1; j < 4 ; ++ j) {
2648 gsl_matrix_set (corMat, i, j, 0.0);
2652 int saveProcessor = -1;
2657 for (
size_t partIndex = 0; partIndex < numberOfParticles; partIndex++) {
2667 gsl_vector_set(rx, 0, gsl_ran_gaussian (
randGen_m,1.0));
2668 gsl_vector_set(rx, 1, gsl_ran_gaussian (
randGen_m,1.0));
2669 gsl_vector_set(rx, 2, gsl_ran_gaussian (
randGen_m,1.0));
2670 gsl_vector_set(rx, 3, gsl_ran_gaussian (
randGen_m,1.0));
2672 gsl_blas_dgemv(CblasNoTrans, 1.0, corMat, rx, 0.0, ry);
2673 x = gsl_vector_get(ry, 0);
2674 px = gsl_vector_get(ry, 1);
2675 y = gsl_vector_get(ry, 2);
2676 py = gsl_vector_get(ry, 3);
2681 allow = (xAndYOk && pxAndPyOk);
2691 if (saveProcessor >= numNodes)
2694 if (scalable || myNode == saveProcessor) {
2702 gsl_matrix_free(corMat);
2703 gsl_vector_free(rx);
2704 gsl_vector_free(ry);
2726 bool hasID1 = (id1.size() != 0);
2727 bool hasID2 = (id2.size() != 0);
2729 if (hasID1 || hasID2)
2730 *
gmsg <<
"* Use special ID1 or ID2 particle in distribution" <<
endl;
2733 size_t numberOfParticles =
tOrZDist_m.size();
2734 beam->
create(numberOfParticles);
2735 for (
size_t partIndex = 0; partIndex < numberOfParticles; partIndex++) {
2751 beam->
TriID[partIndex] = 0;
2754 beam->
Bin[partIndex] = binNumber;
2757 beam->
Bin[partIndex] = 0;
2760 if (beam->
ID[partIndex] == 1) {
2761 beam->
R[partIndex] =
Vector_t(id1[0],id1[1],id1[2]);
2762 beam->
P[partIndex] =
Vector_t(id1[3],id1[4],id1[5]);
2767 if (beam->
ID[partIndex] == 2) {
2768 beam->
R[partIndex] =
Vector_t(id2[0],id2[1],id2[2]);
2769 beam->
P[partIndex] =
Vector_t(id2[3],id2[4],id2[5]);
2865 if (numberOfParticles > 0) {
2868 os <<
"* Number of particles: "
2905 os <<
"* Distribution type: BINOMIAL" <<
endl;
2910 os <<
"* SIGMAT = " <<
sigmaR_m[2] <<
" [sec]" <<
endl;
2913 os <<
"* SIGMAPX = " <<
sigmaP_m[0] <<
" [Beta Gamma]" <<
endl;
2914 os <<
"* SIGMAPY = " <<
sigmaP_m[1] <<
" [Beta Gamma]" <<
endl;
2915 os <<
"* SIGMAPZ = " <<
sigmaP_m[2] <<
" [Beta Gamma]" <<
endl;
2936 os <<
"* Distribution type: ASTRAFLATTOPTH" <<
endl;
2940 os <<
"* Distribution type: GUNGAUSSFLATTOPTH" <<
endl;
2944 os <<
"* Distribution type: FLATTOP" <<
endl;
2952 os <<
"* Transverse profile determined by laser image: " <<
endl
2969 os <<
"* Time Rise = " <<
tRise_m
2970 <<
" [sec]" <<
endl;
2972 <<
" [sec]" <<
endl;
2976 <<
" [sec]" <<
endl;
2978 <<
" [sec]" <<
endl;
2980 <<
" [sec]" <<
endl;
2981 os <<
"* Longitudinal cutoff = " <<
cutoffR_m[2]
2982 <<
" [units of Sigma Time]" <<
endl;
2983 os <<
"* Flat top modulation amplitude = "
2985 <<
" [Percent of distribution amplitude]" <<
endl;
2986 os <<
"* Flat top modulation periods = "
2998 os <<
"* Distribution type: MULTIGAUSS" <<
endl;
3005 std::string longUnits;
3007 longUnits =
" [sec]";
3011 os <<
"* SIGMAZ = " <<
sigmaR_m[2] << longUnits <<
endl;
3012 os <<
"* CUTOFFLONG = " <<
cutoffR_m[2] <<
" [units of SIGMAZ]" <<
endl;
3017 os <<
"* SIGMAPX = " <<
sigmaP_m[0] <<
" [Beta Gamma]" <<
endl;
3018 os <<
"* SIGMAPY = " <<
sigmaP_m[1] <<
" [Beta Gamma]" <<
endl;
3019 os <<
"* SIGMAPZ = " <<
sigmaP_m[2] <<
" [Beta Gamma]" <<
endl;
3020 os <<
"* CUTOFFPX = " <<
cutoffP_m[0] <<
" [units of SIGMAPX]" <<
endl;
3021 os <<
"* CUTOFFPY = " <<
cutoffP_m[1] <<
" [units of SIGMAPY]" <<
endl;
3022 os <<
"* CUTOFFPZ = " <<
cutoffP_m[2] <<
" [units of SIGMAPZ]" <<
endl;
3027 os <<
"* Distribution type: FROMFILE" <<
endl;
3029 os <<
"* Input file: "
3035 os <<
"* Distribution type: MATCHEDGAUSS" <<
endl;
3039 os <<
"* SIGMAPX = " <<
sigmaP_m[0] <<
" [Beta Gamma]" <<
endl;
3040 os <<
"* SIGMAPY = " <<
sigmaP_m[1] <<
" [Beta Gamma]" <<
endl;
3041 os <<
"* SIGMAPZ = " <<
sigmaP_m[2] <<
" [Beta Gamma]" <<
endl;
3060 os <<
"* Distribution type: GAUSS" <<
endl;
3064 <<
" [sec]" <<
endl;
3066 <<
" [sec]" <<
endl;
3068 <<
" [sec]" <<
endl;
3069 os <<
"* Longitudinal cutoff = " <<
cutoffR_m[2]
3070 <<
" [units of Sigma Time]" <<
endl;
3071 os <<
"* Flat top modulation amplitude = "
3073 <<
" [Percent of distribution amplitude]" <<
endl;
3074 os <<
"* Flat top modulation periods = "
3079 os <<
"* SIGMAPX = " <<
sigmaP_m[0]
3080 <<
" [Beta Gamma]" <<
endl;
3081 os <<
"* SIGMAPY = " <<
sigmaP_m[1]
3082 <<
" [Beta Gamma]" <<
endl;
3086 <<
" [units of SIGMAX]" <<
endl;
3088 <<
" [units of SIGMAY]" <<
endl;
3090 <<
" [units of SIGMAPX]" <<
endl;
3092 <<
" [units of SIGMAPY]" <<
endl;
3097 os <<
"* SIGMAPX = " <<
sigmaP_m[0] <<
" [Beta Gamma]" <<
endl;
3098 os <<
"* SIGMAPY = " <<
sigmaP_m[1] <<
" [Beta Gamma]" <<
endl;
3099 os <<
"* SIGMAPZ = " <<
sigmaP_m[2] <<
" [Beta Gamma]" <<
endl;
3100 os <<
"* AVRGPZ = " <<
avrgpz_m <<
" [Beta Gamma]" <<
endl;
3109 os <<
"* CUTOFFX = " <<
cutoffR_m[0] <<
" [units of SIGMAX]" <<
endl;
3110 os <<
"* CUTOFFY = " <<
cutoffR_m[1] <<
" [units of SIGMAY]" <<
endl;
3111 os <<
"* CUTOFFLONG = " <<
cutoffR_m[2] <<
" [units of SIGMAZ]" <<
endl;
3112 os <<
"* CUTOFFPX = " <<
cutoffP_m[0] <<
" [units of SIGMAPX]" <<
endl;
3113 os <<
"* CUTOFFPY = " <<
cutoffP_m[1] <<
" [units of SIGMAPY]" <<
endl;
3114 os <<
"* CUTOFFPZ = " <<
cutoffP_m[2] <<
" [units of SIGMAPY]" <<
endl;
3120 os <<
"* ------------- THERMAL EMITTANCE MODEL --------------------------------------------" <<
endl;
3137 os <<
"* ----------------------------------------------------------------------------------" <<
endl;
3142 os <<
"* THERMAL EMITTANCE in ASTRA MODE" <<
endl;
3143 os <<
"* Kinetic energy (thermal emittance) = "
3145 <<
" [eV] " <<
endl;
3149 os <<
"* THERMAL EMITTANCE in NONE MODE" <<
endl;
3150 os <<
"* Kinetic energy added to longitudinal momentum = "
3152 <<
" [eV] " <<
endl;
3156 os <<
"* THERMAL EMITTANCE in NONEQUIL MODE" <<
endl;
3173 <<
" contains " <<
sum <<
" particles" <<
endl;
3198 for (
size_t partIndex = 0; partIndex < currentNumPart; partIndex++) {
3211 (numberOfParticles + 1) / 2 != numberOfParticles / 2) {
3233 for (
size_t particleIndex = 0; particleIndex <
tOrZDist_m.size(); ++ particleIndex) {
3234 xDist_m.at(particleIndex) *= xmult;
3235 pxDist_m.at(particleIndex) *= pxmult;
3236 yDist_m.at(particleIndex) *= ymult;
3237 pyDist_m.at(particleIndex) *= pymult;
3239 pzDist_m.at(particleIndex) *= pzmult;
3245 gsl_qrng *quasiRandGen =
nullptr;
3249 quasiRandGen = gsl_qrng_alloc(gsl_qrng_halton, dimension);
3251 quasiRandGen = gsl_qrng_alloc(gsl_qrng_sobol, dimension);
3253 quasiRandGen = gsl_qrng_alloc(gsl_qrng_niederreiter_2, dimension);
3256 quasiRandGen = gsl_qrng_alloc(gsl_qrng_halton, dimension);
3259 return quasiRandGen;
3270 "GUNGAUSSFLATTOPTH",
3278 =
Attributes::makeReal(
"EX",
"Projected normalized emittance EX (m-rad), used to create matched distribution ", 1E-6);
3280 =
Attributes::makeReal(
"EY",
"Projected normalized emittance EY (m-rad) used to create matched distribution ", 1E-6);
3282 =
Attributes::makeReal(
"ET",
"Projected normalized emittance ET (m-rad) used to create matched distribution ", 1E-6);
3286 =
Attributes::makeReal(
"RESIDUUM",
"Residuum for the closed orbit finder and sigma matrix generator ", 1
e-8);
3295 " (false: using all sectors) (default: true)",
3298 =
Attributes::makeReal(
"NSTEPS",
"Number of integration steps of closed orbit finder (matched gauss)"
3299 " (default: 720)", 720);
3308 =
Attributes::makeReal(
"NSECTORS",
"Number of sectors to average field, for closed orbit finder ", 1);
3312 "coordinates.",
"");
3321 "distribution list.", 1.0);
3329 "an injected beam.",
false);
3336 {
"NONE",
"ASTRA",
"NONEQUIL"},
"NONE");
3339 "model (eV). (Thermal energy added in with random "
3340 "number generator.)", 1.0);
3343 "emission. (Default 255 nm light.)", 4.86);
3346 " (Default atomically clean copper.)", 4.31);
3349 " (Default atomically clean copper.)", 7.0);
3352 " (Default 300 K.)", 300.0);
3355 "charge solve.", 0.0);
3401 "Gaussian peaks in MultiGauss "
3402 "distribution.", 0.0);
3404 " pulses in MultiGauss "
3405 "distribution.", 0.0);
3408 "0.0 ... infinity.", 10001.0);
3411 "0.0 ... infinity.", 10001.0);
3414 "0.0 ... infinity.", 10001.0);
3417 "0.0 ... infinity.", 10001.0);
3420 "direction in units of sigma.", 3.0);
3422 "direction in units of sigma.", 3.0);
3424 "direction in units of sigma.", 3.0);
3427 "units of sigma.", 3.0);
3429 "dimension in units of sigma.", 3.0);
3431 "dimension in units of sigma.", 3.0);
3433 "dimension in units of sigma.", 3.0);
3437 "on flat top portion of emitted GAUSS "
3438 "distribtuion (in percent of flat top "
3442 "flat top portion of emitted GAUSS "
3443 "distribution", 0.0);
3482 "profile (x,y).",
"");
3487 "image profile, in % of max intensity.",
3494 =
Attributes::makeBool(
"ROTATE90",
"Rotate laser profile 90 degrees counter clockwise",
false);
3496 =
Attributes::makeBool(
"ROTATE180",
"Rotate laser profile 180 degrees counter clockwise",
false);
3498 =
Attributes::makeBool(
"ROTATE270",
"Rotate laser profile 270 degrees counter clockwise",
false);
3512 "respect of number of particles and number of cores",
false);
3526 "when emitting a distribution.", 100.0);
3576 "The attribute DISTRIBUTION isn't supported any more, use TYPE instead");
3584 else if (
distT_m ==
"BINOMIAL")
3586 else if (
distT_m ==
"FLATTOP")
3588 else if (
distT_m ==
"MULTIGAUSS")
3590 else if (
distT_m ==
"GUNGAUSSFLATTOPTH")
3592 else if (
distT_m ==
"ASTRAFLATTOPTH")
3594 else if (
distT_m ==
"GAUSSMATCHED")
3620 WARNMSG(
"The attribute SIGMAPT may be removed in a future version\n"
3621 <<
"use SIGMAPZ instead" <<
endl);
3658 double deltaT = maxT - minT;
3672 double deltaT = maxT - minT;
3689 throw OpalException(
"Distribution::setDistParametersBinomial",
3690 "Attribute R is not supported for binomial distribution\n"
3691 "use CORR[X|Y|Z] and R51, R52, R61, R62 instead");
3852 if (cr.size() == 15) {
3853 *
gmsg <<
"* Use r to specify correlations" <<
endl;
3855 for (
unsigned int i = 0; i < 5; ++ i) {
3856 for (
unsigned int j = i + 1; j < 6; ++ j, ++ k) {
3864 "Inconsistent set of correlations specified, check manual");
3918 for (
int i=0; i<3; i++) {
3929 if (model ==
"ASTRA")
3931 else if (model ==
"NONEQUIL")
3970 size_t numParticles =
pzDist_m.size();
3973 avgPz /= numParticles;
4020 "PT is obsolete. The moments of the beam is defined with OFFSETPZ");
4023 const double pz = beam->
getP()/beam->
getM();
4024 double gamma = std::hypot(pz, 1.0);
4069 double avgZ[] = {0.0, 1.0 *
tOrZDist_m.size()};
4090 size_t startIdx = 0;
4105 "Attribute T isn't supported anymore; use OFFSETZ instead");
4108 double deltaTOrZ = 0.0;
4118 WARNMSG(
"PT & PZ are obsolete and will be ignored. The moments of the beam is defined with PC" <<
endl);
4128 for (
size_t particleIndex = startIdx; particleIndex < endIdx; ++ particleIndex) {
4129 xDist_m.at(particleIndex) += deltaX;
4130 pxDist_m.at(particleIndex) += deltaPx;
4131 yDist_m.at(particleIndex) += deltaY;
4132 pyDist_m.at(particleIndex) += deltaPy;
4134 pzDist_m.at(particleIndex) += deltaPz;
4157 << std::left << std::setw(84) << std::setfill(
'*') <<
"* " <<
"\n"
4158 <<
"* Write initial distribution to file \"" << fname <<
"\"\n"
4159 << std::left << std::setw(84) << std::setfill(
'*') <<
"* "
4160 << std::setfill(
' ') <<
endl;
4162 std::ofstream outputFile(fname);
4163 if (outputFile.bad()) {
4164 *
gmsg <<
"Unable to open output file \"" << fname <<
"\"" <<
endl;
4166 outputFile.
setf(std::ios::left);
4168 outputFile.width(17);
4169 outputFile <<
"x [m]";
4170 outputFile.width(17);
4171 outputFile <<
"px [betax gamma]";
4172 outputFile.width(17);
4173 outputFile <<
"y [m]";
4174 outputFile.width(17);
4175 outputFile <<
"py [betay gamma]";
4177 outputFile.width(17);
4178 outputFile <<
"t [s]";
4180 outputFile.width(17);
4181 outputFile <<
"z [m]";
4183 outputFile.width(17);
4184 outputFile <<
"pz [betaz gamma]" ;
4186 outputFile.width(17);
4187 outputFile <<
"Bin Number" <<
std::endl;
4190 outputFile.
width(17);
4191 outputFile <<
"Bin Number";
4195 outputFile <<
"# " << totalNum <<
std::endl;
4216 std::vector<char> msgbuf;
4217 const size_t bitsPerParticle = (6 *
sizeof(double) +
sizeof(
size_t));
4218 size_t totalSendBits =
xWrite_m.size() * bitsPerParticle;
4232 if (totalSendBits > 0) {
4233 msgbuf.reserve(totalSendBits);
4235 for (
size_t idx = 0; idx <
xWrite_m.size(); ++ idx) {
4236 buffer =
reinterpret_cast<const char*
>(&(
xWrite_m[idx]));
4237 msgbuf.insert(msgbuf.end(), buffer, buffer +
sizeof(double));
4238 buffer =
reinterpret_cast<const char*
>(&(
pxWrite_m[idx]));
4239 msgbuf.insert(msgbuf.end(), buffer, buffer +
sizeof(double));
4240 buffer =
reinterpret_cast<const char*
>(&(
yWrite_m[idx]));
4241 msgbuf.insert(msgbuf.end(), buffer, buffer +
sizeof(double));
4242 buffer =
reinterpret_cast<const char*
>(&(
pyWrite_m[idx]));
4243 msgbuf.insert(msgbuf.end(), buffer, buffer +
sizeof(double));
4244 buffer =
reinterpret_cast<const char*
>(&(
tOrZWrite_m[idx]));
4245 msgbuf.insert(msgbuf.end(), buffer, buffer +
sizeof(double));
4246 buffer =
reinterpret_cast<const char*
>(&(
pzWrite_m[idx]));
4247 msgbuf.insert(msgbuf.end(), buffer, buffer +
sizeof(double));
4248 buffer =
reinterpret_cast<const char*
>(&(
binWrite_m[idx]));
4249 msgbuf.insert(msgbuf.end(), buffer, buffer +
sizeof(size_t));
4262 std::ofstream outputFile(fname, std::fstream::app);
4263 if (outputFile.bad()) {
4266 if (numberOfBits[node] == 0)
continue;
4267 char *recvbuf =
new char[numberOfBits[node]];
4273 outputFile.precision(9);
4274 outputFile.setf(std::ios::scientific);
4275 outputFile.setf(std::ios::right);
4277 for (
size_t partIndex = 0; partIndex <
xWrite_m.size(); partIndex++) {
4279 outputFile << std::setw(17) <<
xWrite_m.at(partIndex)
4280 << std::setw(17) <<
pxWrite_m.at(partIndex)
4281 << std::setw(17) <<
yWrite_m.at(partIndex)
4282 << std::setw(17) <<
pyWrite_m.at(partIndex)
4284 << std::setw(17) <<
pzWrite_m.at(partIndex)
4290 if (numberOfBits[i] > 0) numSenders ++;
4293 for (
int i = 0; i < numSenders; ++ i) {
4299 while (j < bufsize) {
4300 const double *dbuffer =
reinterpret_cast<const double*
>(recvbuf + j);
4301 const size_t *sbuffer =
reinterpret_cast<const size_t*
>(recvbuf + j + 6 *
sizeof(double));
4302 outputFile << std::setw(17) << dbuffer[0]
4303 << std::setw(17) << dbuffer[1]
4304 << std::setw(17) << dbuffer[2]
4305 << std::setw(17) << dbuffer[3]
4306 << std::setw(17) << dbuffer[4]
4307 << std::setw(17) << dbuffer[5]
4308 << std::setw(17) << sbuffer[0]
4310 j += bitsPerParticle;
4342 for (
int nodeIndex = 0; nodeIndex <
Ippl::getNodes(); nodeIndex++) {
4345 size_t numberOfParticles = 0;
4347 std::ofstream outputFile(fname, std::fstream::app);
4348 if (outputFile.bad()) {
4350 <<
"to file \"" << fname <<
"\"" <<
endl;
4354 outputFile.setf(std::ios::scientific);
4355 outputFile.setf(std::ios::right);
4358 for (
size_t partIndex = 0; partIndex < numberOfParticles; partIndex++) {
4360 outputFile.width(17);
4361 outputFile <<
xDist_m.at(partIndex);
4362 outputFile.width(17);
4363 outputFile <<
pxDist_m.at(partIndex);
4364 outputFile.width(17);
4365 outputFile <<
yDist_m.at(partIndex);
4366 outputFile.width(17);
4367 outputFile <<
pyDist_m.at(partIndex);
4368 outputFile.width(17);
4370 outputFile.width(17);
4371 outputFile <<
pzDist_m.at(partIndex);
4374 outputFile.width(17);
4375 outputFile << binNumber;
4416 for (
unsigned int i = 0; i <
pzDist_m.size(); ++ i) {
4422 allreduce(&(avrg[0]), 6, std::plus<double>());
4428 for (
unsigned int i = 0; i <
pzDist_m.size(); ++ i) {
Tps< T > log(const Tps< T > &x)
Natural logarithm.
Tps< T > cos(const Tps< T > &x)
Cosine.
Tps< T > pow(const Tps< T > &x, int y)
Integer power.
Tps< T > exp(const Tps< T > &x)
Exponential.
Tps< T > sin(const Tps< T > &x)
Sine.
Tps< T > sqrt(const Tps< T > &x)
Square root.
PartBunchBase< T, Dim >::ConstIterator end(PartBunchBase< T, Dim > const &bunch)
constexpr double SMALLESTCUTOFF
T::PETE_Expr_t::PETE_Return_t max(const PETE_Expr< T > &expr, NDIndex< D > &loc)
T::PETE_Expr_t::PETE_Return_t min(const PETE_Expr< T > &expr, NDIndex< D > &loc)
void allreduce(const T *input, T *output, int count, Op op)
bool reduce(Communicate &, InputIterator, InputIterator, OutputIterator, const ReduceOp &, bool *IncludeVal=0)
PETE_TUTree< FnAbs, typename T::PETE_Expr_t > abs(const PETE_Expr< T > &l)
PETE_TBTree< FnArcTan2, PETE_Scalar< Vektor< T1, Dim > >, typename T2::PETE_Expr_t > atan2(const Vektor< T1, Dim > &l, const PETE_Expr< T2 > &r)
PETE_TBTree< FnCopysign, PETE_Scalar< Vektor< T1, Dim > >, typename T2::PETE_Expr_t > copysign(const Vektor< T1, Dim > &l, const PETE_Expr< T2 > &r)
T::PETE_Expr_t::PETE_Return_t sum(const PETE_Expr< T > &expr)
T::PETE_Expr_t::PETE_Return_t prod(const PETE_Expr< T > &expr)
PETE_TUTree< FnCeil, typename T::PETE_Expr_t > ceil(const PETE_Expr< T > &l)
PETE_TUTree< FnArcCos, typename T::PETE_Expr_t > acos(const PETE_Expr< T > &l)
PETE_TUTree< FnArcSin, typename T::PETE_Expr_t > asin(const PETE_Expr< T > &l)
Inform & level1(Inform &inf)
Inform & endl(Inform &inf)
Inform & level2(Inform &inf)
Inform & level3(Inform &inf)
Attribute makeBool(const std::string &name, const std::string &help)
Make logical attribute.
double getReal(const Attribute &attr)
Return real value.
Attribute makePredefinedString(const std::string &name, const std::string &help, const std::initializer_list< std::string > &predefinedStrings)
Make predefined string attribute.
Attribute makeReal(const std::string &name, const std::string &help)
Make real attribute.
bool getBool(const Attribute &attr)
Return logical value.
Attribute makeRealArray(const std::string &name, const std::string &help)
Create real array attribute.
std::vector< double > getRealArray(const Attribute &attr)
Get array value.
std::string getString(const Attribute &attr)
Get string value.
Attribute makeString(const std::string &name, const std::string &help)
Make string attribute.
constexpr double kB
Boltzman's constant in eV/K.
constexpr double two_pi
The value of.
constexpr double epsilon_0
The permittivity of vacuum in As/Vm.
constexpr double alpha
The fine structure constant, no dimension.
constexpr double q_e
The elementary charge in As.
constexpr double m_e
The electron rest mass in GeV.
constexpr double e
The value of.
constexpr double c
The velocity of light in m/s.
constexpr double pi
The value of.
std::string::iterator iterator
std::string rngtype
random number generator
bool cloTuneOnly
Do closed orbit and tune calculation only.
bool cZero
If true create symmetric distribution.
int seed
The current random seed.
std::string combineFilePath(std::initializer_list< std::string > ilist)
double convertMomentumEVoverCToBetaGamma(double p, double mass)
double getBetaGamma(double Ekin, double mass)
The base class for all OPAL beam lines and sequences.
virtual Beamline * fetchLine() const =0
Return the embedded CLASSIC beam line.
static BeamSequence * find(const std::string &name)
Find a BeamSequence by name.
The base class for all OPAL definitions.
The base class for all OPAL objects.
void registerOwnership(const AttributeHandler::OwnerType &itsClass) const
const std::string & getOpalName() const
Return object name.
std::vector< Attribute > itsAttr
The object attributes.
bool builtin
Built-in flag.
void setEnergyBins(int numberOfEnergyBins)
ParticleAttrib< Vector_t > Ef
ParticleAttrib< int > Bin
int getSteptoLastInj() const
void setNumBunch(short n)
double getMassPerParticle() const
double getQ() const
Access to reference data.
double getChargePerParticle() const
get the macro particle charge
size_t getLocalNum() const
ParticleAttrib< double > M
size_t getTotalNum() const
ParticleAttrib< Vector_t > P
ParticleAttrib< ParticleType > PType
ParticleAttrib< ParticleOrigin > POrigin
ParticleAttrib< double > Q
double getInitialGamma() const
ParticleType getPType() const
IpplTimings::TimerRef distrReload_m
timer for IC, can not be in Distribution.h
long long getLocalTrackStep() const
short getNumBunch() const
ParticleAttrib< int > TriID
ParticleAttrib< double > dt
ParticleAttrib< Vector_t > Bf
IpplTimings::TimerRef distrCreate_m
void setPBins(PartBins *pbin)
long long getGlobalTrackStep() const
void setTEmission(double t)
void iterateEmittedBin(int binNumber)
std::string getInputBasename()
get input file name without extension
double getGlobalPhaseShift()
units: (sec)
Object * find(const std::string &name)
Find entry.
static OpalData * getInstance()
void define(Object *newObject)
Define a new object.
std::string getAuxiliaryOutputDirectory() const
get the name of the the additional data directory
void addProblemCharacteristicValue(const std::string &name, unsigned int value)
virtual double getCyclHarm() const
virtual std::string getFieldMapFN() const
virtual double getFMHighE() const
virtual double getPHIinit() const
void setPRinit(double prinit)
void setRinit(double rinit)
virtual double getFMLowE() const
virtual void execute()
Execute the algorithm on the attached beam line.
void setGamma(double gamma)
void fill(std::vector< double > &p)
Add a particle to the temporary container.
An abstract sequence of beam line components.
void shiftDistCoordinates(double massIneV)
static Distribution * find(const std::string &name)
void setDistParametersBinomial(double massIneV)
std::vector< double > & getBGzDist()
std::vector< double > & getTOrZDist()
std::vector< double > xWrite_m
Vector_t pmean_m
Total thermal momentum.
void generateFlattopT(size_t numberOfParticles)
double cathodeTemp_m
Cathode material Fermi energy (eV).
void createOpalCycl(PartBunchBase< double, 3 > *beam, size_t numberOfParticles, double current, const Beamline &bl)
void adjustPhaseSpace(double massIneV)
std::vector< double > pxWrite_m
void writeOutFileHeader()
void checkEmissionParameters()
std::vector< double > tOrZDist_m
double tPulseLengthFWHM_m
EmissionModelT::EmissionModelT emissionModel_m
Emission Model.
int getNumberOfEnergyBins()
virtual void execute()
Execute the command.
gsl_histogram * energyBinHist_m
Distribution energy bins.
void setupEmissionModelAstra(PartBunchBase< double, 3 > *beam)
void printEnergyBins(Inform &os) const
std::vector< std::vector< double > > additionalRNs_m
Upper limit on emission energy distribution (eV).
std::vector< double > pxDist_m
std::vector< double > yWrite_m
double getEmissionDeltaT()
void printDistBinomial(Inform &os) const
double cathodeFermiEnergy_m
Laser photon energy (eV).
double emitEnergyUpperLimit_m
Cathode temperature (K).
void calcPartPerDist(size_t numberOfParticles)
unsigned int numberOfDistributions_m
and list type for switch statements.
void initializeBeam(PartBunchBase< double, 3 > *beam)
void doRestartOpalT(PartBunchBase< double, 3 > *p, size_t Np, int restartStep, H5PartWrapper *h5wrapper)
void applyEmissModelNonEquil(double eZ, double &px, double &py, double &pz, std::vector< double > &additionalRNs)
std::vector< double > & getBGxDist()
void chooseInputMomentumUnits(InputMomentumUnitsT::InputMomentumUnitsT inputMoUnits)
void createOpalT(PartBunchBase< double, 3 > *beam, std::vector< Distribution * > addedDistributions, size_t &numberOfParticles)
void generateAstraFlattopT(size_t numberOfParticles)
size_t getNumberOfParticlesInFile(std::ifstream &inputFile)
DistrTypeT::DistrTypeT distrTypeT_m
Distribution type. Declared as string.
void createDistributionBinomial(size_t numberOfParticles, double massIneV)
void setupEmissionModelNone(PartBunchBase< double, 3 > *beam)
virtual bool canReplaceBy(Object *object)
Distribution can only be replaced by another distribution.
std::vector< Distribution * > addedDistributions_m
Vector of distributions to be added to this distribution.
void doRestartOpalCycl(PartBunchBase< double, 3 > *p, size_t Np, int restartStep, const int specifiedNumBunch, H5PartWrapper *h5wrapper)
std::vector< double > tOrZWrite_m
std::vector< double > & getXDist()
size_t getNumberOfEmissionSteps()
void injectBeam(PartBunchBase< double, 3 > *beam)
std::string laserImageName_m
void create(size_t &numberOfParticles, double massIneV, double charge)
std::vector< double > pyDist_m
int getLastEmittedEnergyBin()
void createDistributionMultiGauss(size_t numberOfParticles, double massIneV)
double laserEnergy_m
Cathode material work function (eV).
void setEmissionTime(double &maxT, double &minT)
void setupEnergyBins(double maxTOrZ, double minTOrZ)
void printEmissionModelNone(Inform &os) const
LaserProfile * laserProfile_m
std::vector< double > yDist_m
void generateFlattopZ(size_t numberOfParticles)
std::vector< size_t > particlesPerDist_m
void generateMatchedGauss(const SigmaGenerator::matrix_t &, size_t numberOfParticles, double massIneV)
double tRise_m
time binned distribution with thermal energy
void setSigmaP_m(double massIneV)
std::string laserProfileFileName_m
std::vector< double > & getYDist()
void printDistFromFile(Inform &os) const
virtual Distribution * clone(const std::string &name)
Return a clone.
double getEmissionTimeShift() const
void printDistMultiGauss(Inform &os) const
void reflectDistribution(size_t &numberOfParticles)
std::vector< double > pzWrite_m
virtual void update()
Update this object.
void generateLongFlattopT(size_t numberOfParticles)
void setDistParametersFlattop(double massIneV)
void printDistFlattop(Inform &os) const
void printDistMatchedGauss(Inform &os) const
static const double percentTEmission_m
void writeOutFileEmission()
void printEmissionModelAstra(Inform &os) const
void printEmissionModelNonEquil(Inform &os) const
void generateBinomial(size_t numberOfParticles)
std::vector< double > & getBGyDist()
void setupParticleBins(double massIneV, PartBunchBase< double, 3 > *beam)
void sampleUniformDisk(gsl_qrng *quasiRandGen2D, double &x1, double &x2)
double currentEmissionTime_m
std::vector< size_t > binWrite_m
double getEnergyBinDeltaT()
void createDistributionFromFile(size_t numberOfParticles, double massIneV)
size_t totalNumberParticles_m
double pTotThermal_m
Random number generator.
void setDistToEmitted(bool emitted)
void setDistParametersMultiGauss(double massIneV)
void createDistributionFlattop(size_t numberOfParticles, double massIneV)
size_t findEBin(double tOrZ)
void scaleDistCoordinates()
std::vector< double > pyWrite_m
SymTenzor< double, 6 > correlationMatrix_m
size_t getNumOfLocalParticlesToCreate(size_t n)
std::vector< double > pzDist_m
double tEmission_m
Emission parameters.
void generateFlattopLaserProfile(size_t numberOfParticles)
gsl_qrng * selectRandomGenerator(std::string, unsigned int dimension)
Select and allocate gsl random number generator.
void generateGaussZ(size_t numberOfParticles)
void printDist(Inform &os, size_t numberOfParticles) const
void applyEmissModelNone(double &pz)
void writeOutFileInjection()
size_t emitParticles(PartBunchBase< double, 3 > *beam, double eZ)
void applyEmissionModel(double lowEnergyLimit, double &px, double &py, double &pz, std::vector< double > &additionalRNs)
void applyEmissModelAstra(double &px, double &py, double &pz, std::vector< double > &additionalRNs)
void setupEmissionModelNonEquil()
void setupEmissionModel(PartBunchBase< double, 3 > *beam)
void printDistGauss(Inform &os) const
InputMomentumUnitsT::InputMomentumUnitsT inputMoUnits_m
void printEmissionModel(Inform &os) const
void setDistParametersGauss(double massIneV)
Inform & printInfo(Inform &os) const
void checkParticleNumber(size_t &numberOfParticles)
void createMatchedGaussDistribution(size_t numberOfParticles, double massIneV, double charge)
void createDistributionGauss(size_t numberOfParticles, double massIneV)
void shiftBeam(double &maxTOrZ, double &minTOrZ)
size_t totalNumberEmittedParticles_m
std::vector< double > xDist_m
double laserIntensityCut_m
void generateTransverseGauss(size_t numberOfParticles)
virtual double get(double rand)
virtual double get(double rand)
void getXY(double &x, double &y)
boost::numeric::ublas::compressed_matrix< double, boost::numeric::ublas::row_major > sparse_matrix_t
Sparse matrix type definition.
boost::numeric::ublas::matrix< double > matrix_t
Dense matrix type definition.
boost::numeric::ublas::vector< double, std::vector< double > > vector_t
Dense vector type definition.
void diagonalize(matrix_t &, sparse_matrix_t &, sparse_matrix_t &)
RealDiracMatrix::matrix_t matrix_t
Type for storing maps.
size_t getNumParticles() const
virtual void readStep(PartBunchBase< double, 3 > *, h5_ssize_t firstParticle, h5_ssize_t lastParticle)=0
virtual bool predecessorIsSameFlavour() const =0
virtual void readHeader()=0
The base class for all OPAL exceptions.
virtual int raw_probe_receive(char *&, int &, int &)
virtual bool raw_send(void *, int, int, int)
virtual int raw_receive(char *, int, int &, int &)
int next_tag(int t, int s=1000)
FmtFlags_t setf(FmtFlags_t setbits, FmtFlags_t field)
static MPI_Comm getComm()
static Communicate * Comm
static void stopTimer(TimerRef t)
static void startTimer(TimerRef t)
Vektor< double, 3 > Vector_t