diff --git a/src/Distribution/Distribution.cpp b/src/Distribution/Distribution.cpp index f4c0fa98e29b27e4c1a9acd44fe50050f44af0ce..557943c2fe57836c3560298ce895738c5f55e2b6 100644 --- a/src/Distribution/Distribution.cpp +++ b/src/Distribution/Distribution.cpp @@ -24,7 +24,6 @@ #include <numeric> #include "AbstractObjects/Expressions.h" -#include "Attributes/Attributes.h" #include "Utilities/Options.h" #include "AbstractObjects/OpalData.h" #include "Algorithms/PartBunch.h" @@ -237,7 +236,7 @@ Distribution::Distribution(const std::string &name, Distribution *parent): Distribution::~Distribution() { - if((Ippl::getNodes() == 1) && (os_m.is_open())) + if ((Ippl::getNodes() == 1) && (os_m.is_open())) os_m.close(); if (energyBins_m != NULL) { @@ -255,7 +254,7 @@ Distribution::~Distribution() { randGen_m = NULL; } - if(laserProfile_m) { + if (laserProfile_m) { delete laserProfile_m; laserProfile_m = NULL; } @@ -263,8 +262,8 @@ Distribution::~Distribution() { } /* void Distribution::printSigma(SigmaGenerator<double,unsigned int>::matrix_type& M, Inform& out) { - for(int i=0; i<M.size1(); ++i) { - for(int j=0; j<M.size2(); ++j) { + for (int i=0; i<M.size1(); ++i) { + for (int j=0; j<M.size2(); ++j) { *gmsg << M(i,j) << " "; } *gmsg << endl; @@ -304,14 +303,14 @@ size_t Distribution::getNumOfLocalParticlesToCreate(size_t n) { */ void Distribution::writeToFile() { /* - if(Ippl::getNodes() == 1) { - if(os_m.is_open()) { + if (Ippl::getNodes() == 1) { + if (os_m.is_open()) { ; } else { *gmsg << " Write distribution to file data/dist.dat" << endl; std::string file("data/dist.dat"); os_m.open(file.c_str()); - if(os_m.bad()) { + if (os_m.bad()) { *gmsg << "Unable to open output file " << file << endl; } os_m << "# x y ti px py pz " << std::endl; @@ -460,7 +459,7 @@ void Distribution::create(size_t &numberOfParticles, double massIneV) { void Distribution::createPriPart(PartBunch *beam, BoundaryGeometry &bg) { - if(Options::ppdebug) { // This is Parallel Plate Benchmark. + if (Options::ppdebug) { // This is Parallel Plate Benchmark. int pc = 0; size_t lowMark = beam->getLocalNum(); double vw = this->getVw(); @@ -471,20 +470,20 @@ void Distribution::createPriPart(PartBunch *beam, BoundaryGeometry &bg) { size_t count = 0; size_t N_mean = static_cast<size_t>(floor(bg.getN() / Ippl::getNodes())); size_t N_extra = static_cast<size_t>(bg.getN() - N_mean * Ippl::getNodes()); - if(Ippl::myNode() == 0) + if (Ippl::myNode() == 0) N_mean += N_extra; - if(bg.getN() != 0) { - for(size_t i = 0; i < bg.getN(); i++) { - if(pc == Ippl::myNode()) { - if(count < N_mean) { + if (bg.getN() != 0) { + for (size_t i = 0; i < bg.getN(); i++) { + if (pc == Ippl::myNode()) { + if (count < N_mean) { /*==============Parallel Plate Benchmark=====================================*/ double test_s = 1; double f_x = 0; double test_x = 0; while(test_s > f_x) { - test_s = IpplRandom(); + test_s = gsl_rng_uniform(randGen_m); test_s *= f_max; - test_x = IpplRandom(); + test_x = gsl_rng_uniform(randGen_m); test_x *= 10 * test_a; //range for normalized emission speed(0,10*test_a); f_x = test_x / test_asq * exp(-test_x * test_x / 2 / test_asq); } @@ -494,7 +493,7 @@ void Distribution::createPriPart(PartBunch *beam, BoundaryGeometry &bg) { double betagamma = betaemit / sqrt(1 - betaemit * betaemit); /*============================================================================ */ beam->create(1); - if(pc != 0) { + if (pc != 0) { beam->R[lowMark + count] = bg.getCooridinate(Ippl::myNode() * N_mean + count + N_extra); beam->P[lowMark + count] = betagamma * bg.getMomenta(Ippl::myNode() * N_mean + count); } else { @@ -512,7 +511,7 @@ void Distribution::createPriPart(PartBunch *beam, BoundaryGeometry &bg) { } } pc++; - if(pc == Ippl::getNodes()) + if (pc == Ippl::getNodes()) pc = 0; } bg.clearCooridinateArray(); @@ -529,15 +528,15 @@ void Distribution::createPriPart(PartBunch *beam, BoundaryGeometry &bg) { size_t N_mean = static_cast<size_t>(floor(bg.getN() / Ippl::getNodes())); size_t N_extra = static_cast<size_t>(bg.getN() - N_mean * Ippl::getNodes()); - if(Ippl::myNode() == 0) + if (Ippl::myNode() == 0) N_mean += N_extra; - if(bg.getN() != 0) { - for(size_t i = 0; i < bg.getN(); i++) { + if (bg.getN() != 0) { + for (size_t i = 0; i < bg.getN(); i++) { - if(pc == Ippl::myNode()) { - if(count < N_mean) { + if (pc == Ippl::myNode()) { + if (count < N_mean) { beam->create(1); - if(pc != 0) + if (pc != 0) beam->R[lowMark + count] = bg.getCooridinate(Ippl::myNode() * N_mean + count + N_extra); // node 0 will emit the particle with coordinate ID from 0 to N_mean+N_extra, so other nodes should shift to node_number*N_mean+N_extra else beam->R[lowMark + count] = bg.getCooridinate(count); // for node0 the particle number N_mean = N_mean + N_extra @@ -555,7 +554,7 @@ void Distribution::createPriPart(PartBunch *beam, BoundaryGeometry &bg) { } pc++; - if(pc == Ippl::getNodes()) + if (pc == Ippl::getNodes()) pc = 0; } @@ -645,9 +644,9 @@ void Distribution::doRestartOpalCycl(PartBunch &beam, INFOMSG("* Gamma = " << gamma << ", Beta = " << beta << endl); - if(dataSource->predecessorIsSameFlavour()) { + if (dataSource->predecessorIsSameFlavour()) { INFOMSG("Restart from hdf5 file generated by OPAL-cycl" << endl); - if(specifiedNumBunch > 1) { + if (specifiedNumBunch > 1) { // the allowed maximal bin number is set to 1000 energyBins_m = new PartBinsCyc(1000, beam.getNumBunch()); beam.setPBins(energyBins_m); @@ -659,8 +658,8 @@ void Distribution::doRestartOpalCycl(PartBunch &beam, Vector_t meanR(0.0, 0.0, 0.0); Vector_t meanP(0.0, 0.0, 0.0); unsigned long int newLocalN = beam.getLocalNum(); - for(unsigned int i = 0; i < newLocalN; ++i) { - for(int d = 0; d < 3; ++d) { + for (unsigned int i = 0; i < newLocalN; ++i) { + for (int d = 0; d < 3; ++d) { meanR(d) += beam.R[i](d); meanP(d) += beam.P[i](d); } @@ -671,7 +670,7 @@ void Distribution::doRestartOpalCycl(PartBunch &beam, meanP /= Vector_t(globalN); INFOMSG("Rmean = " << meanR << "[m], Pmean=" << meanP << endl); - for(unsigned int i = 0; i < newLocalN; ++i) { + for (unsigned int i = 0; i < newLocalN; ++i) { beam.R[i] -= meanR; beam.P[i] -= meanP; } @@ -702,7 +701,7 @@ void Distribution::doRestartOpalE(EnvelopeBunch &beam, size_t Np, int restartSte Distribution *Distribution::find(const std::string &name) { Distribution *dist = dynamic_cast<Distribution *>(OpalData::getInstance()->find(name)); - if(dist == 0) { + if (dist == 0) { throw OpalException("Distribution::find()", "Distribution \"" + name + "\" not found."); } @@ -710,7 +709,7 @@ Distribution *Distribution::find(const std::string &name) { } double Distribution::getTEmission() { - if(tEmission_m > 0.0) { + if (tEmission_m > 0.0) { return tEmission_m; } @@ -733,7 +732,7 @@ double Distribution::getTEmission() { double t = a - sqr2 * sig * inv_erf08; double tmps = sig; double tmpt = t; - for(int i = 0; i < 10; ++ i) { + for (int i = 0; i < 10; ++ i) { sig = (t + tRise_m - a) / (sqr2 * inv_erf08); t = a - 0.5 * sqr2 * (sig + tmps) * inv_erf08; sig = (0.5 * (t + tmpt) + tRise_m - a) / (sqr2 * inv_erf08); @@ -753,38 +752,6 @@ double Distribution::getTEmission() { return tEmission_m; } -double Distribution::getEkin() const {return Attributes::getReal(itsAttr[Attrib::Distribution::EKIN]);} -double Distribution::getLaserEnergy() const {return Attributes::getReal(itsAttr[Attrib::Distribution::ELASER]);} -double Distribution::getWorkFunctionRf() const {return Attributes::getReal(itsAttr[Attrib::Distribution::W]);} - -size_t Distribution::getNumberOfDarkCurrentParticles() { return (size_t) Attributes::getReal(itsAttr[Attrib::Distribution::NPDARKCUR]);} -double Distribution::getDarkCurrentParticlesInwardMargin() { return Attributes::getReal(itsAttr[Attrib::Distribution::INWARDMARGIN]);} -double Distribution::getEInitThreshold() { return Attributes::getReal(itsAttr[Attrib::Distribution::EINITHR]);} -double Distribution::getWorkFunction() { return Attributes::getReal(itsAttr[Attrib::Distribution::FNPHIW]); } -double Distribution::getFieldEnhancement() { return Attributes::getReal(itsAttr[Attrib::Distribution::FNBETA]); } -size_t Distribution::getMaxFNemissionPartPerTri() { return (size_t) Attributes::getReal(itsAttr[Attrib::Distribution::FNMAXEMI]);} -double Distribution::getFieldFNThreshold() { return Attributes::getReal(itsAttr[Attrib::Distribution::FNFIELDTHR]);} -double Distribution::getFNParameterA() { return Attributes::getReal(itsAttr[Attrib::Distribution::FNA]);} -double Distribution::getFNParameterB() { return Attributes::getReal(itsAttr[Attrib::Distribution::FNB]);} -double Distribution::getFNParameterY() { return Attributes::getReal(itsAttr[Attrib::Distribution::FNY]);} -double Distribution::getFNParameterVYZero() { return Attributes::getReal(itsAttr[Attrib::Distribution::FNVYZERO]);} -double Distribution::getFNParameterVYSecond() { return Attributes::getReal(itsAttr[Attrib::Distribution::FNVYSECOND]);} -int Distribution::getSecondaryEmissionFlag() { return Attributes::getReal(itsAttr[Attrib::Distribution::SECONDARYFLAG]);} -bool Distribution::getEmissionMode() { return Attributes::getBool(itsAttr[Attrib::Distribution::NEMISSIONMODE]);} - -std::string Distribution::getTypeofDistribution() { return (std::string) Attributes::getString(itsAttr[Attrib::Distribution::TYPE]);} - -double Distribution::getvSeyZero() {return Attributes::getReal(itsAttr[Attrib::Distribution::VSEYZERO]);}// return sey_0 in Vaughan's model -double Distribution::getvEZero() {return Attributes::getReal(itsAttr[Attrib::Distribution::VEZERO]);}// return the energy related to sey_0 in Vaughan's model -double Distribution::getvSeyMax() {return Attributes::getReal(itsAttr[Attrib::Distribution::VSEYMAX]);}// return sey max in Vaughan's model -double Distribution::getvEmax() {return Attributes::getReal(itsAttr[Attrib::Distribution::VEMAX]);}// return Emax in Vaughan's model -double Distribution::getvKenergy() {return Attributes::getReal(itsAttr[Attrib::Distribution::VKENERGY]);}// return fitting parameter denotes the roughness of surface for impact energy in Vaughan's model -double Distribution::getvKtheta() {return Attributes::getReal(itsAttr[Attrib::Distribution::VKTHETA]);}// return fitting parameter denotes the roughness of surface for impact angle in Vaughan's model -double Distribution::getvVThermal() {return Attributes::getReal(itsAttr[Attrib::Distribution::VVTHERMAL]);}// thermal velocity of Maxwellian distribution of secondaries in Vaughan's model -double Distribution::getVw() {return Attributes::getReal(itsAttr[Attrib::Distribution::VW]);}// velocity scalar for parallel plate benchmark; - -int Distribution::getSurfMaterial() {return (int)Attributes::getReal(itsAttr[Attrib::Distribution::SURFMATERIAL]);}// Surface material number for Furman-Pivi's Model; - Inform &Distribution::printInfo(Inform &os) const { os << "* ************* D I S T R I B U T I O N ********************************************" << endl; @@ -1428,7 +1395,7 @@ void Distribution::createMatchedGaussDistribution(size_t numberOfParticles, doub Attributes::getReal(itsAttr[Attrib::Distribution::ORDERMAPS]), writeMap); - if(siggen->match(Attributes::getReal(itsAttr[Attrib::Distribution::RESIDUUM]), + if (siggen->match(Attributes::getReal(itsAttr[Attrib::Distribution::RESIDUUM]), Attributes::getReal(itsAttr[Attrib::Distribution::MAXSTEPSSI]), Attributes::getReal(itsAttr[Attrib::Distribution::MAXSTEPSCO]), CyclotronElement->getPHIinit(), @@ -1445,9 +1412,9 @@ void Distribution::createMatchedGaussDistribution(size_t numberOfParticles, doub << Emit[2] << ") pi mm mrad for E= " << E_m*1E-6 << " (MeV)" << endl; *gmsg << "* Sigma-Matrix " << endl; - for(unsigned int i = 0; i < siggen->getSigma().size1(); ++ i) { + for (unsigned int i = 0; i < siggen->getSigma().size1(); ++ i) { *gmsg << std::setprecision(4) << std::setw(11) << siggen->getSigma()(i,0); - for(unsigned int j = 1; j < siggen->getSigma().size2(); ++ j) { + for (unsigned int j = 1; j < siggen->getSigma().size2(); ++ j) { *gmsg << " & " << std::setprecision(4) << std::setw(11) << siggen->getSigma()(i,j); } *gmsg << " \\\\" << endl; @@ -1463,7 +1430,7 @@ void Distribution::createMatchedGaussDistribution(size_t numberOfParticles, doub */ - if(Options::cloTuneOnly) + if (Options::cloTuneOnly) throw OpalException("Do only CLO and tune calculation","... "); @@ -1538,17 +1505,17 @@ void Distribution::createBoundaryGeometry(PartBunch &beam, BoundaryGeometry &bg int pc = 0; size_t N_mean = static_cast<size_t>(floor(bg.getN() / Ippl::getNodes())); size_t N_extra = static_cast<size_t>(bg.getN() - N_mean * Ippl::getNodes()); - if(Ippl::myNode() == 0) + if (Ippl::myNode() == 0) N_mean += N_extra; size_t count = 0; size_t lowMark = beam.getLocalNum(); - if(bg.getN() != 0) { + if (bg.getN() != 0) { - for(size_t i = 0; i < bg.getN(); i++) { - if(pc == Ippl::myNode()) { - if(count < N_mean) { + for (size_t i = 0; i < bg.getN(); i++) { + if (pc == Ippl::myNode()) { + if (count < N_mean) { beam.create(1); - if(pc != 0) + if (pc != 0) beam.R[lowMark + count] = bg.getCooridinate(Ippl::myNode() * N_mean + count + N_extra); else beam.R[lowMark + count] = bg.getCooridinate(count); @@ -1564,7 +1531,7 @@ void Distribution::createBoundaryGeometry(PartBunch &beam, BoundaryGeometry &bg } } pc++; - if(pc == Ippl::getNodes()) + if (pc == Ippl::getNodes()) pc = 0; } } @@ -2187,7 +2154,7 @@ void Distribution::generateAstraFlattopT(size_t numberOfParticles) { double tmps = sig; double tmpt = t; - for(int i = 0; i < 10; ++ i) { + for (int i = 0; i < 10; ++ i) { sig = (t + tRise_m - a) / (sqr2 * inv_erf08); t = a - 0.5 * sqr2 * (sig + tmps) * inv_erf08; sig = (0.5 * (t + tmpt) + tRise_m - a) / (sqr2 * inv_erf08); @@ -2210,7 +2177,7 @@ void Distribution::generateAstraFlattopT(size_t numberOfParticles) { double weight = 2.0; // sample the function that describes the histogram of the requested distribution - for(int i = 0; i < binTotal + 1; ++ i, x += dx, weight = 6. - weight) { + for (int i = 0; i < binTotal + 1; ++ i, x += dx, weight = 6. - weight) { distributionTable[i] = gsl_sf_erf((x + a) / (sqrt(2) * sig)) - gsl_sf_erf((x - a) / (sqrt(2) * sig)); tot += distributionTable[i] * weight; } @@ -2226,11 +2193,11 @@ void Distribution::generateAstraFlattopT(size_t numberOfParticles) { int effectiveNumParticles = 0; int largestBin = 0; std::vector<int> numParticlesInBin(numberOfEnergyBins,0); - for(int k = 0; k < numberOfEnergyBins; ++ k) { + for (int k = 0; k < numberOfEnergyBins; ++ k) { double loc_fraction = -distributionTable[numberOfSampleBins * k] / tot; weight = 2.0; - for(int i = numberOfSampleBins * k; i < numberOfSampleBins * (k + 1) + 1; + for (int i = numberOfSampleBins * k; i < numberOfSampleBins * (k + 1) + 1; ++ i, weight = 6. - weight) { loc_fraction += distributionTable[i] * weight / tot; } @@ -2243,12 +2210,12 @@ void Distribution::generateAstraFlattopT(size_t numberOfParticles) { numParticlesInBin[largestBin] += (numberOfParticles - effectiveNumParticles); - for(int k = 0; k < numberOfEnergyBins; ++ k) { + for (int k = 0; k < numberOfEnergyBins; ++ k) { gsl_ran_discrete_t *table = gsl_ran_discrete_preproc(numberOfSampleBins, &(distributionTable[numberOfSampleBins * k])); - for(int i = 0; i < numParticlesInBin[k]; i++) { + for (int i = 0; i < numParticlesInBin[k]; i++) { double xx[2]; gsl_qrng_get(quasiRandGen, xx); tCoord = hi * (xx[1] + static_cast<int>(gsl_ran_discrete(randGen_m, table)) @@ -2299,9 +2266,7 @@ void Distribution::generateBinomial(size_t numberOfParticles) { * cos(asin(correlationMatrix_m(2 * index + 1, 2 * index))); } - Vector_t beta; - Vector_t gamma; - Vector_t alpha; + Vector_t alpha, beta, gamma; for (unsigned int index = 0; index < 3; index++) { beta(index) = pow(sigmaR_m[index], 2.0) / emittance(index); gamma(index) = pow(sigmaP_m[index], 2.0) / emittance(index); @@ -2309,26 +2274,31 @@ void Distribution::generateBinomial(size_t numberOfParticles) { * sqrt(beta(index) * gamma(index)); } - Vector_t M = Vector_t(0.0); - Vector_t PM = Vector_t(0.0); - Vector_t COSCHI = Vector_t(0.0); - Vector_t SINCHI = Vector_t(0.0); - Vector_t CHI = Vector_t(0.0); - Vector_t AMI = Vector_t(0.0); - Vector_t L = Vector_t(0.0); - Vector_t PL = Vector_t(0.0); - - for(unsigned int index = 0; index < 3; index++) { - gamma(index) *= cutoffR_m[index]; - beta(index) *= cutoffP_m[index]; - M[index] = sqrt(emittance(index) * beta(index)); - PM[index] = sqrt(emittance(index) * gamma(index)); + Vector_t M, PM, L, PL, X, PX; + Vector_t CHI, COSCHI, SINCHI(0.0); + Vector_t AMI; + Vektor<BinomialBehaviorSplitter*, 3> splitter; + for (unsigned int index = 0; index < 3; index++) { + // gamma(index) *= cutoffR_m[index]; + // beta(index) *= cutoffP_m[index]; COSCHI[index] = sqrt(1.0 / (1.0 + pow(alpha(index), 2.0))); SINCHI[index] = -alpha(index) * COSCHI[index]; CHI[index] = atan2(SINCHI[index], COSCHI[index]); AMI[index] = 1.0 / mBinomial_m[index]; + M[index] = sqrt(emittance(index) * beta(index)); + PM[index] = sqrt(emittance(index) * gamma(index)); L[index] = sqrt((mBinomial_m[index] + 1.0) / 2.0) * M[index]; PL[index] = sqrt((mBinomial_m[index] + 1.0) / 2.0) * PM[index]; + + if (mBinomial_m[index] < 10000) { + X[index] = L[index]; + PX[index] = PL[index]; + splitter[index] = new MDependentBehavior(mBinomial_m[index]); + } else { + X[index] = M[index]; + PX[index] = PM[index]; + splitter[index] = new GaussianLikeBehavior(); + } } int saveProcessor = -1; @@ -2336,102 +2306,49 @@ void Distribution::generateBinomial(size_t numberOfParticles) { const int numNodes = Ippl::getNodes(); const bool scalable = Attributes::getBool(itsAttr[Attrib::Distribution::SCALABLE]); + double temp = 1.0 - std::pow(correlationMatrix_m(1, 0), 2.0); + const double tempa = copysign(sqrt(std::abs(temp)), temp); + const double l32 = (correlationMatrix_m(4, 1) - + correlationMatrix_m(1, 0) * correlationMatrix_m(4, 0)) / tempa; + temp = 1 - std::pow(correlationMatrix_m(4, 0), 2.0) - l32 * l32; + const double l33 = copysign(sqrt(std::abs(temp)), temp); + + const double l42 = (correlationMatrix_m(5, 1) - + correlationMatrix_m(1, 0) * correlationMatrix_m(5, 0)) / tempa; + const double l43 = (correlationMatrix_m(5, 4) - + correlationMatrix_m(4, 0) * correlationMatrix_m(5, 0) - l42 * l32) / l33; + temp = 1 - std::pow(correlationMatrix_m(5, 0), 2.0) - l42 * l42 - l43 * l43; + const double l44 = copysign(sqrt(std::abs(temp)), temp); + Vector_t x = Vector_t(0.0); Vector_t p = Vector_t(0.0); for (size_t partIndex = 0; partIndex < numberOfParticles; partIndex++) { double A = 0.0; double AL = 0.0; - double U = 0.0; - double V = 0.0; - - double S1 = IpplRandom(); - double S2 = IpplRandom(); - - if (mBinomial_m[0] <= 10000) { - - A = sqrt(1.0 - pow(S1, AMI[0])); - AL = Physics::two_pi * S2; - U = A * cos(AL); - V = A * sin(AL); - double Ucp = U; - double Vcp = V; - x[0] = L[0] * U; - p[0] = PL[0] * (U * SINCHI[0] + V * COSCHI[0]); - - S1 = IpplRandom(); - S2 = IpplRandom(); - A = sqrt(1.0 - pow(S1, AMI[1])); - AL = Physics::two_pi * S2; - U = A * cos(AL); - V = A * sin(AL); - x[1] = L[1] * U; - p[1] = PL[1] * (U * SINCHI[1] + V * COSCHI[1]); - - S1 = IpplRandom(); - S2 = IpplRandom(); - A = sqrt(1.0 - pow(S1, AMI[2])); - AL = Physics::two_pi * S2; - U = A * cos(AL); - V = A * sin(AL); - - double tempa = 1.0 - std::pow(correlationMatrix_m(1, 0), 2.0); - const double l32 = (correlationMatrix_m(4, 1) - correlationMatrix_m(1, 0) * correlationMatrix_m(4, 0)) / sqrt(std::abs(tempa)) * tempa / std::abs(tempa); - double tempb = 1 - std::pow(correlationMatrix_m(4, 0), 2.0) - l32 * l32; - const double l33 = sqrt(std::abs(tempb)) * tempb / std::abs(tempb); - x[2] = Ucp * correlationMatrix_m(4, 0) + Vcp * l32 + U * l33; - const double l42 = (correlationMatrix_m(5, 1) - correlationMatrix_m(1, 0) * correlationMatrix_m(5, 0)) / sqrt(std::abs(tempa)) * tempa / std::abs(tempa); - const double l43 = (correlationMatrix_m(5, 4) - correlationMatrix_m(4, 0) * correlationMatrix_m(5, 0) - l42 * l32) / l33; - double tempc = 1 - std::pow(correlationMatrix_m(5, 0), 2.0) - l42 * l42 - l43 * l43; - const double l44 = sqrt(std::abs(tempc)) * tempc / std::abs(tempc); - - p[2] = Ucp * correlationMatrix_m(5, 0) + Vcp * l42 + U * l43 + V * l44; - x[2] *= L[2]; - p[2] *= PL[2]; - - } else { - - A = sqrt(2.0) / 2.0 * sqrt(-log(S1)); - AL = Physics::two_pi * S2; - U = A * cos(AL); - V = A * sin(AL); - double Ucp = U; - double Vcp = V; - x[0] = M[0] * U; - p[0] = PM[0] * (U * SINCHI[0] + V * COSCHI[0]); - - - S1 = IpplRandom(); - S2 = IpplRandom(); - A = sqrt(2.0) / 2.0 * sqrt(-log(S1)); - AL = Physics::two_pi * S2; - U = A * cos(AL); - V = A * sin(AL); - x[1] = M[1] * U; - p[1] = PM[1] * (U * SINCHI[1] + V * COSCHI[1]); - - S1 = IpplRandom(); - S2 = IpplRandom(); - A = sqrt(2.0) / 2.0 * sqrt(-log(S1)); - AL = Physics::two_pi * S2; - U = A * cos(AL); - V = A * sin(AL); - - double tempa = 1.0 - std::pow(correlationMatrix_m(1, 0), 2.0); - const double l32 = std::copysign(1.0, tempa) * (correlationMatrix_m(4, 1) - correlationMatrix_m(1, 0) * correlationMatrix_m(4, 0)) / sqrt(std::abs(tempa)); - double tempb = 1 - std::pow(correlationMatrix_m(4, 0), 2.0) - l32 * l32; - const double l33 = std::copysign(1.0, tempb) * sqrt(std::abs(tempb)); - x[2] = Ucp * correlationMatrix_m(4, 0) + Vcp * l32 + U * l33; - const double l42 = std::copysign(1.0, tempa) * (correlationMatrix_m(5, 1) - correlationMatrix_m(1, 0) * correlationMatrix_m(5, 0)) / sqrt(std::abs(tempa)); - const double l43 = (correlationMatrix_m(5, 4) - correlationMatrix_m(4, 0) * correlationMatrix_m(5, 0) - l42 * l32) / l33; - double tempc = 1 - std::pow(correlationMatrix_m(5, 0), 2.0) - l42 * l42 - l43 * l43; - const double l44 = std::copysign(1.0, tempc) * sqrt(std::abs(tempc)); - - p[2] = Ucp * correlationMatrix_m(5, 0) + Vcp * l42 + U * l43 + V * l44; - x[2] *= M[2]; - p[2] *= PM[2]; - - } + double Ux = 0.0, U = 0.0; + double Vx = 0.0, V = 0.0; + + A = splitter[0]->get(gsl_rng_uniform(randGen_m)); + AL = Physics::two_pi * gsl_rng_uniform(randGen_m); + Ux = A * cos(AL); + Vx = A * sin(AL); + x[0] = X[0] * Ux; + p[0] = PX[0] * (Ux * SINCHI[0] + Vx * COSCHI[0]); + + A = splitter[1]->get(gsl_rng_uniform(randGen_m)); + AL = Physics::two_pi * gsl_rng_uniform(randGen_m); + U = A * cos(AL); + V = A * sin(AL); + x[1] = X[1] * U; + p[1] = PX[1] * (U * SINCHI[1] + V * COSCHI[1]); + + A = splitter[2]->get(gsl_rng_uniform(randGen_m)); + AL = Physics::two_pi * gsl_rng_uniform(randGen_m); + U = A * cos(AL); + V = A * sin(AL); + x[2] = X[2] * (Ux * correlationMatrix_m(4, 0) + Vx * l32 + U * l33); + p[2] = PX[2] * (Ux * correlationMatrix_m(5, 0) + Vx * l42 + U * l43 + V * l44); // Save to each processor in turn. saveProcessor++; @@ -2444,9 +2361,12 @@ void Distribution::generateBinomial(size_t numberOfParticles) { yDist_m.push_back(x[1]); pyDist_m.push_back(p[1]); tOrZDist_m.push_back(x[2]); - pzDist_m.push_back(avrgpz_m * (1 + p[2])); + pzDist_m.push_back(avrgpz_m + p[2]); } + } + for (unsigned int index = 0; index < 3; index++) { + delete splitter[index]; } } @@ -2490,13 +2410,13 @@ void Distribution::generateFlattopT(size_t numberOfParticles) { gsl_qrng *quasiRandGen2D = NULL; - if(Options::rngtype != std::string("RANDOM")) { + if (Options::rngtype != std::string("RANDOM")) { INFOMSG("RNGTYPE= " << Options::rngtype << endl); - if(Options::rngtype == std::string("HALTON")) { + if (Options::rngtype == std::string("HALTON")) { quasiRandGen2D = gsl_qrng_alloc(gsl_qrng_halton, 2); - } else if(Options::rngtype == std::string("SOBOL")) { + } else if (Options::rngtype == std::string("SOBOL")) { quasiRandGen2D = gsl_qrng_alloc(gsl_qrng_sobol, 2); - } else if(Options::rngtype == std::string("NIEDERREITER")) { + } else if (Options::rngtype == std::string("NIEDERREITER")) { quasiRandGen2D = gsl_qrng_alloc(gsl_qrng_niederreiter_2, 2); } else { INFOMSG("RNGTYPE= " << Options::rngtype << " not known, using HALTON" << endl); @@ -2562,15 +2482,15 @@ void Distribution::generateFlattopZ(size_t numberOfParticles) { gsl_qrng *quasiRandGen1D = NULL; gsl_qrng *quasiRandGen2D = NULL; - if(Options::rngtype != std::string("RANDOM")) { + if (Options::rngtype != std::string("RANDOM")) { INFOMSG("RNGTYPE= " << Options::rngtype << endl); - if(Options::rngtype == std::string("HALTON")) { + if (Options::rngtype == std::string("HALTON")) { quasiRandGen1D = gsl_qrng_alloc(gsl_qrng_halton, 1); quasiRandGen2D = gsl_qrng_alloc(gsl_qrng_halton, 2); - } else if(Options::rngtype == std::string("SOBOL")) { + } else if (Options::rngtype == std::string("SOBOL")) { quasiRandGen1D = gsl_qrng_alloc(gsl_qrng_sobol, 1); quasiRandGen2D = gsl_qrng_alloc(gsl_qrng_sobol, 2); - } else if(Options::rngtype == std::string("NIEDERREITER")) { + } else if (Options::rngtype == std::string("NIEDERREITER")) { quasiRandGen1D = gsl_qrng_alloc(gsl_qrng_niederreiter_2, 1); quasiRandGen2D = gsl_qrng_alloc(gsl_qrng_niederreiter_2, 2); } else { @@ -2844,15 +2764,15 @@ void Distribution::generateLongFlattopT(size_t numberOfParticles) { gsl_qrng *quasiRandGen1D = NULL; gsl_qrng *quasiRandGen2D = NULL; - if(Options::rngtype != std::string("RANDOM")) { + if (Options::rngtype != std::string("RANDOM")) { INFOMSG("RNGTYPE= " << Options::rngtype << endl); - if(Options::rngtype == std::string("HALTON")) { + if (Options::rngtype == std::string("HALTON")) { quasiRandGen1D = gsl_qrng_alloc(gsl_qrng_halton, 1); quasiRandGen2D = gsl_qrng_alloc(gsl_qrng_halton, 2); - } else if(Options::rngtype == std::string("SOBOL")) { + } else if (Options::rngtype == std::string("SOBOL")) { quasiRandGen1D = gsl_qrng_alloc(gsl_qrng_sobol, 1); quasiRandGen2D = gsl_qrng_alloc(gsl_qrng_sobol, 2); - } else if(Options::rngtype == std::string("NIEDERREITER")) { + } else if (Options::rngtype == std::string("NIEDERREITER")) { quasiRandGen1D = gsl_qrng_alloc(gsl_qrng_niederreiter_2, 1); quasiRandGen2D = gsl_qrng_alloc(gsl_qrng_niederreiter_2, 2); } else { @@ -3351,27 +3271,27 @@ void Distribution::printDistFromFile(Inform &os) const { void Distribution::printDistMatchedGauss(Inform &os) const { os << "* Distribution type: MATCHEDGAUSS" << endl; - os << "* SIGMAX = " << sigmaR_m[0] << " [m]" << endl; - os << "* SIGMAY = " << sigmaR_m[1] << " [m]" << endl; - os << "* SIGMAZ = " << sigmaR_m[2] << " [m]" << endl; - os << "* SIGMAPX = " << sigmaP_m[0] << " [Beta Gamma]" << endl; - os << "* SIGMAPY = " << sigmaP_m[1] << " [Beta Gamma]" << endl; - os << "* SIGMAPZ = " << sigmaP_m[2] << " [Beta Gamma]" << endl; - os << "* AVRGPZ = " << avrgpz_m << " [Beta Gamma]" << endl; - - os << "* CORRX = " << correlationMatrix_m(1, 0) << endl; - os << "* CORRY = " << correlationMatrix_m(3, 2) << endl; - os << "* CORRZ = " << correlationMatrix_m(5, 4) << endl; - os << "* R61 = " << correlationMatrix_m(5, 0) << endl; - os << "* R62 = " << correlationMatrix_m(5, 1) << endl; - os << "* R51 = " << correlationMatrix_m(4, 0) << endl; - os << "* R52 = " << correlationMatrix_m(4, 1) << endl; - os << "* CUTOFFX = " << cutoffR_m[0] << " [units of SIGMAX]" << endl; - os << "* CUTOFFY = " << cutoffR_m[1] << " [units of SIGMAY]" << endl; - os << "* CUTOFFZ = " << cutoffR_m[2] << " [units of SIGMAZ]" << endl; - os << "* CUTOFFPX = " << cutoffP_m[0] << " [units of SIGMAPX]" << endl; - os << "* CUTOFFPY = " << cutoffP_m[1] << " [units of SIGMAPY]" << endl; - os << "* CUTOFFPZ = " << cutoffP_m[2] << " [units of SIGMAPY]" << endl; + os << "* SIGMAX = " << sigmaR_m[0] << " [m]" << endl; + os << "* SIGMAY = " << sigmaR_m[1] << " [m]" << endl; + os << "* SIGMAZ = " << sigmaR_m[2] << " [m]" << endl; + os << "* SIGMAPX = " << sigmaP_m[0] << " [Beta Gamma]" << endl; + os << "* SIGMAPY = " << sigmaP_m[1] << " [Beta Gamma]" << endl; + os << "* SIGMAPZ = " << sigmaP_m[2] << " [Beta Gamma]" << endl; + os << "* AVRGPZ = " << avrgpz_m << " [Beta Gamma]" << endl; + + os << "* CORRX = " << correlationMatrix_m(1, 0) << endl; + os << "* CORRY = " << correlationMatrix_m(3, 2) << endl; + os << "* CORRZ = " << correlationMatrix_m(5, 4) << endl; + os << "* R61 = " << correlationMatrix_m(5, 0) << endl; + os << "* R62 = " << correlationMatrix_m(5, 1) << endl; + os << "* R51 = " << correlationMatrix_m(4, 0) << endl; + os << "* R52 = " << correlationMatrix_m(4, 1) << endl; + os << "* CUTOFFX = " << cutoffR_m[0] << " [units of SIGMAX]" << endl; + os << "* CUTOFFY = " << cutoffR_m[1] << " [units of SIGMAY]" << endl; + os << "* CUTOFFLONG = " << cutoffR_m[2] << " [units of SIGMAZ]" << endl; + os << "* CUTOFFPX = " << cutoffP_m[0] << " [units of SIGMAPX]" << endl; + os << "* CUTOFFPY = " << cutoffP_m[1] << " [units of SIGMAPY]" << endl; + os << "* CUTOFFPZ = " << cutoffP_m[2] << " [units of SIGMAPY]" << endl; } void Distribution::printDistGauss(Inform &os) const { @@ -3409,27 +3329,27 @@ void Distribution::printDistGauss(Inform &os) const { os << "* CUTOFFPY = " << cutoffP_m[1] << " [units of SIGMAPY]" << endl; } else { - os << "* SIGMAX = " << sigmaR_m[0] << " [m]" << endl; - os << "* SIGMAY = " << sigmaR_m[1] << " [m]" << endl; - os << "* SIGMAZ = " << sigmaR_m[2] << " [m]" << endl; - os << "* SIGMAPX = " << sigmaP_m[0] << " [Beta Gamma]" << endl; - os << "* SIGMAPY = " << sigmaP_m[1] << " [Beta Gamma]" << endl; - os << "* SIGMAPZ = " << sigmaP_m[2] << " [Beta Gamma]" << endl; - os << "* AVRGPZ = " << avrgpz_m << " [Beta Gamma]" << endl; - - os << "* CORRX = " << correlationMatrix_m(1, 0) << endl; - os << "* CORRY = " << correlationMatrix_m(3, 2) << endl; - os << "* CORRZ = " << correlationMatrix_m(5, 4) << endl; - os << "* R61 = " << correlationMatrix_m(5, 0) << endl; - os << "* R62 = " << correlationMatrix_m(5, 1) << endl; - os << "* R51 = " << correlationMatrix_m(4, 0) << endl; - os << "* R52 = " << correlationMatrix_m(4, 1) << endl; - os << "* CUTOFFX = " << cutoffR_m[0] << " [units of SIGMAX]" << endl; - os << "* CUTOFFY = " << cutoffR_m[1] << " [units of SIGMAY]" << endl; - os << "* CUTOFFZ = " << cutoffR_m[2] << " [units of SIGMAZ]" << endl; - os << "* CUTOFFPX = " << cutoffP_m[0] << " [units of SIGMAPX]" << endl; - os << "* CUTOFFPY = " << cutoffP_m[1] << " [units of SIGMAPY]" << endl; - os << "* CUTOFFPZ = " << cutoffP_m[2] << " [units of SIGMAPY]" << endl; + os << "* SIGMAX = " << sigmaR_m[0] << " [m]" << endl; + os << "* SIGMAY = " << sigmaR_m[1] << " [m]" << endl; + os << "* SIGMAZ = " << sigmaR_m[2] << " [m]" << endl; + os << "* SIGMAPX = " << sigmaP_m[0] << " [Beta Gamma]" << endl; + os << "* SIGMAPY = " << sigmaP_m[1] << " [Beta Gamma]" << endl; + os << "* SIGMAPZ = " << sigmaP_m[2] << " [Beta Gamma]" << endl; + os << "* AVRGPZ = " << avrgpz_m << " [Beta Gamma]" << endl; + + os << "* CORRX = " << correlationMatrix_m(1, 0) << endl; + os << "* CORRY = " << correlationMatrix_m(3, 2) << endl; + os << "* CORRZ = " << correlationMatrix_m(5, 4) << endl; + os << "* R61 = " << correlationMatrix_m(5, 0) << endl; + os << "* R62 = " << correlationMatrix_m(5, 1) << endl; + os << "* R51 = " << correlationMatrix_m(4, 0) << endl; + os << "* R52 = " << correlationMatrix_m(4, 1) << endl; + os << "* CUTOFFX = " << cutoffR_m[0] << " [units of SIGMAX]" << endl; + os << "* CUTOFFY = " << cutoffR_m[1] << " [units of SIGMAY]" << endl; + os << "* CUTOFFLONG = " << cutoffR_m[2] << " [units of SIGMAZ]" << endl; + os << "* CUTOFFPX = " << cutoffP_m[0] << " [units of SIGMAPX]" << endl; + os << "* CUTOFFPY = " << cutoffP_m[1] << " [units of SIGMAPY]" << endl; + os << "* CUTOFFPZ = " << cutoffP_m[2] << " [units of SIGMAPY]" << endl; } } @@ -3645,7 +3565,7 @@ void Distribution::setAttributes() { "ASTRAFLATTOPTH, " "GAUSS, " "GAUSSMATCHED"); - itsAttr[Attrib::Distribution::DISTRIBUTION] + itsAttr[Attrib::Legacy::Distribution::DISTRIBUTION] = Attributes::makeString("DISTRIBUTION","This attribute isn't supported any more. Use TYPE instead"); itsAttr[Attrib::Distribution::LINE] = Attributes::makeString("LINE", "Beamline that contains a cyclotron or ring ", ""); @@ -4027,7 +3947,7 @@ void Distribution::setDistToEmitted(bool emitted) { } void Distribution::setDistType() { - if (itsAttr[Attrib::Distribution::DISTRIBUTION]) { + if (itsAttr[Attrib::Legacy::Distribution::DISTRIBUTION]) { throw OpalException("Distribution::setDistType()", "The attribute DISTRIBUTION isn't supported any more, use TYPE instead"); } @@ -4035,21 +3955,21 @@ void Distribution::setDistType() { distT_m = Util::toUpper(Attributes::getString(itsAttr[Attrib::Distribution::TYPE])); if (distT_m == "FROMFILE") distrTypeT_m = DistrTypeT::FROMFILE; - else if(distT_m == "GAUSS") + else if (distT_m == "GAUSS") distrTypeT_m = DistrTypeT::GAUSS; - else if(distT_m == "BINOMIAL") + else if (distT_m == "BINOMIAL") distrTypeT_m = DistrTypeT::BINOMIAL; - else if(distT_m == "FLATTOP") + else if (distT_m == "FLATTOP") distrTypeT_m = DistrTypeT::FLATTOP; - else if(distT_m == "GUNGAUSSFLATTOPTH") + else if (distT_m == "GUNGAUSSFLATTOPTH") distrTypeT_m = DistrTypeT::GUNGAUSSFLATTOPTH; - else if(distT_m == "ASTRAFLATTOPTH") + else if (distT_m == "ASTRAFLATTOPTH") distrTypeT_m = DistrTypeT::ASTRAFLATTOPTH; - else if(distT_m == "SURFACEEMISSION") + else if (distT_m == "SURFACEEMISSION") distrTypeT_m = DistrTypeT::SURFACEEMISSION; - else if(distT_m == "SURFACERANDCREATE") + else if (distT_m == "SURFACERANDCREATE") distrTypeT_m = DistrTypeT::SURFACERANDCREATE; - else if(distT_m == "GAUSSMATCHED") + else if (distT_m == "GAUSSMATCHED") distrTypeT_m = DistrTypeT::MATCHEDGAUSS; else { throw OpalException("Distribution::setDistType()", @@ -4131,6 +4051,14 @@ void Distribution::setDistParametersBinomial(double massIneV) { * Set Distribution parameters. Do all the necessary checks depending * on the input attributes. */ + std::vector<double> cr = Attributes::getRealArray(itsAttr[Attrib::Distribution::R]); + + if (cr.size()>0) { + throw OpalException("Distribution::setDistParametersBinomial", + "Attribute R is not supported for binomial distribution\n" + "use CORR[X|Y|Z] and R51, R52, R61, R62 instead"); + } + correlationMatrix_m(1, 0) = Attributes::getReal(itsAttr[Attrib::Distribution::CORRX]); correlationMatrix_m(3, 2) = Attributes::getReal(itsAttr[Attrib::Distribution::CORRY]); correlationMatrix_m(5, 4) = Attributes::getReal(itsAttr[Attrib::Distribution::CORRT]); @@ -4157,7 +4085,7 @@ void Distribution::setDistParametersBinomial(double massIneV) { std::abs(Attributes::getReal(itsAttr[Attrib::Distribution::SIGMAPZ]))); // SIGMAPZ overrides SIGMAPT. - if (itsAttr[Attrib::Legacy::Distribution::SIGMAPT]) { + if (!itsAttr[Attrib::Legacy::Distribution::SIGMAPT].defaultUsed()) { WARNMSG("The attribute SIGMAPT may be removed in a future version\n" << "use SIGMAPZ instead" << endl;) sigmaP_m[2] = std::abs(Attributes::getReal(itsAttr[Attrib::Legacy::Distribution::SIGMAPT])); @@ -4346,8 +4274,8 @@ void Distribution::setDistParametersGauss(double massIneV) { std::vector<double> cr = Attributes::getRealArray(itsAttr[Attrib::Distribution::R]); - if(cr.size()>0) { - if(cr.size() == 15) { + if (cr.size()>0) { + if (cr.size() == 15) { *gmsg << "* Use r to specify correlations" << endl; unsigned int k = 0; for (unsigned int i = 0; i < 5; ++ i) { @@ -4530,7 +4458,7 @@ void Distribution::setupParticleBins(double massIneV, PartBunch &beam) { double dEBins = Attributes::getReal(itsAttr[Attrib::Legacy::Distribution::DEBIN]); energyBins_m->setRebinEnergy(dEBins); - if (itsAttr[Attrib::Legacy::Distribution::PT]) + if (!itsAttr[Attrib::Legacy::Distribution::PT].defaultUsed()) throw OpalException("Distribution::setupParticleBins", "PT is obsolet. The moments of the beam is defined with OFFSETPZ"); @@ -4848,13 +4776,13 @@ void Distribution::writeOutFileInjection() { if (Attributes::getBool(itsAttr[Attrib::Distribution::WRITETOFILE])) { + std::string fname = "data/" + OpalData::getInstance()->getInputBasename() + "_" + getOpalName() + ".dat"; // Nodes take turn writing particles to file. for (int nodeIndex = 0; nodeIndex < Ippl::getNodes(); nodeIndex++) { // Write to file if its our turn. size_t numberOfParticles = 0; if (Ippl::myNode() == nodeIndex) { - std::string fname = "data/" + OpalData::getInstance()->getInputBasename() + "_" + getOpalName() + ".dat"; std::ofstream outputFile(fname, std::fstream::app); if (outputFile.bad()) { *gmsg << "Node " << Ippl::myNode() << " unable to write" @@ -4897,6 +4825,15 @@ void Distribution::writeOutFileInjection() { } } } + +double Distribution::MDependentBehavior::get(double rand) { + return 2.0 * sqrt(1.0 - pow(rand, ami_m)); +} + +double Distribution::GaussianLikeBehavior::get(double rand) { + return sqrt(-2.0 * log(rand)); +} + // vi: set et ts=4 sw=4 sts=4: // Local Variables: // mode:c++ diff --git a/src/Distribution/Distribution.h b/src/Distribution/Distribution.h index 2336c627217edd6850b343a3eb8e90494bfb3ab5..35438928669f9ff8987c61e8807aa429c82b459c 100644 --- a/src/Distribution/Distribution.h +++ b/src/Distribution/Distribution.h @@ -28,6 +28,7 @@ #include "Algorithms/Vektor.h" #include "Beamlines/Beamline.h" +#include "Attributes/Attributes.h" #include "Ippl.h" @@ -85,7 +86,6 @@ namespace Attrib { enum AttributesT { TYPE, - DISTRIBUTION, FNAME, WRITETOFILE, WEIGHT, @@ -207,7 +207,8 @@ namespace Attrib { enum LegacyAttributesT { // DESCRIPTION OF THE DISTRIBUTION: - DEBIN = Attrib::Distribution::SIZE, + DISTRIBUTION = Attrib::Distribution::SIZE, + DEBIN, SBIN, SIGMAPT, CUTOFF, @@ -383,6 +384,34 @@ private: double converteVToBetaGamma(double valueIneV, double massIneV); double convertMeVPerCToBetaGamma(double valueInMeVPerC, double massIneV); size_t getNumberOfParticlesInFile(std::ifstream &inputFile); + + class BinomialBehaviorSplitter { + public: + virtual ~BinomialBehaviorSplitter() + { } + + virtual double get(double rand) = 0; + }; + + class MDependentBehavior: public BinomialBehaviorSplitter { + public: + MDependentBehavior(const MDependentBehavior &rhs): + ami_m(rhs.ami_m) + {} + + MDependentBehavior(double a) + { ami_m = 1.0 / a; } + + virtual double get(double rand); + private: + double ami_m; + }; + + class GaussianLikeBehavior: public BinomialBehaviorSplitter { + public: + virtual double get(double rand); + }; + void createDistributionBinomial(size_t numberOfParticles, double massIneV); void createDistributionFlattop(size_t numberOfParticles, double massIneV); void createDistributionFromFile(size_t numberOfParticles, double massIneV); @@ -619,8 +648,155 @@ DistrTypeT::DistrTypeT Distribution::getType() const { return distrTypeT_m; } -inline double Distribution::getPercentageEmitted() const { +inline +double Distribution::getPercentageEmitted() const { return (double)totalNumberEmittedParticles_m / (double)totalNumberParticles_m; } +inline +double Distribution::getEkin() const { + return Attributes::getReal(itsAttr[Attrib::Distribution::EKIN]); +} + +inline +double Distribution::getLaserEnergy() const { + return Attributes::getReal(itsAttr[Attrib::Distribution::ELASER]); +} + +inline +double Distribution::getWorkFunctionRf() const { + return Attributes::getReal(itsAttr[Attrib::Distribution::W]); +} + +inline +size_t Distribution::getNumberOfDarkCurrentParticles() { + return (size_t) Attributes::getReal(itsAttr[Attrib::Distribution::NPDARKCUR]); +} + +inline +double Distribution::getDarkCurrentParticlesInwardMargin() { + return Attributes::getReal(itsAttr[Attrib::Distribution::INWARDMARGIN]); +} + +inline +double Distribution::getEInitThreshold() { + return Attributes::getReal(itsAttr[Attrib::Distribution::EINITHR]); +} + +inline +double Distribution::getWorkFunction() { + return Attributes::getReal(itsAttr[Attrib::Distribution::FNPHIW]); +} + +inline +double Distribution::getFieldEnhancement() { + return Attributes::getReal(itsAttr[Attrib::Distribution::FNBETA]); +} + +inline +size_t Distribution::getMaxFNemissionPartPerTri() { + return (size_t) Attributes::getReal(itsAttr[Attrib::Distribution::FNMAXEMI]); +} + +inline +double Distribution::getFieldFNThreshold() { + return Attributes::getReal(itsAttr[Attrib::Distribution::FNFIELDTHR]); +} + +inline +double Distribution::getFNParameterA() { + return Attributes::getReal(itsAttr[Attrib::Distribution::FNA]); +} + +inline +double Distribution::getFNParameterB() { + return Attributes::getReal(itsAttr[Attrib::Distribution::FNB]); +} + +inline +double Distribution::getFNParameterY() { + return Attributes::getReal(itsAttr[Attrib::Distribution::FNY]); +} + +inline +double Distribution::getFNParameterVYZero() { + return Attributes::getReal(itsAttr[Attrib::Distribution::FNVYZERO]); +} + +inline +double Distribution::getFNParameterVYSecond() { + return Attributes::getReal(itsAttr[Attrib::Distribution::FNVYSECOND]); +} + +inline +int Distribution::getSecondaryEmissionFlag() { + return Attributes::getReal(itsAttr[Attrib::Distribution::SECONDARYFLAG]); +} + +inline +bool Distribution::getEmissionMode() { + return Attributes::getBool(itsAttr[Attrib::Distribution::NEMISSIONMODE]); +} + +inline +std::string Distribution::getTypeofDistribution() { + return (std::string) Attributes::getString(itsAttr[Attrib::Distribution::TYPE]); +} + +inline +double Distribution::getvSeyZero() { + // return sey_0 in Vaughan's model + return Attributes::getReal(itsAttr[Attrib::Distribution::VSEYZERO]); +} + +inline +double Distribution::getvEZero() { + // return the energy related to sey_0 in Vaughan's model + return Attributes::getReal(itsAttr[Attrib::Distribution::VEZERO]); +} + +inline +double Distribution::getvSeyMax() { + // return sey max in Vaughan's model + return Attributes::getReal(itsAttr[Attrib::Distribution::VSEYMAX]); +} + +inline +double Distribution::getvEmax() { + // return Emax in Vaughan's model + return Attributes::getReal(itsAttr[Attrib::Distribution::VEMAX]); +} + +inline +double Distribution::getvKenergy() { + // return fitting parameter denotes the roughness of surface for + // impact energy in Vaughan's model + return Attributes::getReal(itsAttr[Attrib::Distribution::VKENERGY]); +} + +inline +double Distribution::getvKtheta() { + // return fitting parameter denotes the roughness of surface for + // impact angle in Vaughan's model + return Attributes::getReal(itsAttr[Attrib::Distribution::VKTHETA]); +} + +inline +double Distribution::getvVThermal() { + // thermal velocity of Maxwellian distribution of secondaries in Vaughan's model + return Attributes::getReal(itsAttr[Attrib::Distribution::VVTHERMAL]); +} + +inline +double Distribution::getVw() { + // velocity scalar for parallel plate benchmark; + return Attributes::getReal(itsAttr[Attrib::Distribution::VW]); +} + +inline +int Distribution::getSurfMaterial() { + // Surface material number for Furman-Pivi's Model; + return (int)Attributes::getReal(itsAttr[Attrib::Distribution::SURFMATERIAL]); +} + #endif // OPAL_Distribution_HH \ No newline at end of file diff --git a/tests/opal_src/Distribution/BinomialTest.cpp b/tests/opal_src/Distribution/BinomialTest.cpp index 3ba72c656c8cfca85a81995447a1a2dd51ef5577..737e2821210f1eba67f9e47367518e9e70d5afb8 100644 --- a/tests/opal_src/Distribution/BinomialTest.cpp +++ b/tests/opal_src/Distribution/BinomialTest.cpp @@ -15,7 +15,7 @@ TEST(BinomialTest, FullSigmaTest1) { const double expectedR22 = 0.7998; const double expectedR33 = 2.498; const double expectedR44 = 0.6212; - const double expectedR55 = 1.537; + const double expectedR55 = 1.537; const double expectedR66 = 0.9457; const double expectedR21 = -0.40993; @@ -35,16 +35,22 @@ TEST(BinomialTest, FullSigmaTest1) { Distribution dist; Attributes::setString(dist.itsAttr[Attrib::Distribution::TYPE], "BINOMIAL"); + Attributes::setReal(dist.itsAttr[Attrib::Distribution::MX], 999999999.9); + Attributes::setReal(dist.itsAttr[Attrib::Distribution::MY], 999999999.9); + Attributes::setReal(dist.itsAttr[Attrib::Distribution::MZ], 999999999.9); Attributes::setReal(dist.itsAttr[Attrib::Distribution::SIGMAX], expectedR11 * 1e-3); Attributes::setReal(dist.itsAttr[Attrib::Distribution::SIGMAPX], expectedR22); Attributes::setReal(dist.itsAttr[Attrib::Distribution::SIGMAY], expectedR33 * 1e-3); Attributes::setReal(dist.itsAttr[Attrib::Distribution::SIGMAPY], expectedR44); Attributes::setReal(dist.itsAttr[Attrib::Distribution::SIGMAZ], expectedR55 * 1e-3); Attributes::setReal(dist.itsAttr[Attrib::Distribution::SIGMAPZ], expectedR66); - Attributes::setReal(dist.itsAttr[Attrib::Distribution::MX], 999999999.9); - Attributes::setReal(dist.itsAttr[Attrib::Distribution::MY], 999999999.9); - Attributes::setReal(dist.itsAttr[Attrib::Distribution::MZ], 999999999.9); - Attributes::setRealArray(dist.itsAttr[Attrib::Distribution::R], expectedR); + Attributes::setReal(dist.itsAttr[Attrib::Distribution::CORRX], expectedR21); + Attributes::setReal(dist.itsAttr[Attrib::Distribution::CORRY], expectedR43); + Attributes::setReal(dist.itsAttr[Attrib::Distribution::CORRZ], expectedR65); + Attributes::setReal(dist.itsAttr[Attrib::Distribution::R51], expectedR51); + Attributes::setReal(dist.itsAttr[Attrib::Distribution::R61], expectedR61); + Attributes::setReal(dist.itsAttr[Attrib::Distribution::R52], expectedR52); + Attributes::setReal(dist.itsAttr[Attrib::Distribution::R62], expectedR62); Attributes::setBool(dist.itsAttr[Attrib::Distribution::EMITTED], false); dist.setDistType(); @@ -61,6 +67,8 @@ TEST(BinomialTest, FullSigmaTest1) { double R21 = (gsl_stats_covariance(&(dist.xDist_m[0]), 1, &(dist.pxDist_m[0]), 1, dist.xDist_m.size()) * 1e3 / (expectedR11 * expectedR22)); + double R43 = (gsl_stats_covariance(&(dist.yDist_m[0]), 1, &(dist.pyDist_m[0]), 1, dist.yDist_m.size()) * 1e3 / + (expectedR33 * expectedR44)); double R51 = (gsl_stats_covariance(&(dist.xDist_m[0]), 1, &(dist.tOrZDist_m[0]), 1, dist.xDist_m.size()) * 1e6 / (expectedR11 * expectedR55)); double R52 = (gsl_stats_covariance(&(dist.pxDist_m[0]), 1, &(dist.tOrZDist_m[0]), 1, dist.pxDist_m.size()) * 1e3 / @@ -70,18 +78,19 @@ TEST(BinomialTest, FullSigmaTest1) { double R62 = (gsl_stats_covariance(&(dist.pxDist_m[0]), 1, &(dist.pzDist_m[0]), 1, dist.pxDist_m.size()) / (expectedR22 * expectedR66)); - EXPECT_NEAR(expectedR11, R11, 0.05 * std::abs(expectedR11)); - EXPECT_NEAR(expectedR22, R22, 0.05 * std::abs(expectedR22)); - EXPECT_NEAR(expectedR33, R33, 0.05 * std::abs(expectedR33)); - EXPECT_NEAR(expectedR44, R44, 0.05 * std::abs(expectedR44)); - EXPECT_NEAR(expectedR55, R55, 0.05 * std::abs(expectedR55)); - EXPECT_NEAR(expectedR66, R66, 0.05 * std::abs(expectedR66)); - - EXPECT_NEAR(expectedR21, R21, 0.1 * std::abs(expectedR21)); - EXPECT_NEAR(expectedR51, R51, 0.1 * std::abs(expectedR51)); - EXPECT_NEAR(expectedR52, R52, 0.1 * std::abs(expectedR52)); - EXPECT_NEAR(expectedR61, R61, 0.1 * std::abs(expectedR61)); - EXPECT_NEAR(expectedR62, R62, 0.1 * std::abs(expectedR62)); + EXPECT_NEAR(R11 / expectedR11, 1.0, 0.002); + EXPECT_NEAR(R22 / expectedR22, 1.0, 0.002); + EXPECT_NEAR(R33 / expectedR33, 1.0, 0.002); + EXPECT_NEAR(R44 / expectedR44, 1.0, 0.002); + EXPECT_NEAR(R55 / expectedR55, 1.0, 0.002); + EXPECT_NEAR(R66 / expectedR66, 1.0, 0.002); + + EXPECT_NEAR(R21 / expectedR21, 1.0, 0.01); + EXPECT_NEAR(R43 / expectedR43, 1.0, 0.01); + EXPECT_NEAR(R51 / expectedR51, 1.0, 0.01); + EXPECT_NEAR(R52 / expectedR52, 1.0, 0.01); + EXPECT_NEAR(R61 / expectedR61, 1.0, 0.01); + EXPECT_NEAR(R62 / expectedR62, 1.0, 0.01); } TEST(BinomialTest, FullSigmaTest2) { @@ -104,7 +113,10 @@ TEST(BinomialTest, FullSigmaTest2) { Distribution dist; - Attributes::setString(dist.itsAttr[Attrib::Distribution::TYPE], "GAUSS"); + Attributes::setString(dist.itsAttr[Attrib::Distribution::TYPE], "BINOMIAL"); + Attributes::setReal(dist.itsAttr[Attrib::Distribution::MX], 1.0); + Attributes::setReal(dist.itsAttr[Attrib::Distribution::MY], 1.0); + Attributes::setReal(dist.itsAttr[Attrib::Distribution::MZ], 1.0); Attributes::setReal(dist.itsAttr[Attrib::Distribution::SIGMAX], expectedR11 * 1e-3); Attributes::setReal(dist.itsAttr[Attrib::Distribution::SIGMAPX], expectedR22); Attributes::setReal(dist.itsAttr[Attrib::Distribution::SIGMAY], expectedR33 * 1e-3); @@ -119,6 +131,7 @@ TEST(BinomialTest, FullSigmaTest2) { Attributes::setReal(dist.itsAttr[Attrib::Distribution::R52], expectedR52); Attributes::setReal(dist.itsAttr[Attrib::Distribution::R62], expectedR62); Attributes::setBool(dist.itsAttr[Attrib::Distribution::EMITTED], false); + Attributes::setBool(dist.itsAttr[Attrib::Distribution::WRITETOFILE], true); dist.setDistType(); dist.checkIfEmitted(); @@ -135,6 +148,8 @@ TEST(BinomialTest, FullSigmaTest2) { double R21 = (gsl_stats_covariance(&(dist.xDist_m[0]), 1, &(dist.pxDist_m[0]), 1, dist.xDist_m.size()) * 1e3 / (expectedR11 * expectedR22)); + double R43 = (gsl_stats_covariance(&(dist.yDist_m[0]), 1, &(dist.pyDist_m[0]), 1, dist.yDist_m.size()) * 1e3 / + (expectedR33 * expectedR44)); double R51 = (gsl_stats_covariance(&(dist.xDist_m[0]), 1, &(dist.tOrZDist_m[0]), 1, dist.xDist_m.size()) * 1e6 / (expectedR11 * expectedR55)); double R52 = (gsl_stats_covariance(&(dist.pxDist_m[0]), 1, &(dist.tOrZDist_m[0]), 1, dist.pxDist_m.size()) * 1e3 / @@ -144,16 +159,17 @@ TEST(BinomialTest, FullSigmaTest2) { double R62 = (gsl_stats_covariance(&(dist.pxDist_m[0]), 1, &(dist.pzDist_m[0]), 1, dist.pxDist_m.size()) / (expectedR22 * expectedR66)); - EXPECT_NEAR(expectedR11, R11, 0.05 * std::abs(expectedR11)); - EXPECT_NEAR(expectedR22, R22, 0.05 * std::abs(expectedR22)); - EXPECT_NEAR(expectedR33, R33, 0.05 * std::abs(expectedR33)); - EXPECT_NEAR(expectedR44, R44, 0.05 * std::abs(expectedR44)); - EXPECT_NEAR(expectedR55, R55, 0.05 * std::abs(expectedR55)); - EXPECT_NEAR(expectedR66, R66, 0.05 * std::abs(expectedR66)); - - EXPECT_NEAR(expectedR21, R21, 0.1 * std::abs(expectedR21)); - EXPECT_NEAR(expectedR51, R51, 0.1 * std::abs(expectedR51)); - EXPECT_NEAR(expectedR52, R52, 0.1 * std::abs(expectedR52)); - EXPECT_NEAR(expectedR61, R61, 0.1 * std::abs(expectedR61)); - EXPECT_NEAR(expectedR62, R62, 0.1 * std::abs(expectedR62)); + EXPECT_NEAR(R11 / expectedR11, 1.0, 0.002); + EXPECT_NEAR(R22 / expectedR22, 1.0, 0.002); + EXPECT_NEAR(R33 / expectedR33, 1.0, 0.002); + EXPECT_NEAR(R44 / expectedR44, 1.0, 0.002); + EXPECT_NEAR(R55 / expectedR55, 1.0, 0.002); + EXPECT_NEAR(R66 / expectedR66, 1.0, 0.002); + + EXPECT_NEAR(R21 / expectedR21, 1.0, 0.01); + EXPECT_NEAR(R43 / expectedR43, 1.0, 0.01); + EXPECT_NEAR(R51 / expectedR51, 1.0, 0.01); + EXPECT_NEAR(R52 / expectedR52, 1.0, 0.01); + EXPECT_NEAR(R61 / expectedR61, 1.0, 0.01); + EXPECT_NEAR(R62 / expectedR62, 1.0, 0.01); } \ No newline at end of file diff --git a/tests/opal_src/Distribution/GaussTest.cpp b/tests/opal_src/Distribution/GaussTest.cpp index 0f86fdbd93f1aaf25208cc79ebd8c04c77997c8f..300ac1f37424ed862c09298ae5f71ea6d5f4d811 100644 --- a/tests/opal_src/Distribution/GaussTest.cpp +++ b/tests/opal_src/Distribution/GaussTest.cpp @@ -9,7 +9,7 @@ #include "gsl/gsl_statistics_double.h" TEST(GaussTest, FullSigmaTest1) { - OpalTestUtilities::SilenceTest silencer(false); + OpalTestUtilities::SilenceTest silencer(true); const double expectedR11 = 1.978; const double expectedR22 = 0.7998; @@ -41,8 +41,15 @@ TEST(GaussTest, FullSigmaTest1) { Attributes::setReal(dist.itsAttr[Attrib::Distribution::SIGMAPY], expectedR44); Attributes::setReal(dist.itsAttr[Attrib::Distribution::SIGMAZ], expectedR55 * 1e-3); Attributes::setReal(dist.itsAttr[Attrib::Distribution::SIGMAPZ], expectedR66); + Attributes::setReal(dist.itsAttr[Attrib::Distribution::CUTOFFX], 5.0); + Attributes::setReal(dist.itsAttr[Attrib::Distribution::CUTOFFY], 5.0); + Attributes::setReal(dist.itsAttr[Attrib::Distribution::CUTOFFLONG], 5.0); + Attributes::setReal(dist.itsAttr[Attrib::Distribution::CUTOFFPX], 5.0); + Attributes::setReal(dist.itsAttr[Attrib::Distribution::CUTOFFPY], 5.0); + Attributes::setReal(dist.itsAttr[Attrib::Distribution::CUTOFFPZ], 5.0); Attributes::setRealArray(dist.itsAttr[Attrib::Distribution::R], expectedR); Attributes::setBool(dist.itsAttr[Attrib::Distribution::EMITTED], false); + Attributes::setBool(dist.itsAttr[Attrib::Distribution::WRITETOFILE], true); dist.setDistType(); dist.checkIfEmitted(); @@ -58,6 +65,8 @@ TEST(GaussTest, FullSigmaTest1) { double R21 = (gsl_stats_covariance(&(dist.xDist_m[0]), 1, &(dist.pxDist_m[0]), 1, dist.xDist_m.size()) * 1e3 / (expectedR11 * expectedR22)); + double R43 = (gsl_stats_covariance(&(dist.yDist_m[0]), 1, &(dist.pyDist_m[0]), 1, dist.yDist_m.size()) * 1e3 / + (expectedR33 * expectedR44)); double R51 = (gsl_stats_covariance(&(dist.xDist_m[0]), 1, &(dist.tOrZDist_m[0]), 1, dist.xDist_m.size()) * 1e6 / (expectedR11 * expectedR55)); double R52 = (gsl_stats_covariance(&(dist.pxDist_m[0]), 1, &(dist.tOrZDist_m[0]), 1, dist.pxDist_m.size()) * 1e3 / @@ -67,22 +76,23 @@ TEST(GaussTest, FullSigmaTest1) { double R62 = (gsl_stats_covariance(&(dist.pxDist_m[0]), 1, &(dist.pzDist_m[0]), 1, dist.pxDist_m.size()) / (expectedR22 * expectedR66)); - EXPECT_NEAR(expectedR11, R11, 0.05 * std::abs(expectedR11)); - EXPECT_NEAR(expectedR22, R22, 0.05 * std::abs(expectedR22)); - EXPECT_NEAR(expectedR33, R33, 0.05 * std::abs(expectedR33)); - EXPECT_NEAR(expectedR44, R44, 0.05 * std::abs(expectedR44)); - EXPECT_NEAR(expectedR55, R55, 0.05 * std::abs(expectedR55)); - EXPECT_NEAR(expectedR66, R66, 0.05 * std::abs(expectedR66)); - - EXPECT_NEAR(expectedR21, R21, 0.1 * std::abs(expectedR21)); - EXPECT_NEAR(expectedR51, R51, 0.1 * std::abs(expectedR51)); - EXPECT_NEAR(expectedR52, R52, 0.1 * std::abs(expectedR52)); - EXPECT_NEAR(expectedR61, R61, 0.1 * std::abs(expectedR61)); - EXPECT_NEAR(expectedR62, R62, 0.1 * std::abs(expectedR62)); + EXPECT_NEAR(R11 / expectedR11, 1.0, 0.002); + EXPECT_NEAR(R22 / expectedR22, 1.0, 0.002); + EXPECT_NEAR(R33 / expectedR33, 1.0, 0.002); + EXPECT_NEAR(R44 / expectedR44, 1.0, 0.002); + EXPECT_NEAR(R55 / expectedR55, 1.0, 0.002); + EXPECT_NEAR(R66 / expectedR66, 1.0, 0.002); + + EXPECT_NEAR(R21 / expectedR21, 1.0, 0.02); + EXPECT_NEAR(R43 / expectedR43, 1.0, 0.02); + EXPECT_NEAR(R51 / expectedR51, 1.0, 0.05); + EXPECT_NEAR(R52 / expectedR52, 1.0, 0.02); + EXPECT_NEAR(R61 / expectedR61, 1.0, 0.02); + EXPECT_NEAR(R62 / expectedR62, 1.0, 0.02); } TEST(GaussTest, FullSigmaTest2) { - OpalTestUtilities::SilenceTest silencer(false); + OpalTestUtilities::SilenceTest silencer(true); const double expectedR11 = 1.978; const double expectedR22 = 0.7998; @@ -115,7 +125,14 @@ TEST(GaussTest, FullSigmaTest2) { Attributes::setReal(dist.itsAttr[Attrib::Distribution::R61], expectedR61); Attributes::setReal(dist.itsAttr[Attrib::Distribution::R52], expectedR52); Attributes::setReal(dist.itsAttr[Attrib::Distribution::R62], expectedR62); + Attributes::setReal(dist.itsAttr[Attrib::Distribution::CUTOFFX], 5.0); + Attributes::setReal(dist.itsAttr[Attrib::Distribution::CUTOFFY], 5.0); + Attributes::setReal(dist.itsAttr[Attrib::Distribution::CUTOFFLONG], 5.0); + Attributes::setReal(dist.itsAttr[Attrib::Distribution::CUTOFFPX], 5.0); + Attributes::setReal(dist.itsAttr[Attrib::Distribution::CUTOFFPY], 5.0); + Attributes::setReal(dist.itsAttr[Attrib::Distribution::CUTOFFPZ], 5.0); Attributes::setBool(dist.itsAttr[Attrib::Distribution::EMITTED], false); + Attributes::setBool(dist.itsAttr[Attrib::Distribution::WRITETOFILE], true); dist.setDistType(); dist.checkIfEmitted(); @@ -132,6 +149,8 @@ TEST(GaussTest, FullSigmaTest2) { double R21 = (gsl_stats_covariance(&(dist.xDist_m[0]), 1, &(dist.pxDist_m[0]), 1, dist.xDist_m.size()) * 1e3 / (expectedR11 * expectedR22)); + double R43 = (gsl_stats_covariance(&(dist.yDist_m[0]), 1, &(dist.pyDist_m[0]), 1, dist.yDist_m.size()) * 1e3 / + (expectedR33 * expectedR44)); double R51 = (gsl_stats_covariance(&(dist.xDist_m[0]), 1, &(dist.tOrZDist_m[0]), 1, dist.xDist_m.size()) * 1e6 / (expectedR11 * expectedR55)); double R52 = (gsl_stats_covariance(&(dist.pxDist_m[0]), 1, &(dist.tOrZDist_m[0]), 1, dist.pxDist_m.size()) * 1e3 / @@ -141,16 +160,17 @@ TEST(GaussTest, FullSigmaTest2) { double R62 = (gsl_stats_covariance(&(dist.pxDist_m[0]), 1, &(dist.pzDist_m[0]), 1, dist.pxDist_m.size()) / (expectedR22 * expectedR66)); - EXPECT_NEAR(expectedR11, R11, 0.05 * std::abs(expectedR11)); - EXPECT_NEAR(expectedR22, R22, 0.05 * std::abs(expectedR22)); - EXPECT_NEAR(expectedR33, R33, 0.05 * std::abs(expectedR33)); - EXPECT_NEAR(expectedR44, R44, 0.05 * std::abs(expectedR44)); - EXPECT_NEAR(expectedR55, R55, 0.05 * std::abs(expectedR55)); - EXPECT_NEAR(expectedR66, R66, 0.05 * std::abs(expectedR66)); - - EXPECT_NEAR(expectedR21, R21, 0.1 * std::abs(expectedR21)); - EXPECT_NEAR(expectedR51, R51, 0.1 * std::abs(expectedR51)); - EXPECT_NEAR(expectedR52, R52, 0.1 * std::abs(expectedR52)); - EXPECT_NEAR(expectedR61, R61, 0.1 * std::abs(expectedR61)); - EXPECT_NEAR(expectedR62, R62, 0.1 * std::abs(expectedR62)); + EXPECT_NEAR(R11 / expectedR11, 1.0, 0.002); + EXPECT_NEAR(R22 / expectedR22, 1.0, 0.002); + EXPECT_NEAR(R33 / expectedR33, 1.0, 0.002); + EXPECT_NEAR(R44 / expectedR44, 1.0, 0.002); + EXPECT_NEAR(R55 / expectedR55, 1.0, 0.002); + EXPECT_NEAR(R66 / expectedR66, 1.0, 0.002); + + EXPECT_NEAR(R21 / expectedR21, 1.0, 0.02); + EXPECT_NEAR(R43 / expectedR43, 1.0, 0.02); + EXPECT_NEAR(R51 / expectedR51, 1.0, 0.05); + EXPECT_NEAR(R52 / expectedR52, 1.0, 0.02); + EXPECT_NEAR(R61 / expectedR61, 1.0, 0.02); + EXPECT_NEAR(R62 / expectedR62, 1.0, 0.02); } \ No newline at end of file