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/filesystem.hpp>
48#include <boost/regex.hpp>
49#include <boost/numeric/odeint/stepper/runge_kutta4.hpp>
73 for (
unsigned int i = 0; i < 6u; ++ i) {
83 "The DISTRIBUTION statement defines data for the 6D particle distribution."),
85 numberOfDistributions_m(1),
90 currentEmissionTime_m(0.0),
91 currentEnergyBin_m(1),
92 currentSampleBin_m(0),
93 numberOfEnergyBins_m(0),
94 numberOfSampleBins_m(0),
95 energyBins_m(nullptr),
96 energyBinHist_m(nullptr),
100 cathodeWorkFunc_m(0.0),
102 cathodeFermiEnergy_m(0.0),
104 emitEnergyUpperLimit_m(0.0),
105 totalNumberParticles_m(0),
106 totalNumberEmittedParticles_m(0),
111 tPulseLengthFWHM_m(0.0),
112 correlationMatrix_m(getUnit6x6()),
115 laserProfileFileName_m(
""),
116 laserImageName_m(
""),
117 laserIntensityCut_m(0.0),
118 laserProfile_m(nullptr),
125 defaultDistribution->
builtin =
true;
130 delete defaultDistribution;
134 randGen_m = gsl_rng_alloc(gsl_rng_default);
144 distT_m(parent->distT_m),
146 numberOfDistributions_m(parent->numberOfDistributions_m),
147 emitting_m(parent->emitting_m),
148 particleRefData_m(parent->particleRefData_m),
149 addedDistributions_m(parent->addedDistributions_m),
150 particlesPerDist_m(parent->particlesPerDist_m),
151 emissionModel_m(parent->emissionModel_m),
152 tEmission_m(parent->tEmission_m),
153 tBin_m(parent->tBin_m),
154 currentEmissionTime_m(parent->currentEmissionTime_m),
155 currentEnergyBin_m(parent->currentEnergyBin_m),
156 currentSampleBin_m(parent->currentSampleBin_m),
157 numberOfEnergyBins_m(parent->numberOfEnergyBins_m),
158 numberOfSampleBins_m(parent->numberOfSampleBins_m),
159 energyBins_m(nullptr),
160 energyBinHist_m(nullptr),
162 pTotThermal_m(parent->pTotThermal_m),
163 pmean_m(parent->pmean_m),
164 cathodeWorkFunc_m(parent->cathodeWorkFunc_m),
165 laserEnergy_m(parent->laserEnergy_m),
166 cathodeFermiEnergy_m(parent->cathodeFermiEnergy_m),
167 cathodeTemp_m(parent->cathodeTemp_m),
168 emitEnergyUpperLimit_m(parent->emitEnergyUpperLimit_m),
169 totalNumberParticles_m(parent->totalNumberParticles_m),
170 totalNumberEmittedParticles_m(parent->totalNumberEmittedParticles_m),
171 xDist_m(parent->xDist_m),
172 pxDist_m(parent->pxDist_m),
173 yDist_m(parent->yDist_m),
174 pyDist_m(parent->pyDist_m),
175 tOrZDist_m(parent->tOrZDist_m),
176 pzDist_m(parent->pzDist_m),
177 xWrite_m(parent->xWrite_m),
178 pxWrite_m(parent->pxWrite_m),
179 yWrite_m(parent->yWrite_m),
180 pyWrite_m(parent->pyWrite_m),
181 tOrZWrite_m(parent->tOrZWrite_m),
182 pzWrite_m(parent->pzWrite_m),
183 avrgpz_m(parent->avrgpz_m),
184 inputMoUnits_m(parent->inputMoUnits_m),
185 sigmaTRise_m(parent->sigmaTRise_m),
186 sigmaTFall_m(parent->sigmaTFall_m),
187 tPulseLengthFWHM_m(parent->tPulseLengthFWHM_m),
188 sigmaR_m(parent->sigmaR_m),
189 sigmaP_m(parent->sigmaP_m),
190 cutoffR_m(parent->cutoffR_m),
191 cutoffP_m(parent->cutoffP_m),
192 correlationMatrix_m(parent->correlationMatrix_m),
193 sepPeaks_m(parent->sepPeaks_m),
194 nPeaks_m(parent->nPeaks_m),
195 laserProfileFileName_m(parent->laserProfileFileName_m),
196 laserImageName_m(parent->laserImageName_m),
197 laserIntensityCut_m(parent->laserIntensityCut_m),
198 laserProfile_m(nullptr),
201 tRise_m(parent->tRise_m),
202 tFall_m(parent->tFall_m),
203 sigmaRise_m(parent->sigmaRise_m),
204 sigmaFall_m(parent->sigmaFall_m),
205 cutoff_m(parent->cutoff_m)
208 randGen_m = gsl_rng_alloc(gsl_rng_default);
235 if (myNode < remainder)
264 size_t numberOfLocalParticles = numberOfParticles;
266 numberOfLocalParticles = (numberOfParticles + 1) / 2;
274 mySeed = tv.tv_sec + tv.tv_usec;
279 *
gmsg <<
level2 <<
"* Generation of distribution with seed = " << mySeed <<
" + core_id\n"
280 <<
"* is scalable with number of particles and cores." <<
endl;
283 *
gmsg <<
level2 <<
"* Generation of distribution with seed = " << mySeed <<
"\n"
284 <<
"* isn't scalable with number of particles and cores." <<
endl;
313 "Unknown \"TYPE\" of \"DISTRIBUTION\"");
318 unsigned int numAdditionalRNsPerParticle = 0;
323 numAdditionalRNsPerParticle = 2;
326 numAdditionalRNsPerParticle = 40;
328 numAdditionalRNsPerParticle = 20;
332 int saveProcessor = -1;
337 for (
size_t partIndex = 0; partIndex < numberOfLocalParticles; ++ partIndex) {
341 if (saveProcessor >= numNodes)
344 if (scalable || myNode == saveProcessor) {
345 std::vector<double> rns;
346 for (
unsigned int i = 0; i < numAdditionalRNsPerParticle; ++ i) {
352 for (
unsigned int i = 0; i < numAdditionalRNsPerParticle; ++ i) {
384 size_t firstParticle = numParticlesPerNode *
Ippl::myNode();
385 size_t lastParticle = firstParticle + numParticlesPerNode - 1;
387 lastParticle = numParticles - 1;
390 numParticles = lastParticle - firstParticle + 1;
393 beam->
create(numParticles);
396 dataSource->
readStep(beam, firstParticle, lastParticle);
400 double actualT = beam->
getT();
406 *
gmsg <<
"Total number of particles in the h5 file= " << beam->
getTotalNum() <<
"\n"
407 <<
"Global step= " << gtstep <<
"; Local step= " << ltstep <<
"; "
408 <<
"restart step= " << restartStep <<
"\n"
415 const int specifiedNumBunch,
420 INFOMSG(
"---------------- Start reading hdf5 file----------------" <<
endl);
425 size_t firstParticle = numParticlesPerNode *
Ippl::myNode();
426 size_t lastParticle = firstParticle + numParticlesPerNode - 1;
428 lastParticle = numParticles - 1;
431 numParticles = lastParticle - firstParticle + 1;
434 beam->
create(numParticles);
437 dataSource->
readStep(beam, firstParticle, lastParticle);
447 INFOMSG(
"total number of particles = " << globalN <<
endl);
448 INFOMSG(
"* Restart Energy = " << meanE <<
" (MeV), Path lenght = " << beam->
get_sPos() <<
" (m)" <<
endl);
455 INFOMSG(
"* Gamma = " << gamma <<
", Beta = " << beta <<
endl);
458 INFOMSG(
"Restart from hdf5 file generated by OPAL-cycl" <<
endl);
459 if (specifiedNumBunch > 1) {
466 INFOMSG(
"Restart from hdf5 file generated by OPAL-t" <<
endl);
471 for (
unsigned int i = 0; i < newLocalN; ++i) {
472 for (
int d = 0; d < 3; ++d) {
473 meanR(d) += beam->
R[i](d);
474 meanP(d) += beam->
P[i](d);
481 INFOMSG(
"Rmean = " << meanR <<
"[m], Pmean=" << meanP <<
endl);
483 for (
unsigned int i = 0; i < newLocalN; ++i) {
489 INFOMSG(
"---------------Finished reading hdf5 file---------------" <<
endl);
497 throw OpalException(
"Distribution::find()",
"Distribution \"" +
name +
"\" not found.");
522 double inv_erf08 = 0.906193802436823;
524 double t =
a - sqr2 * sig * inv_erf08;
527 for (
int i = 0; i < 10; ++ i) {
528 sig = (t +
tRise_m -
a) / (sqr2 * inv_erf08);
529 t =
a - 0.5 * sqr2 * (sig + tmps) * inv_erf08;
530 sig = (0.5 * (t + tmpt) +
tRise_m -
a) / (sqr2 * inv_erf08);
550 <<
"* ************* D I S T R I B U T I O N ********************************************" <<
endl;
553 os <<
"* In restart. Distribution read in from .h5 file." <<
endl;
556 os <<
"* Main Distribution" <<
endl
557 <<
"-----------------" <<
endl;
564 size_t distCount = 1;
567 os <<
"* Added Distribution #" << distCount <<
endl;
568 os <<
"* ----------------------" <<
endl;
582 os <<
"* Distribution is emitted. " <<
endl;
589 os <<
"* Distribution is injected." <<
endl;
593 os <<
"*\n* Write initial distribution to file '" <<
outFilename_m <<
"'" <<
endl;
597 os <<
"* **********************************************************************************" <<
endl;
614 for (
double dist : (*addedDistIt)->getXDist()) {
617 (*addedDistIt)->eraseXDist();
619 for (
double dist : (*addedDistIt)->getBGxDist()) {
622 (*addedDistIt)->eraseBGxDist();
624 for (
double dist : (*addedDistIt)->getYDist()) {
627 (*addedDistIt)->eraseYDist();
629 for (
double dist : (*addedDistIt)->getBGyDist()) {
632 (*addedDistIt)->eraseBGyDist();
634 for (
double dist : (*addedDistIt)->getTOrZDist()) {
637 (*addedDistIt)->eraseTOrZDist();
639 for (
double dist : (*addedDistIt)->getBGzDist()) {
642 (*addedDistIt)->eraseBGzDist();
683 std::vector<double> &additionalRNs) {
691 unsigned int counter = 0;
694 double randFuncValue = additionalRNs[counter++];
696 double funcValue = ((1.0
697 - 1.0 / (1.0 + expRelativeEnergy * expRelativeLaserEnergy)) /
698 (1.0 + expRelativeEnergy));
700 if (randFuncValue <= funcValue)
703 if (counter == additionalRNs.size()) {
704 for (
unsigned int i = 0; i < counter; ++ i) {
705 additionalRNs[i] = gsl_rng_uniform(
randGen_m);
712 while (additionalRNs.size() - counter < 2) {
714 additionalRNs[counter] = gsl_rng_uniform(
randGen_m);
719 double energyExternal = energy - lowEnergyLimit;
722 double thetaIn = additionalRNs[counter++] * thetaInMax;
723 double sinThetaOut =
std::sin(thetaIn) *
std::sqrt(energyInternal / energyExternal);
727 double betaGammaExternal
730 bgx = betaGammaExternal * sinThetaOut *
std::cos(phi);
731 bgy = betaGammaExternal * sinThetaOut *
std::sin(phi);
743 std::map<unsigned int, size_t> nPartFromFiles;
744 double totalWeight = 0.0;
751 std::ifstream inputFile;
754 inputFile.open(fileName.c_str());
757 nPartFromFiles.insert(std::make_pair(i, nPart));
758 if (nPart > numberOfParticles) {
760 "Number of particles is too small");
763 numberOfParticles -= nPart;
769 size_t numberOfCommittedPart = 0;
778 size_t particlesCurrentDist = numberOfParticles * currDist->
getWeight() / totalWeight;
780 numberOfCommittedPart += particlesCurrentDist;
785 if (numberOfParticles != numberOfCommittedPart) {
786 size_t diffNumber = numberOfParticles - numberOfCommittedPart;
798 if (diffNumber != 0) {
800 "Particles can't be distributed to distributions in array");
816 if (emissionSteps == 0)
847 size_t numberOfDistParticles =
tOrZDist_m.size();
850 if (numberOfDistParticles == 0) {
852 "Zero particles in the distribution! "
853 "The number of particles needs to be specified.");
856 if (numberOfDistParticles != numberOfParticles) {
858 "The number of particles in the initial\n"
860 std::to_string(numberOfDistParticles) +
"\n"
861 "is different from the number of particles\n"
862 "defined by the BEAM command\n" +
863 std::to_string(numberOfParticles) +
".\n"
864 "This often happens when using a FROMFILE type\n"
865 "distribution and not matching the number of\n"
866 "particles in the input distribution file(s) with\n"
867 "the number given in the BEAM command.");
877 "The z-momentum of the particle distribution\n" +
878 std::to_string(
pmean_m[2]) +
"\n"
879 "is different from the momentum given in the \"BEAM\" command\n" +
881 "When using a \"FROMFILE\" type distribution\n"
882 "the momentum in the \"BEAM\" command should be\n"
883 "the same as the momentum of the particles in the file.");
891 static const std::map<std::string, InputMomentumUnits> stringInputMomentumUnits_s = {
897 if (inputUnits.empty()) {
930 int saveProcessor = -1;
937 for (
size_t partIndex = 0; partIndex < numberOfParticles; partIndex++) {
938 double x = 0.0, y = 0.0, tOrZ = 0.0;
939 double px = 0.0, py = 0.0, pz = 0.0;
949 double randNums[2] = {0.0, 0.0};
951 if (quasiRandGen2D !=
nullptr) {
952 gsl_qrng_get(quasiRandGen2D, randNums);
954 randNums[0] = gsl_rng_uniform(
randGen_m);
955 randNums[1] = gsl_rng_uniform(
randGen_m);
961 for (
unsigned i = 0; i <
nPeaks_m; i++)
963 allow = (r <= proba);
984 if (saveProcessor >= numNodes)
987 if (scalable || myNode == saveProcessor) {
997 gsl_qrng_free(quasiRandGen2D);
1002 size_t numberOfParticlesRead = 0;
1004 const boost::regex commentExpr(
"[[:space:]]*#.*");
1005 const std::string repl(
"");
1007 std::stringstream linestream;
1011 std::getline(inputFile, line);
1012 line = boost::regex_replace(line, commentExpr, repl);
1013 }
while (line.length() == 0 && !inputFile.fail());
1015 linestream.str(line);
1016 linestream >> tempInt;
1018 throw OpalException(
"Distribution::getNumberOfParticlesInFile",
1021 "' does not seem to be an ASCII file containing a distribution.");
1023 numberOfParticlesRead =
static_cast<size_t>(tempInt);
1027 return numberOfParticlesRead;
1032 std::ifstream inputFile;
1034 if (!boost::filesystem::exists(fileName)) {
1036 "Distribution::createDistributionFromFile",
1037 "Open file operation failed, please check if '" + fileName +
"' really exists.");
1040 inputFile.open(fileName.c_str());
1048 unsigned int saveProcessor = 0;
1052 unsigned int distributeFrequency = 1000;
1053 size_t singleDataSize = 6;
1054 unsigned int dataSize = distributeFrequency * singleDataSize;
1055 std::vector<double> data(dataSize);
1058 constexpr unsigned int bufferSize = 1024;
1059 char lineBuffer[bufferSize];
1060 unsigned int numParts = 0;
1062 while (!inputFile.eof()) {
1063 inputFile.getline(lineBuffer, bufferSize);
1067 std::istringstream line(lineBuffer);
1087 if (saveProcessor > 0u) {
1088 currentPosition = std::copy(&(
R[0]), &(
R[0]) + 3, currentPosition);
1089 currentPosition = std::copy(&(P[0]), &(P[0]) + 3, currentPosition);
1091 if (currentPosition == data.end()) {
1093 MPI_Bcast(&(data[0]), dataSize, MPI_DOUBLE, 0,
Ippl::getComm());
1095 currentPosition = data.begin();
1111 (numberOfParticlesRead == numParts ? currentPosition - data.begin()
1115 if (numberOfParticlesRead != numParts) {
1117 "Distribution::createDistributionFromFile",
1118 "Found " + std::to_string(numParts) +
" particles in file '" + fileName
1119 +
"' instead of " + std::to_string(numberOfParticlesRead));
1121 MPI_Bcast(&(data[0]), dataSize, MPI_DOUBLE, 0,
Ippl::getComm());
1128 "Distribution::createDistributionFromFile",
1129 "Couldn't find " + std::to_string(numberOfParticlesRead)
1130 +
" particles in file '" + fileName +
"'");
1132 MPI_Bcast(&(data[0]), dataSize, MPI_DOUBLE, 0,
Ippl::getComm());
1135 while (i < dataSize) {
1137 const double* tmp = &(data[i]);
1145 i += singleDataSize;
1152 }
while (dataSize == distributeFrequency * singleDataSize);
1155 pmean_m /= numberOfParticlesRead;
1173 if (lineName.empty())
return;
1176 if (lineSequence ==
nullptr)
1177 throw OpalException(
"Distribution::CreateMatchedGaussDistribution",
1178 "didn't find any Cyclotron element in line");
1182 size_t NumberOfCyclotrons = CyclotronVisitor.
size();
1184 if (NumberOfCyclotrons > 1) {
1185 throw OpalException(
"Distribution::createMatchedGaussDistribution",
1186 "I am confused, found more than one Cyclotron element in line");
1188 if (NumberOfCyclotrons == 0) {
1189 throw OpalException(
"Distribution::createMatchedGaussDistribution",
1190 "didn't find any Cyclotron element in line");
1203 throw OpalException(
"Distribution::createMatchedGaussDistribution()",
1204 "Negative number of integration steps");
1207 throw OpalException(
"Distribution::createMatchedGaussDistribution()",
1208 "Negative number of sectors");
1210 if ( Nsectors > 1 && full ==
false )
1211 throw OpalException(
"Distribution::createMatchedGaussDistribution()",
1212 "Averaging over sectors can only be done with SECTOR=FALSE");
1214 *
gmsg <<
"* ----------------------------------------------------" <<
endl;
1215 *
gmsg <<
"* About to find closed orbit and matched distribution " <<
endl;
1221 *
gmsg <<
"* SECTOR: " <<
"match using all sectors, with" <<
endl
1222 <<
"* NSECTORS = " << Nsectors <<
" to average the field over" <<
endl;
1225 *
gmsg <<
"* SECTOR: " <<
"match using single sector" <<
endl;
1227 *
gmsg <<
"* NSTEPS = " << Nint <<
endl
1231 <<
"* ----------------------------------------------------" <<
endl;
1233 if ( CyclotronElement->
getFMLowE() < 0 ||
1236 throw OpalException(
"Distribution::createMatchedGaussDistribution()",
1237 "Missing attributes 'FMLOWE' and/or 'FMHIGHE' in "
1238 "'CYCLOTRON' definition.");
1241 std::size_t maxitCOF =
1250 if ( denergy < 0.0 )
1251 throw OpalException(
"Distribution:createMatchedGaussDistribution()",
1258 *
gmsg <<
"* Stopping after closed orbit and tune calculation" <<
endl;
1259 typedef std::vector<double> container_t;
1260 typedef boost::numeric::odeint::runge_kutta4<container_t> rk4_t;
1263 cof_t cof(massIneV*
Units::eV2MeV, charge, Nint, CyclotronElement, full, Nsectors);
1264 cof.findOrbit(accuracy, maxitCOF,
E_m*
Units::eV2MeV, denergy, rguess,
true);
1267 "Do only tune calculation.");
1270 bool writeMap =
true;
1272 std::unique_ptr<SigmaGenerator> siggen = std::unique_ptr<SigmaGenerator>(
1286 if (siggen->match(accuracy,
1294 std::array<double,3> Emit = siggen->getEmittances();
1297 *
gmsg <<
"* RGUESS " << rguess <<
" (m) " <<
endl;
1299 *
gmsg <<
"* Converged (Ex, Ey, Ez) = (" << Emit[0] <<
", " << Emit[1] <<
", "
1301 *
gmsg <<
"* Sigma-Matrix " <<
endl;
1303 for (
unsigned int i = 0; i < siggen->getSigma().size1(); ++ i) {
1304 *
gmsg << std::setprecision(4) << std::setw(11) << siggen->getSigma()(i,0);
1305 for (
unsigned int j = 1; j < siggen->getSigma().size2(); ++ j) {
1306 if (
std::abs(siggen->getSigma()(i,j)) < 1.0e-15) {
1307 *
gmsg <<
" & " << std::setprecision(4) << std::setw(11) << 0.0;
1310 *
gmsg <<
" & " << std::setprecision(4) << std::setw(11) << siggen->getSigma()(i,j);
1321 CyclotronElement->
setPRinit(siggen->getInjectionMomentum());
1326 throw OpalException(
"Distribution::CreateMatchedGaussDistribution",
1327 "didn't find any matched distribution.");
1344 size_t numberOfParticles,
1345 double current,
const Beamline &) {
1353 size_t numberOfPartToCreate = numberOfParticles;
1406 std::vector<Distribution *> addedDistributions,
1407 size_t &numberOfParticles) {
1414 size_t &numberOfParticles) {
1437 addedDist->setDistType();
1463 size_t distCount = 1;
1519 std::vector<std::vector<double> > mirrored;
1527 std::vector<double> tmp;
1528 tmp.push_back((*it).front());
1529 tmp.push_back((*it).back() + 0.5);
1530 mirrored.push_back(tmp);
1535 std::vector<double> tmp((*it).begin() + numAdditionals, (*it).end());
1536 mirrored.push_back(tmp);
1537 (*it).erase((*it).begin() + numAdditionals, (*it).end());
1582 size_t numberOfEmittedParticles = beam->
getLocalNum();
1583 size_t oldNumberOfEmittedParticles = numberOfEmittedParticles;
1592 std::vector<size_t> particlesToBeErased;
1598 for (
size_t particleIndex = 0; particleIndex <
tOrZDist_m.size(); particleIndex++) {
1606 particlesToBeErased.push_back(particleIndex);
1609 double deltaT =
tOrZDist_m.at(particleIndex);
1610 beam->
dt[numberOfEmittedParticles] = deltaT;
1612 double oneOverCDt = 1.0 / (
Physics::c * deltaT);
1614 double px =
pxDist_m.at(particleIndex);
1615 double py =
pyDist_m.at(particleIndex);
1616 double pz =
pzDist_m.at(particleIndex);
1617 std::vector<double> additionalRNs;
1622 "not enough additional particles");
1626 double particleGamma
1632 beam->
R[numberOfEmittedParticles]
1634 + px * deltaT *
Physics::c / (2.0 * particleGamma)),
1635 oneOverCDt * (
yDist_m.at(particleIndex)
1636 + py * deltaT *
Physics::c / (2.0 * particleGamma)),
1637 pz / (2.0 * particleGamma));
1638 beam->
P[numberOfEmittedParticles]
1643 beam->
Ef[numberOfEmittedParticles] =
Vector_t(0.0);
1644 beam->
Bf[numberOfEmittedParticles] =
Vector_t(0.0);
1647 beam->
TriID[numberOfEmittedParticles] = 0;
1648 numberOfEmittedParticles++;
1664 std::vector<size_t>::reverse_iterator ptbErasedIt;
1665 for (ptbErasedIt = particlesToBeErased.rbegin();
1666 ptbErasedIt < particlesToBeErased.rend();
1706 <<
" has emitted all particles (new emit)." <<
endl);
1734 size_t currentEmittedParticles = numberOfEmittedParticles - oldNumberOfEmittedParticles;
1738 return currentEmittedParticles;
1769 double randNums[2] = {0.0, 0.0};
1771 if (quasiRandGen2D !=
nullptr)
1772 gsl_qrng_get(quasiRandGen2D, randNums);
1774 randNums[0] = gsl_rng_uniform(
randGen_m);
1775 randNums[1] = gsl_rng_uniform(
randGen_m);
1778 x1 = 2 * randNums[0] - 1;
1779 x2 = 2 * randNums[1] - 1;
1790 const size_t numberOfParticles =
tOrZDist_m.size();
1791 for (
size_t partIndex = 0; partIndex < numberOfParticles; partIndex++) {
1805 for (
size_t particleIndex = 0; particleIndex <
tOrZDist_m.size(); particleIndex++) {
1807 std::vector<double> partCoord;
1809 partCoord.push_back(
xDist_m.at(particleIndex));
1810 partCoord.push_back(
yDist_m.at(particleIndex));
1811 partCoord.push_back(
tOrZDist_m.at(particleIndex));
1812 partCoord.push_back(
pxDist_m.at(particleIndex));
1813 partCoord.push_back(
pyDist_m.at(particleIndex));
1814 partCoord.push_back(
pzDist_m.at(particleIndex));
1815 partCoord.push_back(0.0);
1845 gsl_qrng *quasiRandGen = gsl_qrng_alloc(gsl_qrng_halton, 2);
1847 int numberOfSampleBins
1849 int numberOfEnergyBins
1852 int binTotal = numberOfSampleBins * numberOfEnergyBins;
1854 double *distributionTable =
new double[binTotal + 1];
1858 double inv_erf08 = 0.906193802436823;
1860 double t =
a - sqr2 * sig * inv_erf08;
1864 for (
int i = 0; i < 10; ++ i) {
1865 sig = (t +
tRise_m -
a) / (sqr2 * inv_erf08);
1866 t =
a - 0.5 * sqr2 * (sig + tmps) * inv_erf08;
1867 sig = (0.5 * (t + tmpt) +
tRise_m -
a) / (sqr2 * inv_erf08);
1879 double lo = -
tBin_m / 2.0 * numberOfEnergyBins;
1880 double hi =
tBin_m / 2.0 * numberOfEnergyBins;
1881 double dx =
tBin_m / numberOfSampleBins;
1884 double weight = 2.0;
1887 for (
int i = 0; i < binTotal + 1; ++ i, x += dx, weight = 6. - weight) {
1888 distributionTable[i] = gsl_sf_erf((x +
a) / (sqr2 * sig)) - gsl_sf_erf((x -
a) / (sqr2 * sig));
1889 tot += distributionTable[i] * weight;
1891 tot -= distributionTable[binTotal] * (5. - weight);
1892 tot -= distributionTable[0];
1894 int saveProcessor = -1;
1898 double tCoord = 0.0;
1900 int effectiveNumParticles = 0;
1902 std::vector<int> numParticlesInBin(numberOfEnergyBins,0);
1903 for (
int k = 0; k < numberOfEnergyBins; ++ k) {
1904 double loc_fraction = -distributionTable[numberOfSampleBins * k] / tot;
1907 for (
int i = numberOfSampleBins * k; i < numberOfSampleBins * (k + 1) + 1;
1908 ++ i, weight = 6. - weight) {
1909 loc_fraction += distributionTable[i] * weight / tot;
1911 loc_fraction -= distributionTable[numberOfSampleBins * (k + 1)]
1912 * (5. - weight) / tot;
1913 numParticlesInBin[k] =
static_cast<int>(std::round(loc_fraction * numberOfParticles));
1914 effectiveNumParticles += numParticlesInBin[k];
1915 if (numParticlesInBin[k] > numParticlesInBin[largestBin]) largestBin = k;
1918 numParticlesInBin[largestBin] += (numberOfParticles - effectiveNumParticles);
1920 for (
int k = 0; k < numberOfEnergyBins; ++ k) {
1921 gsl_ran_discrete_t *table
1922 = gsl_ran_discrete_preproc(numberOfSampleBins,
1923 &(distributionTable[numberOfSampleBins * k]));
1925 for (
int i = 0; i < numParticlesInBin[k]; i++) {
1927 gsl_qrng_get(quasiRandGen, xx);
1928 tCoord = hi * (xx[1] +
static_cast<int>(gsl_ran_discrete(
randGen_m, table))
1929 - binTotal / 2 + k * numberOfSampleBins) / (binTotal / 2);
1932 if (saveProcessor >= numNodes)
1935 if (scalable || myNode == saveProcessor) {
1940 gsl_ran_discrete_free(table);
1943 gsl_qrng_free(quasiRandGen);
1944 delete [] distributionTable;
1972 for (
unsigned int index = 0; index < 3; index++) {
1976 if (
std::abs(emittance(index)) > std::numeric_limits<double>::epsilon()) {
1984 *
std::sqrt(beta(index) * gamma(index));
1991 for (
unsigned int index = 0; index < 3; index++) {
1995 SINCHI[index] = -
alpha(index) * COSCHI[index];
1996 CHI[index] =
std::atan2(SINCHI[index], COSCHI[index]);
1998 M[index] =
std::sqrt(emittance(index) * beta(index));
1999 PM[index] =
std::sqrt(emittance(index) * gamma(index));
2004 X[index] = L[index];
2005 PX[index] = PL[index];
2008 X[index] = M[index];
2009 PX[index] =
PM[index];
2014 int saveProcessor = -1;
2035 for (
size_t partIndex = 0; partIndex < numberOfParticles; partIndex++) {
2039 double Ux = 0.0, U = 0.0;
2040 double Vx = 0.0, V = 0.0;
2042 A = splitter[0]->get(gsl_rng_uniform(
randGen_m));
2047 p[0] = PX[0] * (Ux * SINCHI[0] + Vx * COSCHI[0]);
2049 A = splitter[1]->get(gsl_rng_uniform(
randGen_m));
2054 p[1] = PX[1] * (U * SINCHI[1] + V * COSCHI[1]);
2056 A = splitter[2]->get(gsl_rng_uniform(
randGen_m));
2065 if (saveProcessor >= numNodes)
2068 if (scalable || myNode == saveProcessor) {
2078 for (
unsigned int index = 0; index < 3; index++) {
2079 delete splitter[index];
2085 int saveProcessor = -1;
2090 for (
size_t partIndex = 0; partIndex < numberOfParticles; partIndex++) {
2101 if (saveProcessor >= numNodes)
2104 if (scalable || myNode == saveProcessor) {
2123 int saveProcessor = -1;
2127 for (
size_t partIndex = 0; partIndex < numberOfParticles; partIndex++) {
2140 if (saveProcessor >= numNodes)
2143 if (scalable || myNode == saveProcessor) {
2152 gsl_qrng_free(quasiRandGen2D);
2166 int saveProcessor = -1;
2171 for (
size_t partIndex = 0; partIndex < numberOfParticles; partIndex++) {
2184 if (quasiRandGen1D !=
nullptr)
2185 gsl_qrng_get(quasiRandGen1D, &z);
2193 if (saveProcessor >= numNodes)
2196 if (scalable || myNode == saveProcessor) {
2206 gsl_qrng_free(quasiRandGen1D);
2207 gsl_qrng_free(quasiRandGen2D);
2212 gsl_matrix * corMat = gsl_matrix_alloc (6, 6);
2213 gsl_vector * rx = gsl_vector_alloc(6);
2214 gsl_vector * ry = gsl_vector_alloc(6);
2216 for (
unsigned int i = 0; i < 6; ++ i) {
2218 for (
unsigned int j = 0; j < i; ++ j) {
2226 *
gmsg <<
"* m before gsl_linalg_cholesky_decomp" <<
endl;
2227 for (
int i = 0; i < 6; i++) {
2228 for (
int j = 0; j < 6; j++) {
2230 *
gmsg <<
"* r(" << std::setprecision(1) << i <<
", : ) = "
2231 << std::setprecision(4) << std::setw(10) << gsl_matrix_get (corMat, i, j);
2233 *
gmsg <<
" & " << std::setprecision(4) << std::setw(10) << gsl_matrix_get (corMat, i, j);
2242 int errcode = gsl_linalg_cholesky_decomp(corMat);
2271 if (errcode == GSL_EDOM) {
2273 "gsl_linalg_cholesky_decomp failed");
2276 for (
int i = 0; i < 5; ++ i) {
2277 for (
int j = i+1; j < 6 ; ++ j) {
2278 gsl_matrix_set (corMat, i, j, 0.0);
2283 *
gmsg <<
"* m after gsl_linalg_cholesky_decomp" <<
endl;
2284 for (
int i = 0; i < 6; i++) {
2285 for (
int j = 0; j < 6; j++) {
2287 *
gmsg <<
"* r(" << std::setprecision(1) << i <<
", : ) = "
2288 << std::setprecision(4) << std::setw(10) << gsl_matrix_get (corMat, i, j);
2290 *
gmsg <<
" & " << std::setprecision(4) << std::setw(10) << gsl_matrix_get (corMat, i, j);
2296 int saveProcessor = -1;
2301 for (
size_t partIndex = 0; partIndex < numberOfParticles; partIndex++) {
2312 gsl_vector_set(rx, 0, gsl_ran_gaussian(
randGen_m, 1.0));
2313 gsl_vector_set(rx, 1, gsl_ran_gaussian(
randGen_m, 1.0));
2314 gsl_vector_set(rx, 2, gsl_ran_gaussian(
randGen_m, 1.0));
2315 gsl_vector_set(rx, 3, gsl_ran_gaussian(
randGen_m, 1.0));
2316 gsl_vector_set(rx, 4, gsl_ran_gaussian(
randGen_m, 1.0));
2317 gsl_vector_set(rx, 5, gsl_ran_gaussian(
randGen_m, 1.0));
2319 gsl_blas_dgemv(CblasNoTrans, 1.0, corMat, rx, 0.0, ry);
2321 x = gsl_vector_get(ry, 0);
2322 px = gsl_vector_get(ry, 1);
2323 y = gsl_vector_get(ry, 2);
2324 py = gsl_vector_get(ry, 3);
2325 z = gsl_vector_get(ry, 4);
2326 pz = gsl_vector_get(ry, 5);
2334 allow = (xAndYOk && pxAndPyOk && zOk && pzOk);
2346 if (saveProcessor >= numNodes)
2349 if (scalable || myNode == saveProcessor) {
2361 gsl_vector_free(rx);
2362 gsl_vector_free(ry);
2363 gsl_matrix_free(corMat);
2367 size_t numberOfParticles,
double massIneV)
2380 for (
unsigned int i = 0; i < 3; ++ i) {
2381 if ( sigma(2 * i, 2 * i) < 0 || sigma(2 * i + 1, 2 * i + 1) < 0 )
2383 "Negative value on the diagonal of the sigma matrix.");
2420 A(0, 0) = sigma(0, 0);
2421 A(1, 1) = sigma(1, 1);
2422 A(2, 2) = sigma(4, 4);
2423 A(3, 3) = sigma(5, 5);
2425 A(0, 1) = sigma(0, 1);
2426 A(0, 2) = sigma(0, 4);
2427 A(0, 3) = sigma(0, 5);
2428 A(1, 0) = sigma(1, 0);
2429 A(2, 0) = sigma(4, 0);
2430 A(3, 0) = sigma(5, 0);
2432 A(1, 2) = sigma(1, 4);
2433 A(2, 1) = sigma(4, 1);
2434 A(1, 3) = sigma(1, 5);
2435 A(3, 1) = sigma(5, 1);
2436 A(2, 3) = sigma(4, 5);
2437 A(3, 2) = sigma(5, 4);
2444 for (
int i = 0; i < 4; ++i) {
2454 A(2, 2) = sigma(2, 2);
2455 A(3, 3) = sigma(3, 3);
2456 A(2, 3) = sigma(2, 3);
2457 A(3, 2) = sigma(3, 2);
2461 for (
int i = 0; i < 4; ++i) {
2465 int saveProcessor = -1;
2471 for (
size_t i = 0; i < numberOfParticles; i++) {
2472 for (
int j = 0; j < 4; j++) {
2473 p1(j) = gsl_ran_gaussian(
randGen_m, 1.0) * variances(j);
2474 p2(j) = gsl_ran_gaussian(
randGen_m, 1.0) * variances(4 + j);
2482 if (saveProcessor >= numNodes)
2485 if (scalable || myNode == saveProcessor) {
2501 if (flattopTime < 0.0)
2505 double distArea = flattopTime
2509 size_t numRise = numberOfParticles *
sigmaTRise_m * normalizedFlankArea / distArea;
2510 size_t numFall = numberOfParticles *
sigmaTFall_m * normalizedFlankArea / distArea;
2511 size_t numFlat = numberOfParticles - numRise - numFall;
2514 int saveProcessor = -1;
2519 for (
size_t partIndex = 0; partIndex < numFall; partIndex++) {
2535 if (saveProcessor >= numNodes)
2538 if (scalable || myNode == saveProcessor) {
2549 if (modulationAmp > 1.0)
2550 modulationAmp = 1.0;
2551 double numModulationPeriods
2553 double modulationPeriod = 0.0;
2554 if (numModulationPeriods != 0.0)
2555 modulationPeriod = flattopTime / numModulationPeriods;
2560 for (
size_t partIndex = 0; partIndex < numFlat; partIndex++) {
2565 if (modulationAmp == 0.0 || numModulationPeriods == 0.0) {
2567 if (quasiRandGen1D !=
nullptr)
2568 gsl_qrng_get(quasiRandGen1D, &t);
2572 t = flattopTime * t;
2577 double randNums[2] = {0.0, 0.0};
2579 if (quasiRandGen2D !=
nullptr) {
2580 gsl_qrng_get(quasiRandGen2D, randNums);
2582 randNums[0]= gsl_rng_uniform(
randGen_m);
2583 randNums[1]= gsl_rng_uniform(
randGen_m);
2585 t = randNums[0] * flattopTime;
2587 double funcValue = (1.0 + modulationAmp
2591 allow = (randNums[1] <= funcValue);
2599 if (saveProcessor >= numNodes)
2602 if (scalable || myNode == saveProcessor) {
2609 for (
size_t partIndex = 0; partIndex < numRise; partIndex++) {
2625 if (saveProcessor >= numNodes)
2628 if (scalable || myNode == saveProcessor) {
2634 gsl_qrng_free(quasiRandGen1D);
2635 gsl_qrng_free(quasiRandGen2D);
2641 gsl_matrix * corMat = gsl_matrix_alloc (4, 4);
2642 gsl_vector * rx = gsl_vector_alloc(4);
2643 gsl_vector * ry = gsl_vector_alloc(4);
2645 for (
unsigned int i = 0; i < 4; ++ i) {
2647 for (
unsigned int j = 0; j < i; ++ j) {
2653 int errcode = gsl_linalg_cholesky_decomp(corMat);
2655 if (errcode == GSL_EDOM) {
2656 throw OpalException(
"Distribution::GenerateTransverseGauss",
2657 "gsl_linalg_cholesky_decomp failed");
2660 for (
int i = 0; i < 3; ++ i) {
2661 for (
int j = i+1; j < 4 ; ++ j) {
2662 gsl_matrix_set (corMat, i, j, 0.0);
2666 int saveProcessor = -1;
2671 for (
size_t partIndex = 0; partIndex < numberOfParticles; partIndex++) {
2681 gsl_vector_set(rx, 0, gsl_ran_gaussian (
randGen_m,1.0));
2682 gsl_vector_set(rx, 1, gsl_ran_gaussian (
randGen_m,1.0));
2683 gsl_vector_set(rx, 2, gsl_ran_gaussian (
randGen_m,1.0));
2684 gsl_vector_set(rx, 3, gsl_ran_gaussian (
randGen_m,1.0));
2686 gsl_blas_dgemv(CblasNoTrans, 1.0, corMat, rx, 0.0, ry);
2687 x = gsl_vector_get(ry, 0);
2688 px = gsl_vector_get(ry, 1);
2689 y = gsl_vector_get(ry, 2);
2690 py = gsl_vector_get(ry, 3);
2695 allow = (xAndYOk && pxAndPyOk);
2705 if (saveProcessor >= numNodes)
2708 if (scalable || myNode == saveProcessor) {
2716 gsl_matrix_free(corMat);
2717 gsl_vector_free(rx);
2718 gsl_vector_free(ry);
2740 bool hasID1 = !id1.empty();
2741 bool hasID2 = !id2.empty();
2743 if (hasID1 || hasID2)
2744 *
gmsg <<
"* Use special ID1 or ID2 particle in distribution" <<
endl;
2747 size_t numberOfParticles =
tOrZDist_m.size();
2748 beam->
create(numberOfParticles);
2749 for (
size_t partIndex = 0; partIndex < numberOfParticles; partIndex++) {
2765 beam->
TriID[partIndex] = 0;
2768 beam->
Bin[partIndex] = binNumber;
2771 beam->
Bin[partIndex] = 0;
2774 if (beam->
ID[partIndex] == 1) {
2775 beam->
R[partIndex] =
Vector_t(id1[0],id1[1],id1[2]);
2776 beam->
P[partIndex] =
Vector_t(id1[3],id1[4],id1[5]);
2781 if (beam->
ID[partIndex] == 2) {
2782 beam->
R[partIndex] =
Vector_t(id2[0],id2[1],id2[2]);
2783 beam->
P[partIndex] =
Vector_t(id2[3],id2[4],id2[5]);
2879 if (numberOfParticles > 0) {
2882 os <<
"* Number of particles: "
2888 os <<
"* Distribution input momentum units: ";
2891 os <<
"[Beta Gamma]" <<
"\n* " <<
endl;
2895 os <<
"[eV/c]" <<
"\n* " <<
endl;
2900 "Unknown \"INPUTMOUNITS\" for \"DISTRIBUTION\" command");
2926 "Unknown \"TYPE\" of \"DISTRIBUTION\"");
2933 os <<
"* Distribution type: BINOMIAL" <<
endl;
2938 os <<
"* SIGMAT = " <<
sigmaR_m[2] <<
" [sec]" <<
endl;
2941 os <<
"* SIGMAPX = " <<
sigmaP_m[0] <<
" [Beta Gamma]" <<
endl;
2942 os <<
"* SIGMAPY = " <<
sigmaP_m[1] <<
" [Beta Gamma]" <<
endl;
2943 os <<
"* SIGMAPZ = " <<
sigmaP_m[2] <<
" [Beta Gamma]" <<
endl;
2964 os <<
"* Distribution type: ASTRAFLATTOPTH" <<
endl;
2968 os <<
"* Distribution type: GUNGAUSSFLATTOPTH" <<
endl;
2972 os <<
"* Distribution type: FLATTOP" <<
endl;
2980 os <<
"* Transverse profile determined by laser image: " <<
endl
2997 os <<
"* Time Rise = " <<
tRise_m
2998 <<
" [sec]" <<
endl;
3000 <<
" [sec]" <<
endl;
3004 <<
" [sec]" <<
endl;
3006 <<
" [sec]" <<
endl;
3008 <<
" [sec]" <<
endl;
3009 os <<
"* Longitudinal cutoff = " <<
cutoffR_m[2]
3010 <<
" [units of Sigma Time]" <<
endl;
3011 os <<
"* Flat top modulation amplitude = "
3013 <<
" [Percent of distribution amplitude]" <<
endl;
3014 os <<
"* Flat top modulation periods = "
3026 os <<
"* Distribution type: MULTIGAUSS" <<
endl;
3033 std::string longUnits;
3035 longUnits =
" [sec]";
3039 os <<
"* SIGMAZ = " <<
sigmaR_m[2] << longUnits <<
endl;
3040 os <<
"* CUTOFFLONG = " <<
cutoffR_m[2] <<
" [units of SIGMAZ]" <<
endl;
3045 os <<
"* SIGMAPX = " <<
sigmaP_m[0] <<
" [Beta Gamma]" <<
endl;
3046 os <<
"* SIGMAPY = " <<
sigmaP_m[1] <<
" [Beta Gamma]" <<
endl;
3047 os <<
"* SIGMAPZ = " <<
sigmaP_m[2] <<
" [Beta Gamma]" <<
endl;
3048 os <<
"* CUTOFFPX = " <<
cutoffP_m[0] <<
" [units of SIGMAPX]" <<
endl;
3049 os <<
"* CUTOFFPY = " <<
cutoffP_m[1] <<
" [units of SIGMAPY]" <<
endl;
3050 os <<
"* CUTOFFPZ = " <<
cutoffP_m[2] <<
" [units of SIGMAPZ]" <<
endl;
3055 os <<
"* Distribution type: FROMFILE" <<
endl;
3057 os <<
"* Input file: '"
3063 os <<
"* Distribution type: MATCHEDGAUSS" <<
endl;
3067 os <<
"* SIGMAPX = " <<
sigmaP_m[0] <<
" [Beta Gamma]" <<
endl;
3068 os <<
"* SIGMAPY = " <<
sigmaP_m[1] <<
" [Beta Gamma]" <<
endl;
3069 os <<
"* SIGMAPZ = " <<
sigmaP_m[2] <<
" [Beta Gamma]" <<
endl;
3088 os <<
"* Distribution type: GAUSS" <<
endl;
3092 <<
" [sec]" <<
endl;
3094 <<
" [sec]" <<
endl;
3096 <<
" [sec]" <<
endl;
3097 os <<
"* Longitudinal cutoff = " <<
cutoffR_m[2]
3098 <<
" [units of Sigma Time]" <<
endl;
3099 os <<
"* Flat top modulation amplitude = "
3101 <<
" [Percent of distribution amplitude]" <<
endl;
3102 os <<
"* Flat top modulation periods = "
3107 os <<
"* SIGMAPX = " <<
sigmaP_m[0]
3108 <<
" [Beta Gamma]" <<
endl;
3109 os <<
"* SIGMAPY = " <<
sigmaP_m[1]
3110 <<
" [Beta Gamma]" <<
endl;
3114 <<
" [units of SIGMAX]" <<
endl;
3116 <<
" [units of SIGMAY]" <<
endl;
3118 <<
" [units of SIGMAPX]" <<
endl;
3120 <<
" [units of SIGMAPY]" <<
endl;
3125 os <<
"* SIGMAPX = " <<
sigmaP_m[0] <<
" [Beta Gamma]" <<
endl;
3126 os <<
"* SIGMAPY = " <<
sigmaP_m[1] <<
" [Beta Gamma]" <<
endl;
3127 os <<
"* SIGMAPZ = " <<
sigmaP_m[2] <<
" [Beta Gamma]" <<
endl;
3128 os <<
"* AVRGPZ = " <<
avrgpz_m <<
" [Beta Gamma]" <<
endl;
3137 os <<
"* CUTOFFX = " <<
cutoffR_m[0] <<
" [units of SIGMAX]" <<
endl;
3138 os <<
"* CUTOFFY = " <<
cutoffR_m[1] <<
" [units of SIGMAY]" <<
endl;
3139 os <<
"* CUTOFFLONG = " <<
cutoffR_m[2] <<
" [units of SIGMAZ]" <<
endl;
3140 os <<
"* CUTOFFPX = " <<
cutoffP_m[0] <<
" [units of SIGMAPX]" <<
endl;
3141 os <<
"* CUTOFFPY = " <<
cutoffP_m[1] <<
" [units of SIGMAPY]" <<
endl;
3142 os <<
"* CUTOFFPZ = " <<
cutoffP_m[2] <<
" [units of SIGMAPY]" <<
endl;
3148 os <<
"* ------------- THERMAL EMITTANCE MODEL --------------------------------------------" <<
endl;
3165 os <<
"* ----------------------------------------------------------------------------------" <<
endl;
3170 os <<
"* THERMAL EMITTANCE in ASTRA MODE" <<
endl;
3171 os <<
"* Kinetic energy (thermal emittance) = "
3173 <<
" [eV] " <<
endl;
3177 os <<
"* THERMAL EMITTANCE in NONE MODE" <<
endl;
3178 os <<
"* Kinetic energy added to longitudinal momentum = "
3180 <<
" [eV] " <<
endl;
3184 os <<
"* THERMAL EMITTANCE in NONEQUIL MODE" <<
endl;
3201 <<
" contains " <<
sum <<
" particles" <<
endl;
3226 for (
size_t partIndex = 0; partIndex < currentNumPart; partIndex++) {
3239 (numberOfParticles + 1) / 2 != numberOfParticles / 2) {
3261 for (
size_t particleIndex = 0; particleIndex <
tOrZDist_m.size(); ++ particleIndex) {
3262 xDist_m.at(particleIndex) *= xmult;
3263 pxDist_m.at(particleIndex) *= pxmult;
3264 yDist_m.at(particleIndex) *= ymult;
3265 pyDist_m.at(particleIndex) *= pymult;
3267 pzDist_m.at(particleIndex) *= pzmult;
3273 gsl_qrng *quasiRandGen =
nullptr;
3277 quasiRandGen = gsl_qrng_alloc(gsl_qrng_halton, dimension);
3279 quasiRandGen = gsl_qrng_alloc(gsl_qrng_sobol, dimension);
3281 quasiRandGen = gsl_qrng_alloc(gsl_qrng_niederreiter_2, dimension);
3284 quasiRandGen = gsl_qrng_alloc(gsl_qrng_halton, dimension);
3287 return quasiRandGen;
3298 "GUNGAUSSFLATTOPTH",
3306 =
Attributes::makeReal(
"EX",
"Projected normalized emittance EX (m-rad), used to create matched distribution ", 1E-6);
3308 =
Attributes::makeReal(
"EY",
"Projected normalized emittance EY (m-rad) used to create matched distribution ", 1E-6);
3310 =
Attributes::makeReal(
"ET",
"Projected normalized emittance ET (m-rad) used to create matched distribution ", 1E-6);
3314 =
Attributes::makeReal(
"RESIDUUM",
"Residuum for the closed orbit finder and sigma matrix generator ", 1
e-8);
3323 " (false: using all sectors) (default: true)",
3326 =
Attributes::makeReal(
"NSTEPS",
"Number of integration steps of closed orbit finder (matched gauss)"
3327 " (default: 720)", 720);
3336 =
Attributes::makeReal(
"NSECTORS",
"Number of sectors to average field, for closed orbit finder ", 1);
3340 "coordinates.",
"");
3349 "distribution list.", 1.0);
3357 "an injected beam.",
false);
3364 {
"NONE",
"ASTRA",
"NONEQUIL"},
"NONE");
3367 "model (eV). (Thermal energy added in with random "
3368 "number generator.)", 1.0);
3371 "emission. (Default 255 nm light.)", 4.86);
3374 " (Default atomically clean copper.)", 4.31);
3377 " (Default atomically clean copper.)", 7.0);
3380 " (Default 300 K.)", 300.0);
3383 "charge solve.", 0.0);
3429 "Gaussian peaks in MultiGauss "
3430 "distribution.", 0.0);
3432 " pulses in MultiGauss "
3433 "distribution.", 0.0);
3436 "0.0 ... infinity.", 10001.0);
3439 "0.0 ... infinity.", 10001.0);
3442 "0.0 ... infinity.", 10001.0);
3445 "0.0 ... infinity.", 10001.0);
3448 "direction in units of sigma.", 3.0);
3450 "direction in units of sigma.", 3.0);
3452 "direction in units of sigma.", 3.0);
3455 "units of sigma.", 3.0);
3457 "dimension in units of sigma.", 3.0);
3459 "dimension in units of sigma.", 3.0);
3461 "dimension in units of sigma.", 3.0);
3465 "on flat top portion of emitted GAUSS "
3466 "distribtuion (in percent of flat top "
3470 "flat top portion of emitted GAUSS "
3471 "distribution", 0.0);
3510 "profile (x,y).",
"");
3515 "image profile, in % of max intensity.",
3522 =
Attributes::makeBool(
"ROTATE90",
"Rotate laser profile 90 degrees counter clockwise",
false);
3524 =
Attributes::makeBool(
"ROTATE180",
"Rotate laser profile 180 degrees counter clockwise",
false);
3526 =
Attributes::makeBool(
"ROTATE270",
"Rotate laser profile 270 degrees counter clockwise",
false);
3540 "respect of number of particles and number of cores",
false);
3554 "when emitting a distribution.", 100.0);
3604 "The attribute \"DISTRIBUTION\" isn't supported any more, use \"TYPE\" instead");
3607 static const std::map<std::string, DistributionType> typeStringToDistType_s = {
3622 "The attribute \"TYPE\" isn't set for the \"DISTRIBUTION\"!");
3650 WARNMSG(
"The attribute SIGMAPT may be removed in a future version\n"
3651 <<
"use SIGMAPZ instead" <<
endl);
3688 double deltaT = maxT - minT;
3702 double deltaT = maxT - minT;
3719 throw OpalException(
"Distribution::setDistParametersBinomial",
3720 "Attribute R is not supported for binomial distribution\n"
3721 "use CORR[X|Y|Z] and R51, R52, R61, R62 instead");
3882 if (cr.size() == 15) {
3883 *
gmsg <<
"* Use r to specify correlations" <<
endl;
3885 for (
unsigned int i = 0; i < 5; ++ i) {
3886 for (
unsigned int j = i + 1; j < 6; ++ j, ++ k) {
3894 "Inconsistent set of correlations specified, check manual");
3948 for (
int i=0; i<3; i++) {
3958 static const std::map<std::string, EmissionModel> stringEmissionModel_s = {
3965 if (model.empty()) {
4007 size_t numParticles =
pzDist_m.size();
4010 avgPz /= numParticles;
4057 "PT is obsolete. The moments of the beam is defined with OFFSETPZ");
4060 const double pz = beam->
getP()/beam->
getM();
4061 double gamma = std::hypot(pz, 1.0);
4106 double avgZ[] = {0.0, 1.0 *
tOrZDist_m.size()};
4127 size_t startIdx = 0;
4142 "Attribute T isn't supported anymore; use OFFSETZ instead");
4145 double deltaTOrZ = 0.0;
4155 WARNMSG(
"PT & PZ are obsolete and will be ignored. The moments of the beam is defined with PC" <<
endl);
4165 for (
size_t particleIndex = startIdx; particleIndex < endIdx; ++ particleIndex) {
4166 xDist_m.at(particleIndex) += deltaX;
4167 pxDist_m.at(particleIndex) += deltaPx;
4168 yDist_m.at(particleIndex) += deltaY;
4169 pyDist_m.at(particleIndex) += deltaPy;
4171 pzDist_m.at(particleIndex) += deltaPz;
4195 if (outputFile.bad()) {
4198 outputFile.
setf(std::ios::left);
4200 outputFile.width(17);
4201 outputFile <<
"x [m]";
4202 outputFile.width(17);
4203 outputFile <<
"px [betax gamma]";
4204 outputFile.width(17);
4205 outputFile <<
"y [m]";
4206 outputFile.width(17);
4207 outputFile <<
"py [betay gamma]";
4209 outputFile.width(17);
4210 outputFile <<
"t [s]";
4212 outputFile.width(17);
4213 outputFile <<
"z [m]";
4215 outputFile.width(17);
4216 outputFile <<
"pz [betaz gamma]" ;
4218 outputFile.width(17);
4219 outputFile <<
"Bin Number" <<
std::endl;
4222 outputFile.
width(17);
4223 outputFile <<
"Bin Number";
4227 outputFile <<
"# " << totalNum <<
std::endl;
4248 std::vector<char> msgbuf;
4249 const size_t bitsPerParticle = (6 *
sizeof(double) +
sizeof(
size_t));
4250 size_t totalSendBits =
xWrite_m.size() * bitsPerParticle;
4264 if (totalSendBits > 0) {
4265 msgbuf.reserve(totalSendBits);
4267 for (
size_t idx = 0; idx <
xWrite_m.size(); ++ idx) {
4268 buffer =
reinterpret_cast<const char*
>(&(
xWrite_m[idx]));
4269 msgbuf.insert(msgbuf.end(), buffer, buffer +
sizeof(double));
4270 buffer =
reinterpret_cast<const char*
>(&(
pxWrite_m[idx]));
4271 msgbuf.insert(msgbuf.end(), buffer, buffer +
sizeof(double));
4272 buffer =
reinterpret_cast<const char*
>(&(
yWrite_m[idx]));
4273 msgbuf.insert(msgbuf.end(), buffer, buffer +
sizeof(double));
4274 buffer =
reinterpret_cast<const char*
>(&(
pyWrite_m[idx]));
4275 msgbuf.insert(msgbuf.end(), buffer, buffer +
sizeof(double));
4276 buffer =
reinterpret_cast<const char*
>(&(
tOrZWrite_m[idx]));
4277 msgbuf.insert(msgbuf.end(), buffer, buffer +
sizeof(double));
4278 buffer =
reinterpret_cast<const char*
>(&(
pzWrite_m[idx]));
4279 msgbuf.insert(msgbuf.end(), buffer, buffer +
sizeof(double));
4280 buffer =
reinterpret_cast<const char*
>(&(
binWrite_m[idx]));
4281 msgbuf.insert(msgbuf.end(), buffer, buffer +
sizeof(size_t));
4288 if (outputFile.bad()) {
4291 if (numberOfBits[node] == 0)
continue;
4292 char *recvbuf =
new char[numberOfBits[node]];
4298 outputFile.precision(9);
4299 outputFile.setf(std::ios::scientific);
4300 outputFile.setf(std::ios::right);
4302 for (
size_t partIndex = 0; partIndex <
xWrite_m.size(); partIndex++) {
4304 outputFile << std::setw(17) <<
xWrite_m.at(partIndex)
4305 << std::setw(17) <<
pxWrite_m.at(partIndex)
4306 << std::setw(17) <<
yWrite_m.at(partIndex)
4307 << std::setw(17) <<
pyWrite_m.at(partIndex)
4309 << std::setw(17) <<
pzWrite_m.at(partIndex)
4315 if (numberOfBits[i] > 0) numSenders ++;
4318 for (
int i = 0; i < numSenders; ++ i) {
4324 while (j < bufsize) {
4325 const double *dbuffer =
reinterpret_cast<const double*
>(recvbuf + j);
4326 const size_t *sbuffer =
reinterpret_cast<const size_t*
>(recvbuf + j + 6 *
sizeof(double));
4327 outputFile << std::setw(17) << dbuffer[0]
4328 << std::setw(17) << dbuffer[1]
4329 << std::setw(17) << dbuffer[2]
4330 << std::setw(17) << dbuffer[3]
4331 << std::setw(17) << dbuffer[4]
4332 << std::setw(17) << dbuffer[5]
4333 << std::setw(17) << sbuffer[0]
4335 j += bitsPerParticle;
4363 for (
int nodeIndex = 0; nodeIndex <
Ippl::getNodes(); nodeIndex++) {
4366 size_t numberOfParticles = 0;
4369 if (outputFile.bad()) {
4375 outputFile.setf(std::ios::scientific);
4376 outputFile.setf(std::ios::right);
4379 for (
size_t partIndex = 0; partIndex < numberOfParticles; partIndex++) {
4381 outputFile.width(17);
4382 outputFile <<
xDist_m.at(partIndex);
4383 outputFile.width(17);
4384 outputFile <<
pxDist_m.at(partIndex);
4385 outputFile.width(17);
4386 outputFile <<
yDist_m.at(partIndex);
4387 outputFile.width(17);
4388 outputFile <<
pyDist_m.at(partIndex);
4389 outputFile.width(17);
4391 outputFile.width(17);
4392 outputFile <<
pzDist_m.at(partIndex);
4395 outputFile.width(17);
4396 outputFile << binNumber;
4437 for (
unsigned int i = 0; i <
pzDist_m.size(); ++ i) {
4443 allreduce(&(avrg[0]), 6, std::plus<double>());
4449 for (
unsigned int i = 0; i <
pzDist_m.size(); ++ i) {
PartBunchBase< T, Dim >::ConstIterator end(PartBunchBase< T, Dim > const &bunch)
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.
constexpr double SMALLESTCUTOFF
void allreduce(const T *input, T *output, int count, Op op)
bool reduce(Communicate &, InputIterator, InputIterator, OutputIterator, const ReduceOp &, bool *IncludeVal=0)
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)
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)
PETE_TBTree< FnCopysign, PETE_Scalar< Vektor< T1, Dim > >, typename T2::PETE_Expr_t > copysign(const Vektor< T1, Dim > &l, const PETE_Expr< T2 > &r)
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)
Inform & level2(Inform &inf)
Inform & endl(Inform &inf)
Inform & level1(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.
constexpr double rad2mrad
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::string outFilename_m
std::vector< double > tOrZDist_m
double tPulseLengthFWHM_m
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
List of Distribution types.
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 createOpalT(PartBunchBase< double, 3 > *beam, std::vector< Distribution * > addedDistributions, size_t &numberOfParticles)
void generateAstraFlattopT(size_t numberOfParticles)
size_t getNumberOfParticlesInFile(std::ifstream &inputFile)
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
DistributionType distrTypeT_m
Distribution type strings.
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)
void chooseInputMomentumUnits(InputMomentumUnits inputMoUnits)
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
InputMomentumUnits inputMoUnits_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
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)
EmissionModel emissionModel_m
Emission Model.
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