#ifndef PART_BUNCH_BASE_HPP #define PART_BUNCH_BASE_HPP #include "PartBunchBase.h" #include "Distribution/Distribution.h" #include "AbstractObjects/OpalData.h" // OPAL file #include "Utilities/OpalException.h" #include "Utilities/Options.h" #include "Utilities/Util.h" using Physics::pi; extern Inform *gmsg; // template // PartBunchBase::PartBunchBase() // : pbase(nullptr), // myNode_m(Ippl::myNode()), // nodes_m(Ippl::getNodes()), // fixed_grid(false), // pbin_m(nullptr), // lossDs_m(nullptr), // pmsg_m(nullptr), // f_stream(nullptr), // unit_state_(units), // stateOfLastBoundP_(unitless), // moments_m(), // dt_m(0.0), // t_m(0.0), // eKin_m(0.0), // dE_m(0.0), // spos_m(0.0), // rmax_m(0.0), // rmin_m(0.0), // rrms_m(0.0), // prms_m(0.0), // rmean_m(0.0), // pmean_m(0.0), // eps_m(0.0), // eps_norm_m(0.0), // rprms_m(0.0), // Dx_m(0.0), // Dy_m(0.0), // DDx_m(0.0), // DDy_m(0.0), // hr_m(-1.0), // nr_m(0), // fs_m(nullptr), // couplingConstant_m(0.0), // qi_m(0.0), // distDump_m(0), // fieldDBGStep_m(0), // dh_m(1e-12), // tEmission_m(0.0), // bingamma_m(nullptr), // binemitted_m(nullptr), // lPath_m(0.0), // stepsPerTurn_m(0), // localTrackStep_m(0), // globalTrackStep_m(0), // numBunch_m(1), // SteptoLastInj_m(0), // globalPartPerNode_m(nullptr), // dist_m(nullptr), // globalMeanR_m(Vector_t(0.0, 0.0, 0.0)), // globalToLocalQuaternion_m(Quaternion_t(1.0, 0.0, 0.0, 0.0)), // lowParticleCount_m(false), // dcBeam_m(false) // { // R(*(pbase->R_p)); // undefined behaviour due to reference to null pointer // ID(*(pbase->ID_p)); // undefined behaviour due to reference to null pointer // } template PartBunchBase::PartBunchBase(AbstractParticle* pb) : R(*(pb->R_p)), ID(*(pb->ID_p)), myNode_m(Ippl::myNode()), nodes_m(Ippl::getNodes()), fixed_grid(false), pbin_m(nullptr), lossDs_m(nullptr), pmsg_m(nullptr), f_stream(nullptr), lowParticleCount_m(false), // reference(ref), //FIXME unit_state_(units), stateOfLastBoundP_(unitless), moments_m(), dt_m(0.0), t_m(0.0), eKin_m(0.0), dE_m(0.0), spos_m(0.0), globalMeanR_m(Vector_t(0.0, 0.0, 0.0)), globalToLocalQuaternion_m(Quaternion_t(1.0, 0.0, 0.0, 0.0)), rmax_m(0.0), rmin_m(0.0), rrms_m(0.0), prms_m(0.0), rmean_m(0.0), pmean_m(0.0), eps_m(0.0), eps_norm_m(0.0), rprms_m(0.0), Dx_m(0.0), Dy_m(0.0), DDx_m(0.0), DDy_m(0.0), hr_m(-1.0), nr_m(0), fs_m(nullptr), couplingConstant_m(0.0), qi_m(0.0), distDump_m(0), fieldDBGStep_m(0), dh_m(1e-12), tEmission_m(0.0), bingamma_m(nullptr), binemitted_m(nullptr), lPath_m(0.0), stepsPerTurn_m(0), localTrackStep_m(0), globalTrackStep_m(0), numBunch_m(1), SteptoLastInj_m(0), globalPartPerNode_m(nullptr), dist_m(nullptr), dcBeam_m(false), periodLength_m(Physics::c / 1e9), pbase(pb) { setup(pb); boundpTimer_m = IpplTimings::getTimer("Boundingbox"); boundpBoundsTimer_m = IpplTimings::getTimer("Boundingbox-bounds"); boundpUpdateTimer_m = IpplTimings::getTimer("Boundingbox-update"); statParamTimer_m = IpplTimings::getTimer("Compute Statistics"); selfFieldTimer_m = IpplTimings::getTimer("SelfField total"); histoTimer_m = IpplTimings::getTimer("Histogram"); distrCreate_m = IpplTimings::getTimer("Create Distr"); distrReload_m = IpplTimings::getTimer("Load Distr"); globalPartPerNode_m = std::unique_ptr(new size_t[Ippl::getNodes()]); lossDs_m = std::unique_ptr(new LossDataSink(std::string("GlobalLosses"), !Options::asciidump)); pmsg_m.release(); // f_stream.release(); /* if(Ippl::getNodes() == 1) { f_stream = std::unique_ptr(new ofstream); f_stream->open("data/dist.dat", ios::out); pmsg_m = std::unique_ptr(new Inform(0, *f_stream, 0)); } */ } template PartBunchBase::PartBunchBase(AbstractParticle* pb, const PartData *ref) : R(*(pb->R_p)), ID(*(pb->ID_p)), myNode_m(Ippl::myNode()), nodes_m(Ippl::getNodes()), fixed_grid(false), pbin_m(nullptr), lossDs_m(nullptr), pmsg_m(nullptr), f_stream(nullptr), lowParticleCount_m(false), reference(ref), unit_state_(units), stateOfLastBoundP_(unitless), moments_m(), dt_m(0.0), t_m(0.0), eKin_m(0.0), dE_m(0.0), spos_m(0.0), globalMeanR_m(Vector_t(0.0, 0.0, 0.0)), globalToLocalQuaternion_m(Quaternion_t(1.0, 0.0, 0.0, 0.0)), rmax_m(0.0), rmin_m(0.0), rrms_m(0.0), prms_m(0.0), rmean_m(0.0), pmean_m(0.0), eps_m(0.0), eps_norm_m(0.0), rprms_m(0.0), Dx_m(0.0), Dy_m(0.0), DDx_m(0.0), DDy_m(0.0), hr_m(-1.0), nr_m(0), fs_m(nullptr), couplingConstant_m(0.0), qi_m(0.0), distDump_m(0), fieldDBGStep_m(0), dh_m(1e-12), tEmission_m(0.0), bingamma_m(nullptr), binemitted_m(nullptr), lPath_m(0.0), stepsPerTurn_m(0), localTrackStep_m(0), globalTrackStep_m(0), numBunch_m(1), SteptoLastInj_m(0), globalPartPerNode_m(nullptr), dist_m(nullptr), dcBeam_m(false), periodLength_m(Physics::c / 1e9), pbase(pb) { setup(pb); boundpTimer_m = IpplTimings::getTimer("Boundingbox"); boundpBoundsTimer_m = IpplTimings::getTimer("Boundingbox-bounds"); boundpUpdateTimer_m = IpplTimings::getTimer("Boundingbox-update"); statParamTimer_m = IpplTimings::getTimer("Compute Statistics"); selfFieldTimer_m = IpplTimings::getTimer("SelfField total"); histoTimer_m = IpplTimings::getTimer("Histogram"); distrCreate_m = IpplTimings::getTimer("Create Distr"); distrReload_m = IpplTimings::getTimer("Load Distr"); globalPartPerNode_m = std::unique_ptr(new size_t[Ippl::getNodes()]); lossDs_m = std::unique_ptr(new LossDataSink(std::string("GlobalLosses"), !Options::asciidump)); pmsg_m.release(); // f_stream.release(); /* if(Ippl::getNodes() == 1) { f_stream = std::unique_ptr(new ofstream); f_stream->open("data/dist.dat", ios::out); pmsg_m = std::unique_ptr(new Inform(0, *f_stream, 0)); } */ } template PartBunchBase::PartBunchBase(AbstractParticle* pb, const std::vector& rhs, const PartData *ref): R(*(pb->R_p)), ID(*(pb->ID_p)), myNode_m(Ippl::myNode()), nodes_m(Ippl::getNodes()), fixed_grid(false), pbin_m(nullptr), lossDs_m(nullptr), pmsg_m(nullptr), f_stream(nullptr), lowParticleCount_m(false), reference(ref), unit_state_(units), stateOfLastBoundP_(unitless), moments_m(), dt_m(0.0), t_m(0.0), eKin_m(0.0), dE_m(0.0), spos_m(0.0), globalMeanR_m(Vector_t(0.0, 0.0, 0.0)), globalToLocalQuaternion_m(Quaternion_t(1.0, 0.0, 0.0, 0.0)), rmax_m(0.0), rmin_m(0.0), rrms_m(0.0), prms_m(0.0), rmean_m(0.0), pmean_m(0.0), eps_m(0.0), eps_norm_m(0.0), rprms_m(0.0), Dx_m(0.0), Dy_m(0.0), DDx_m(0.0), DDy_m(0.0), hr_m(-1.0), nr_m(0), fs_m(nullptr), couplingConstant_m(0.0), qi_m(0.0), distDump_m(0), fieldDBGStep_m(0), dh_m(1e-12), tEmission_m(0.0), bingamma_m(nullptr), binemitted_m(nullptr), lPath_m(0.0), stepsPerTurn_m(0), localTrackStep_m(0), globalTrackStep_m(0), numBunch_m(1), SteptoLastInj_m(0), globalPartPerNode_m(nullptr), dist_m(nullptr), dcBeam_m(false), periodLength_m(Physics::c / 1e9), pbase(pb) { } template PartBunchBase::PartBunchBase(const PartBunchBase& rhs): R(rhs.R), ID(rhs.ID), myNode_m(Ippl::myNode()), nodes_m(Ippl::getNodes()), fixed_grid(rhs.fixed_grid), pbin_m(nullptr), lossDs_m(nullptr), pmsg_m(nullptr), f_stream(nullptr), lowParticleCount_m(rhs.lowParticleCount_m), reference(rhs.reference), unit_state_(rhs.unit_state_), stateOfLastBoundP_(rhs.stateOfLastBoundP_), moments_m(rhs.moments_m), dt_m(rhs.dt_m), t_m(rhs.t_m), eKin_m(rhs.eKin_m), dE_m(rhs.dE_m), spos_m(0.0), globalMeanR_m(Vector_t(0.0, 0.0, 0.0)), globalToLocalQuaternion_m(Quaternion_t(1.0, 0.0, 0.0, 0.0)), rmax_m(rhs.rmax_m), rmin_m(rhs.rmin_m), rrms_m(rhs.rrms_m), prms_m(rhs.prms_m), rmean_m(rhs.rmean_m), pmean_m(rhs.pmean_m), eps_m(rhs.eps_m), eps_norm_m(rhs.eps_norm_m), rprms_m(rhs.rprms_m), Dx_m(rhs.Dx_m), Dy_m(rhs.Dy_m), DDx_m(rhs.DDx_m), DDy_m(rhs.DDy_m), hr_m(rhs.hr_m), nr_m(rhs.nr_m), fs_m(nullptr), couplingConstant_m(rhs.couplingConstant_m), qi_m(rhs.qi_m), distDump_m(rhs.distDump_m), fieldDBGStep_m(rhs.fieldDBGStep_m), dh_m(rhs.dh_m), tEmission_m(rhs.tEmission_m), bingamma_m(nullptr), binemitted_m(nullptr), lPath_m(rhs.lPath_m), stepsPerTurn_m(rhs.stepsPerTurn_m), localTrackStep_m(rhs.localTrackStep_m), globalTrackStep_m(rhs.globalTrackStep_m), numBunch_m(rhs.numBunch_m), SteptoLastInj_m(rhs.SteptoLastInj_m), globalPartPerNode_m(nullptr), dist_m(nullptr), dcBeam_m(rhs.dcBeam_m), periodLength_m(rhs.periodLength_m), pbase(rhs.pbase) { } // template // AbstractParticle* PartBunchBase::getParticleBase() { // return pbase; // } // // // template // const AbstractParticle* PartBunchBase::getParticleBase() const { // return pbase; // } /* * Bunch common member functions */ template bool PartBunchBase::getIfBeamEmitting() { if (dist_m != NULL) { size_t isBeamEmitted = dist_m->getIfDistEmitting(); reduce(isBeamEmitted, isBeamEmitted, OpAddAssign()); if (isBeamEmitted > 0) return true; else return false; } else return false; } template int PartBunchBase::getLastEmittedEnergyBin() { /* * Get maximum last emitted energy bin. */ int lastEmittedBin = dist_m->getLastEmittedEnergyBin(); reduce(lastEmittedBin, lastEmittedBin, OpMaxAssign()); return lastEmittedBin; } template size_t PartBunchBase::getNumberOfEmissionSteps() { return dist_m->getNumberOfEmissionSteps(); } template int PartBunchBase::getNumberOfEnergyBins() { return dist_m->getNumberOfEnergyBins(); } template void PartBunchBase::Rebin() { size_t isBeamEmitting = dist_m->getIfDistEmitting(); reduce(isBeamEmitting, isBeamEmitting, OpAddAssign()); if (isBeamEmitting > 0) { *gmsg << "*****************************************************" << endl << "Warning: attempted to rebin, but not all distribution" << endl << "particles have been emitted. Rebin failed." << endl << "*****************************************************" << endl; } else { if (dist_m->Rebin()) this->Bin = 0; } } template void PartBunchBase::setEnergyBins(int numberOfEnergyBins) { bingamma_m = std::unique_ptr(new double[numberOfEnergyBins]); binemitted_m = std::unique_ptr(new size_t[numberOfEnergyBins]); for(int i = 0; i < numberOfEnergyBins; i++) binemitted_m[i] = 0; } template bool PartBunchBase::weHaveEnergyBins() { if (dist_m != NULL) return dist_m->getNumberOfEnergyBins() > 0; else return false; } template void PartBunchBase::switchToUnitlessPositions(bool use_dt_per_particle) { if(unit_state_ == unitless) throw SwitcherError("PartBunch::switchToUnitlessPositions", "Cannot make a unitless PartBunch unitless"); bool hasToReset = false; if(!R.isDirty()) hasToReset = true; for(size_t i = 0; i < getLocalNum(); i++) { double dt = getdT(); if(use_dt_per_particle) dt = this->dt[i]; R[i] /= Vector_t(Physics::c * dt); } unit_state_ = unitless; if(hasToReset) R.resetDirtyFlag(); } //FIXME: unify methods, use convention that all particles have own dt template void PartBunchBase::switchOffUnitlessPositions(bool use_dt_per_particle) { if(unit_state_ == units) throw SwitcherError("PartBunch::switchOffUnitlessPositions", "Cannot apply units twice to PartBunch"); bool hasToReset = false; if(!R.isDirty()) hasToReset = true; for(size_t i = 0; i < getLocalNum(); i++) { double dt = getdT(); if(use_dt_per_particle) dt = this->dt[i]; R[i] *= Vector_t(Physics::c * dt); } unit_state_ = units; if(hasToReset) R.resetDirtyFlag(); } template void PartBunchBase::do_binaryRepart() { // do nothing here } template void PartBunchBase::setDistribution(Distribution *d, std::vector addedDistributions, size_t &np) { Inform m("setDistribution " ); dist_m = d; dist_m->createOpalT(this, addedDistributions, np); // if (Options::cZero) // dist_m->create(this, addedDistributions, np / 2); // else // dist_m->create(this, addedDistributions, np); } template bool PartBunchBase::isGridFixed() { return fixed_grid; } template bool PartBunchBase::hasBinning() { return (pbin_m != nullptr); } template void PartBunchBase::setTEmission(double t) { tEmission_m = t; } template double PartBunchBase::getTEmission() { return tEmission_m; } template bool PartBunchBase::doEmission() { if (dist_m != NULL) return dist_m->getIfDistEmitting(); else return false; } template bool PartBunchBase::weHaveBins() const { if(pbin_m != NULL) return pbin_m->weHaveBins(); else return false; } template void PartBunchBase::setPBins(PartBins *pbin) { pbin_m = pbin; *gmsg << *pbin_m << endl; setEnergyBins(pbin_m->getNBins()); } template void PartBunchBase::setPBins(PartBinsCyc *pbin) { pbin_m = pbin; setEnergyBins(pbin_m->getNBins()); } template size_t PartBunchBase::emitParticles(double eZ) { return dist_m->emitParticles(this, eZ); } template void PartBunchBase::updateNumTotal() { size_t numParticles = getLocalNum(); reduce(numParticles, numParticles, OpAddAssign()); setTotalNum(numParticles); } template void PartBunchBase::rebin() { this->Bin = 0; pbin_m->resetBins(); // delete pbin_m; we did not allocate it! pbin_m = NULL; } template int PartBunchBase::getNumBins() { if(pbin_m != NULL) return pbin_m->getNBins(); else return 0; } template int PartBunchBase::getLastemittedBin() { if(pbin_m != NULL) return pbin_m->getLastemittedBin(); else return 0; } template void PartBunchBase::calcGammas() { const int emittedBins = dist_m->getNumberOfEnergyBins(); size_t s = 0; for(int i = 0; i < emittedBins; i++) bingamma_m[i] = 0.0; for(unsigned int n = 0; n < getLocalNum(); n++) bingamma_m[this->Bin[n]] += sqrt(1.0 + dot(this->P[n], this->P[n])); std::unique_ptr particlesInBin(new size_t[emittedBins]); reduce(bingamma_m.get(), bingamma_m.get() + emittedBins, bingamma_m.get(), OpAddAssign()); reduce(binemitted_m.get(), binemitted_m.get() + emittedBins, particlesInBin.get(), OpAddAssign()); for(int i = 0; i < emittedBins; i++) { size_t &pInBin = particlesInBin[i]; if(pInBin != 0) { bingamma_m[i] /= pInBin; INFOMSG(level2 << "Bin " << std::setw(3) << i << " gamma = " << std::setw(8) << std::scientific << std::setprecision(5) << bingamma_m[i] << "; NpInBin= " << std::setw(8) << std::setfill(' ') << pInBin << endl); } else { bingamma_m[i] = 1.0; INFOMSG(level2 << "Bin " << std::setw(3) << i << " has no particles " << endl); } s += pInBin; } particlesInBin.reset(); if(s != getTotalNum() && !OpalData::getInstance()->hasGlobalGeometry()) ERRORMSG("sum(Bins)= " << s << " != sum(R)= " << getTotalNum() << endl;); if(emittedBins >= 2) { for(int i = 1; i < emittedBins; i++) { if(binemitted_m[i - 1] != 0 && binemitted_m[i] != 0) INFOMSG(level2 << "d(gamma)= " << 100.0 * std::abs(bingamma_m[i - 1] - bingamma_m[i]) / bingamma_m[i] << " [%] " << "between bin " << i - 1 << " and " << i << endl); } } } template void PartBunchBase::calcGammas_cycl() { const int emittedBins = pbin_m->getLastemittedBin(); for(int i = 0; i < emittedBins; i++) bingamma_m[i] = 0.0; for(unsigned int n = 0; n < getLocalNum(); n++) bingamma_m[this->Bin[n]] += sqrt(1.0 + dot(this->P[n], this->P[n])); allreduce(*bingamma_m.get(), emittedBins, std::plus()); for(int i = 0; i < emittedBins; i++) { if(pbin_m->getTotalNumPerBin(i) > 0) bingamma_m[i] /= pbin_m->getTotalNumPerBin(i); else bingamma_m[i] = 0.0; INFOMSG("Bin " << i << " : particle number = " << pbin_m->getTotalNumPerBin(i) << " gamma = " << bingamma_m[i] << endl); } } template double PartBunchBase::getBinGamma(int bin) { return bingamma_m[bin]; } template void PartBunchBase::setBinCharge(int bin, double q) { this->Q = where(eq(this->Bin, bin), q, 0.0); } template void PartBunchBase::setBinCharge(int bin) { this->Q = where(eq(this->Bin, bin), this->qi_m, 0.0); } template size_t PartBunchBase::calcNumPartsOutside(Vector_t x) { std::size_t localnum = 0; const Vector_t meanR = get_rmean(); for(unsigned long k = 0; k < getLocalNum(); ++ k) if (std::abs(R[k](0) - meanR(0)) > x(0) || std::abs(R[k](1) - meanR(1)) > x(1) || std::abs(R[k](2) - meanR(2)) > x(2)) { ++localnum; } gather(&localnum, &globalPartPerNode_m[0], 1); size_t npOutside = std::accumulate(globalPartPerNode_m.get(), globalPartPerNode_m.get() + Ippl::getNodes(), 0, std::plus()); return npOutside; } /** * \method calcLineDensity() * \brief calculates the 1d line density (not normalized) and append it to a file. * \see ParallelTTracker * \warning none yet * * DETAILED TODO * */ template void PartBunchBase::calcLineDensity(unsigned int nBins, std::vector &lineDensity, std::pair &meshInfo) { Vector_t rmin, rmax; get_bounds(rmin, rmax); if (nBins < 2) { Vektor/*NDIndex<3>*/ grid; this->updateDomainLength(grid); nBins = grid[2]; } double length = rmax(2) - rmin(2); double zmin = rmin(2) - dh_m * length, zmax = rmax(2) + dh_m * length; double hz = (zmax - zmin) / (nBins - 2); double perMeter = 1.0 / hz;//(zmax - zmin); zmin -= hz; lineDensity.resize(nBins, 0.0); std::fill(lineDensity.begin(), lineDensity.end(), 0.0); const unsigned int lN = getLocalNum(); for (unsigned int i = 0; i < lN; ++ i) { const double z = R[i](2) - 0.5 * hz; unsigned int idx = (z - zmin) / hz; double tau = (z - zmin) / hz - idx; lineDensity[idx] += Q[i] * (1.0 - tau) * perMeter; lineDensity[idx + 1] += Q[i] * tau * perMeter; } reduce(&(lineDensity[0]), &(lineDensity[0]) + nBins, &(lineDensity[0]), OpAddAssign()); meshInfo.first = zmin; meshInfo.second = hz; } template void PartBunchBase::boundp() { /* Assume rmin_m < 0.0 */ IpplTimings::startTimer(boundpTimer_m); //if(!R.isDirty() && stateOfLastBoundP_ == unit_state_) return; if ( !(R.isDirty() || ID.isDirty() ) && stateOfLastBoundP_ == unit_state_) return; //-DW stateOfLastBoundP_ = unit_state_; if(!isGridFixed()) { const int dimIdx = (dcBeam_m? 2: 3); /** In case of dcBeam_m && hr_m < 0 this is the first call to boundp and we have to set hr completely i.e. x,y and z. */ this->updateDomainLength(nr_m); IpplTimings::startTimer(boundpBoundsTimer_m); get_bounds(rmin_m, rmax_m); IpplTimings::stopTimer(boundpBoundsTimer_m); Vector_t len = rmax_m - rmin_m; double volume = 1.0; for(int i = 0; i < dimIdx; i++) { double length = std::abs(rmax_m[i] - rmin_m[i]); if (length < 1e-10) { rmax_m[i] += 1e-10; rmin_m[i] -= 1e-10; } else { rmax_m[i] += dh_m * length; rmin_m[i] -= dh_m * length; } hr_m[i] = (rmax_m[i] - rmin_m[i]) / (nr_m[i] - 1); } if (dcBeam_m) { rmax_m[2] = rmin_m[2] + periodLength_m; hr_m[2] = periodLength_m / (nr_m[2] - 1); } for (int i = 0; i < dimIdx; ++ i) { volume *= std::abs(rmax_m[i] - rmin_m[i]); } if (getIfBeamEmitting() && dist_m != NULL) { // keep particles per cell ratio high, don't spread a hand full particles across the whole grid double percent = std::max(1.0 / (nr_m[2] - 1), dist_m->getPercentageEmitted()); double length = std::abs(rmax_m[2] - rmin_m[2]) / (1.0 + 2 * dh_m); if (percent < 1.0 && percent > 0.0) { rmax_m[2] -= dh_m * length; rmin_m[2] = rmax_m[2] - length / percent; length /= percent; rmax_m[2] += dh_m * length; rmin_m[2] -= dh_m * length; hr_m[2] = (rmax_m[2] - rmin_m[2]) / (nr_m[2] - 1); } } if (volume < 1e-21 && getTotalNum() > 1 && std::abs(sum(Q)) > 0.0) { WARNMSG(level1 << "!!! Extremly high particle density detected !!!" << endl); } //INFOMSG("It is a full boundp hz= " << hr_m << " rmax= " << rmax_m << " rmin= " << rmin_m << endl); if(hr_m[0] * hr_m[1] * hr_m[2] <= 0) { throw GeneralClassicException("boundp() ", "h<0, can not build a mesh"); } Vector_t origin = rmin_m - Vector_t(hr_m[0] / 2.0, hr_m[1] / 2.0, hr_m[2] / 2.0); this->updateFields(hr_m, origin); } IpplTimings::startTimer(boundpUpdateTimer_m); update(); IpplTimings::stopTimer(boundpUpdateTimer_m); R.resetDirtyFlag(); IpplTimings::stopTimer(boundpTimer_m); } template void PartBunchBase::boundp_destroy() { Inform gmsgAll("boundp_destroy ", INFORM_ALL_NODES); Vector_t len; const int dimIdx = 3; IpplTimings::startTimer(boundpTimer_m); std::unique_ptr countLost; if(weHaveBins()) { const int tempN = pbin_m->getLastemittedBin(); countLost = std::unique_ptr(new size_t[tempN]); for(int ii = 0; ii < tempN; ii++) countLost[ii] = 0; } this->updateDomainLength(nr_m); IpplTimings::startTimer(boundpBoundsTimer_m); get_bounds(rmin_m, rmax_m); IpplTimings::stopTimer(boundpBoundsTimer_m); len = rmax_m - rmin_m; calcBeamParameters(); int checkfactor = Options::remotePartDel; if (checkfactor != 0) { //INFOMSG("checkfactor= " << checkfactor << endl); // check the bunch if its full size is larger than checkfactor times of its rms size if(checkfactor < 0) { checkfactor *= -1; if (len[0] > checkfactor * rrms_m[0] || len[1] > checkfactor * rrms_m[1] || len[2] > checkfactor * rrms_m[2]) { for(unsigned int ii = 0; ii < this->getLocalNum(); ii++) { /* delete the particle if the distance to the beam center * is larger than 8 times of beam's rms size */ if (std::abs(R[ii](0) - rmean_m(0)) > checkfactor * rrms_m[0] || std::abs(R[ii](1) - rmean_m(1)) > checkfactor * rrms_m[1] || std::abs(R[ii](2) - rmean_m(2)) > checkfactor * rrms_m[2]) { // put particle onto deletion list destroy(1, ii); //update bin parameter if (weHaveBins()) countLost[Bin[ii]] += 1 ; /* INFOMSG("REMOTE PARTICLE DELETION: ID = " << ID[ii] << ", R = " << R[ii] * << ", beam rms = " << rrms_m << endl;); */ } } } } else { if (len[0] > checkfactor * rrms_m[0] || len[2] > checkfactor * rrms_m[2]) { for(unsigned int ii = 0; ii < this->getLocalNum(); ii++) { /* delete the particle if the distance to the beam center * is larger than 8 times of beam's rms size */ if (std::abs(R[ii](0) - rmean_m(0)) > checkfactor * rrms_m[0] || std::abs(R[ii](2) - rmean_m(2)) > checkfactor * rrms_m[2]) { // put particle onto deletion list destroy(1, ii); //update bin parameter if (weHaveBins()) countLost[Bin[ii]] += 1 ; /* INFOMSG("REMOTE PARTICLE DELETION: ID = " << ID[ii] << ", R = " << R[ii] * << ", beam rms = " << rrms_m << endl;); */ } } } } } for(int i = 0; i < dimIdx; i++) { double length = std::abs(rmax_m[i] - rmin_m[i]); rmax_m[i] += dh_m * length; rmin_m[i] -= dh_m * length; hr_m[i] = (rmax_m[i] - rmin_m[i]) / (nr_m[i] - 1); } // rescale mesh this->updateFields(hr_m, rmin_m); if(weHaveBins()) { pbin_m->updatePartInBin_cyc(countLost.get()); } IpplTimings::startTimer(boundpUpdateTimer_m); update(); IpplTimings::stopTimer(boundpUpdateTimer_m); IpplTimings::stopTimer(boundpTimer_m); } template size_t PartBunchBase::boundp_destroyT() { const unsigned int minNumParticlesPerCore = getMinimumNumberOfParticlesPerCore(); this->updateDomainLength(nr_m); std::unique_ptr tmpbinemitted; boundp(); size_t ne = 0; const size_t localNum = getLocalNum(); if(weHaveEnergyBins()) { tmpbinemitted = std::unique_ptr(new size_t[getNumberOfEnergyBins()]); for(int i = 0; i < getNumberOfEnergyBins(); i++) { tmpbinemitted[i] = 0; } for(unsigned int i = 0; i < localNum; i++) { if (Bin[i] < 0) { ne++; destroy(1, i); } else tmpbinemitted[Bin[i]]++; } } else { for(unsigned int i = 0; i < localNum; i++) { if((Bin[i] < 0) && ((localNum - ne) > minNumParticlesPerCore)) { // need in minimum x particles per node ne++; destroy(1, i); } } lowParticleCount_m = ((localNum - ne) <= minNumParticlesPerCore); reduce(lowParticleCount_m, lowParticleCount_m, OpOr()); } if (lowParticleCount_m) { Inform m ("boundp_destroyT a) ", INFORM_ALL_NODES); m << level3 << "Warning low number of particles on some cores localNum= " << localNum << " ne= " << ne << " NLocal= " << getLocalNum() << endl; } else { boundp(); } calcBeamParameters(); gatherLoadBalanceStatistics(); if(weHaveEnergyBins()) { const int lastBin = dist_m->getLastEmittedEnergyBin(); for(int i = 0; i < lastBin; i++) { binemitted_m[i] = tmpbinemitted[i]; } } reduce(ne, ne, OpAddAssign()); return ne; } template size_t PartBunchBase::destroyT() { const unsigned int minNumParticlesPerCore = getMinimumNumberOfParticlesPerCore(); std::unique_ptr tmpbinemitted; const size_t localNum = getLocalNum(); const size_t totalNum = getTotalNum(); size_t ne = 0; if(weHaveEnergyBins()) { tmpbinemitted = std::unique_ptr(new size_t[getNumberOfEnergyBins()]); for(int i = 0; i < getNumberOfEnergyBins(); i++) { tmpbinemitted[i] = 0; } for(unsigned int i = 0; i < localNum; i++) { if (Bin[i] < 0) { destroy(1, i); ++ ne; } else tmpbinemitted[Bin[i]]++; } } else { Inform dmsg("destroy: ", INFORM_ALL_NODES); for(size_t i = 0; i < localNum; i++) { if((Bin[i] < 0)) { if ((localNum - ne) > minNumParticlesPerCore) { // need in minimum x particles per node ne++; destroy(1, i); } } } lowParticleCount_m = ((localNum - ne) <= minNumParticlesPerCore); reduce(lowParticleCount_m, lowParticleCount_m, OpOr()); } if (ne > 0) { performDestroy(true); } calcBeamParameters(); gatherLoadBalanceStatistics(); if (weHaveEnergyBins()) { const int lastBin = dist_m->getLastEmittedEnergyBin(); for(int i = 0; i < lastBin; i++) { binemitted_m[i] = tmpbinemitted[i]; } } size_t newTotalNum = getLocalNum(); reduce(newTotalNum, newTotalNum, OpAddAssign()); setTotalNum(newTotalNum); return totalNum - newTotalNum; } template double PartBunchBase::getPx(int i) { return 0.0; } template double PartBunchBase::getPy(int i) { return 0.0; } template double PartBunchBase::getPz(int i) { return 0.0; } template double PartBunchBase::getPx0(int i) { return 0.0; } template double PartBunchBase::getPy0(int i) { return 0; } //ff template double PartBunchBase::getX(int i) { return this->R[i](0); } //ff template double PartBunchBase::getY(int i) { return this->R[i](1); } //ff template double PartBunchBase::getZ(int i) { return this->R[i](2); } //ff template double PartBunchBase::getX0(int i) { return 0.0; } //ff template double PartBunchBase::getY0(int i) { return 0.0; } template void PartBunchBase::setZ(int i, double zcoo) { // nothing done here }; template void PartBunchBase::get_bounds(Vector_t &rmin, Vector_t &rmax) { this->getLocalBounds(rmin, rmax); double min[Dim]; double max[Dim]; for (unsigned int i = 0; i < Dim; ++i) { min[i] = rmin[i]; max[i] = rmax[i]; } //FIXME use a min-max function allreduce(&min[0], Dim, std::less()); allreduce(&max[0], Dim, std::greater()); for (unsigned int i = 0; i < Dim; ++i) { rmin[i] = min[i]; rmax[i] = max[i]; } } template void PartBunchBase::getLocalBounds(Vector_t &rmin, Vector_t &rmax) { const size_t localNum = getLocalNum(); if (localNum == 0) { rmin = Vector_t(0.0, 0.0, 0.0); rmax = Vector_t(0.0, 0.0, 0.0); return; } rmin = R[0]; rmax = R[0]; for (size_t i = 1; i < localNum; ++ i) { for (unsigned short d = 0; d < 3u; ++ d) { if (rmin(d) > R[i](d)) rmin(d) = R[i](d); else if (rmax(d) < R[i](d)) rmax(d) = R[i](d); } } } template std::pair PartBunchBase::getBoundingSphere() { Vector_t rmin, rmax; get_bounds(rmin, rmax); std::pair sphere; sphere.first = 0.5 * (rmin + rmax); sphere.second = sqrt(dot(rmax - sphere.first, rmax - sphere.first)); return sphere; } template std::pair PartBunchBase::getLocalBoundingSphere() { Vector_t rmin, rmax; getLocalBounds(rmin, rmax); std::pair sphere; sphere.first = 0.5 * (rmin + rmax); sphere.second = sqrt(dot(rmax - sphere.first, rmax - sphere.first)); return sphere; } template void PartBunchBase::push_back(OpalParticle p) { Inform msg("PartBunch "); create(1); size_t i = getTotalNum(); R[i](0) = p[0]; R[i](1) = p[1]; R[i](2) = p[2]; P[i](0) = p[3]; P[i](1) = p[4]; P[i](2) = p[5]; update(); msg << "Created one particle i= " << i << endl; } template void PartBunchBase::set_part(FVector z, int ii) { R[ii](0) = z[0]; P[ii](0) = z[1]; R[ii](1) = z[2]; P[ii](1) = z[3]; R[ii](2) = z[4]; P[ii](2) = z[5]; } template void PartBunchBase::set_part(OpalParticle p, int ii) { R[ii](0) = p[0]; P[ii](0) = p[1]; R[ii](1) = p[2]; P[ii](1) = p[3]; R[ii](2) = p[4]; P[ii](2) = p[5]; } template OpalParticle PartBunchBase::get_part(int ii) { OpalParticle part; part[0] = R[ii](0); part[1] = P[ii](0); part[2] = R[ii](1); part[3] = P[ii](1); part[4] = R[ii](2); part[5] = P[ii](2); return part; } template void PartBunchBase::maximumAmplitudes(const FMatrix &D, double &axmax, double &aymax) { axmax = aymax = 0.0; OpalParticle part; for(unsigned int ii = 0; ii < getLocalNum(); ii++) { part = get_part(ii); double xnor = D(0, 0) * part.x() + D(0, 1) * part.px() + D(0, 2) * part.y() + D(0, 3) * part.py() + D(0, 4) * part.t() + D(0, 5) * part.pt(); double pxnor = D(1, 0) * part.x() + D(1, 1) * part.px() + D(1, 2) * part.y() + D(1, 3) * part.py() + D(1, 4) * part.t() + D(1, 5) * part.pt(); double ynor = D(2, 0) * part.x() + D(2, 1) * part.px() + D(2, 2) * part.y() + D(2, 3) * part.py() + D(2, 4) * part.t() + D(2, 5) * part.pt(); double pynor = D(3, 0) * part.x() + D(3, 1) * part.px() + D(3, 2) * part.y() + D(3, 3) * part.py() + D(3, 4) * part.t() + D(3, 5) * part.pt(); axmax = std::max(axmax, (xnor * xnor + pxnor * pxnor)); aymax = std::max(aymax, (ynor * ynor + pynor * pynor)); } } template void PartBunchBase::setdT(double dt) { dt_m = dt; } template double PartBunchBase::getdT() const { return dt_m; } template void PartBunchBase::setT(double t) { t_m = t; } template double PartBunchBase::getT() const { return t_m; } template double PartBunchBase::get_sPos() { if(sum(PType != ParticleType::REGULAR)) { const size_t n = getLocalNum(); size_t numPrimBeamParts = 0; double z = 0.0; if(n != 0) { for(size_t i = 0; i < n; i++) { if(PType[i] == ParticleType::REGULAR) { z += R[i](2); numPrimBeamParts++; } } } reduce(z, z, OpAddAssign()); reduce(numPrimBeamParts, numPrimBeamParts, OpAddAssign()); if(numPrimBeamParts != 0) z = z / numPrimBeamParts; return z; } else { return spos_m; } } template void PartBunchBase::set_sPos(double s) { spos_m = s; } template double PartBunchBase::get_gamma() const { return eKin_m / (getM()*1e-6) + 1.0; } template double PartBunchBase::get_meanKineticEnergy() const { return eKin_m; } template Vector_t PartBunchBase::get_origin() const { return rmin_m; } template Vector_t PartBunchBase::get_maxExtent() const { return rmax_m; } template Vector_t PartBunchBase::get_centroid() const { return rmean_m; } template Vector_t PartBunchBase::get_rrms() const { return rrms_m; } template Vector_t PartBunchBase::get_rprms() const { return rprms_m; } template Vector_t PartBunchBase::get_rmean() const { return rmean_m; } template Vector_t PartBunchBase::get_prms() const { return prms_m; } template Vector_t PartBunchBase::get_pmean() const { return pmean_m; } template Vector_t PartBunchBase::get_pmean_Distribution() const { if (dist_m && dist_m->getType() != DistrTypeT::FROMFILE) return dist_m->get_pmean(); double gamma = 0.1 / getM() + 1; // set default 0.1 eV return Vector_t(0, 0, sqrt(std::pow(gamma, 2) - 1)); } template Vector_t PartBunchBase::get_emit() const { return eps_m; } template Vector_t PartBunchBase::get_norm_emit() const { return eps_norm_m; } template Vector_t PartBunchBase::get_hr() const { return hr_m; } template double PartBunchBase::get_Dx() const { return Dx_m; } template double PartBunchBase::get_Dy() const { return Dy_m; } template double PartBunchBase::get_DDx() const { return DDx_m; } template double PartBunchBase::get_DDy() const { return DDy_m; } template void PartBunchBase::set_meshEnlargement(double dh) { dh_m = dh; } template void PartBunchBase::gatherLoadBalanceStatistics() { for(int i = 0; i < Ippl::getNodes(); i++) globalPartPerNode_m[i] = 0; std::size_t localnum = getLocalNum(); gather(&localnum, &globalPartPerNode_m[0], 1); } template size_t PartBunchBase::getLoadBalance(int p) const { return globalPartPerNode_m[p]; } template void PartBunchBase::get_PBounds(Vector_t &min, Vector_t &max) const { bounds(this->P, min, max); } template void PartBunchBase::calcBeamParameters() { using Physics::c; Vector_t eps2, fac, rsqsum, psqsum, rpsum; IpplTimings::startTimer(statParamTimer_m); const size_t locNp = getLocalNum(); const size_t totalNum = getTotalNum(); const double zero = 0.0; get_bounds(rmin_m, rmax_m); if(totalNum == 0) { for(unsigned int i = 0 ; i < Dim; i++) { rmean_m(i) = 0.0; pmean_m(i) = 0.0; rrms_m(i) = 0.0; prms_m(i) = 0.0; eps_norm_m(i) = 0.0; } rprms_m = 0.0; eKin_m = 0.0; eps_m = 0.0; IpplTimings::stopTimer(statParamTimer_m); return; } const size_t intN = calcMoments(); const double N = static_cast(intN); for(unsigned int i = 0 ; i < Dim; i++) { rmean_m(i) = centroid_m[2 * i] / N; pmean_m(i) = centroid_m[(2 * i) + 1] / N; rsqsum(i) = moments_m(2 * i, 2 * i) - N * rmean_m(i) * rmean_m(i); psqsum(i) = moments_m((2 * i) + 1, (2 * i) + 1) - N * pmean_m(i) * pmean_m(i); if(psqsum(i) < 0) psqsum(i) = 0; rpsum(i) = moments_m((2 * i), (2 * i) + 1) - N * rmean_m(i) * pmean_m(i); } eps2 = (rsqsum * psqsum - rpsum * rpsum) / (N * N); rpsum /= N; for(unsigned int i = 0 ; i < Dim; i++) { rrms_m(i) = sqrt(rsqsum(i) / N); prms_m(i) = sqrt(psqsum(i) / N); eps_norm_m(i) = std::sqrt(std::max(eps2(i), zero)); double tmp = rrms_m(i) * prms_m(i); fac(i) = (tmp == 0) ? zero : 1.0 / tmp; } rprms_m = rpsum * fac; Dx_m = moments_m(0, 5) / N; DDx_m = moments_m(1, 5) / N; Dy_m = moments_m(2, 5) / N; DDy_m = moments_m(3, 5) / N; // Find unnormalized emittance. double gamma = 0.0; for(size_t i = 0; i < locNp; i++) gamma += sqrt(1.0 + dot(P[i], P[i])); allreduce(gamma, 1, std::plus()); gamma /= N; calcEMean(); // The computation of the energy spread is an estimation // based on the standard deviation of the longitudinal // momentum: // Var[f(P)] ~= (df/dP)(E[P])^2 Var[P] const double m0 = getM() * 1.E-6; double tmp = 1.0 / std::pow(eKin_m / m0 + 1., 2.0); if (OpalData::getInstance()->isInOPALCyclMode()) { dE_m = prms_m(1) * m0 * sqrt(1.0 - tmp); } else { dE_m = prms_m(2) * m0 * sqrt(1.0 - tmp); } eps_m = eps_norm_m / Vector_t(gamma * sqrt(1.0 - 1.0 / (gamma * gamma))); IpplTimings::stopTimer(statParamTimer_m); } template void PartBunchBase::calcBeamParametersInitial() { using Physics::c; const double N = static_cast(getTotalNum()); if(N == 0) { rmean_m = Vector_t(0.0); pmean_m = Vector_t(0.0); rrms_m = Vector_t(0.0); prms_m = Vector_t(0.0); eps_m = Vector_t(0.0); } else { if(Ippl::myNode() == 0) { // fixme: the following code is crap! // Only use one node as this function will get called only once before // particles have been emitted (at least in principle). Vector_t eps2, fac, rsqsum, psqsum, rpsum; const double zero = 0.0; const double N = static_cast(pbin_m->getNp()); calcMomentsInitial(); for(unsigned int i = 0 ; i < Dim; i++) { rmean_m(i) = centroid_m[2 * i] / N; pmean_m(i) = centroid_m[(2 * i) + 1] / N; rsqsum(i) = moments_m(2 * i, 2 * i) - N * rmean_m(i) * rmean_m(i); psqsum(i) = moments_m((2 * i) + 1, (2 * i) + 1) - N * pmean_m(i) * pmean_m(i); if(psqsum(i) < 0) psqsum(i) = 0; rpsum(i) = moments_m((2 * i), (2 * i) + 1) - N * rmean_m(i) * pmean_m(i); } eps2 = (rsqsum * psqsum - rpsum * rpsum) / (N * N); rpsum /= N; for(unsigned int i = 0 ; i < Dim; i++) { rrms_m(i) = sqrt(rsqsum(i) / N); prms_m(i) = sqrt(psqsum(i) / N); eps_m(i) = sqrt(std::max(eps2(i), zero)); double tmp = rrms_m(i) * prms_m(i); fac(i) = (tmp == 0) ? zero : 1.0 / tmp; } rprms_m = rpsum * fac; } } } template double PartBunchBase::getCouplingConstant() const { return couplingConstant_m; } template void PartBunchBase::setCouplingConstant(double c) { couplingConstant_m = c; } template void PartBunchBase::setCharge(double q) { qi_m = q; if(getTotalNum() != 0) Q = qi_m; else WARNMSG("Could not set total charge in PartBunch::setCharge based on getTotalNum" << endl); } template void PartBunchBase::setChargeZeroPart(double q) { qi_m = q; } template void PartBunchBase::setMass(double mass) { M = mass; } /// \brief Need Ek for the Schottky effect calculation (eV) template double PartBunchBase::getEkin() const { if(dist_m) return dist_m->getEkin(); else return 0.0; } /// \brief Need the work function for the Schottky effect calculation (eV) template double PartBunchBase::getWorkFunctionRf() const { if(dist_m) return dist_m->getWorkFunctionRf(); else return 0.0; } /// \brief Need the laser energy for the Schottky effect calculation (eV) template double PartBunchBase::getLaserEnergy() const { if(dist_m) return dist_m->getLaserEnergy(); else return 0.0; } template double PartBunchBase::getCharge() const { return sum(Q); } template double PartBunchBase::getChargePerParticle() const { return qi_m; } template void PartBunchBase::setSolver(FieldSolver *fs) { fs_m = fs; fs_m->initSolver(this); /** CAN not re-inizialize ParticleLayout this is an IPPL issue */ if(!OpalData::getInstance()->hasBunchAllocated()) { this->initialize(fs_m->getFieldLayout()); // this->setMesh(fs_m->getMesh()); // this->setFieldLayout(fs_m->getFieldLayout()); } } template bool PartBunchBase::hasFieldSolver() { if(fs_m) return fs_m->hasValidSolver(); else return false; } /// \brief Return the fieldsolver type if we have a fieldsolver template std::string PartBunchBase::getFieldSolverType() const { if(fs_m) return fs_m->getFieldSolverType(); else return ""; } template void PartBunchBase::setLPath(double s) { lPath_m = s; } template double PartBunchBase::getLPath() const { return lPath_m; } template void PartBunchBase::setStepsPerTurn(int n) { stepsPerTurn_m = n; } template int PartBunchBase::getStepsPerTurn() const { return stepsPerTurn_m; } template void PartBunchBase::setGlobalTrackStep(long long n) { globalTrackStep_m = n; } template long long PartBunchBase::getGlobalTrackStep() const { return globalTrackStep_m; } template void PartBunchBase::setLocalTrackStep(long long n) { localTrackStep_m = n; } template void PartBunchBase::incTrackSteps() { globalTrackStep_m++; localTrackStep_m++; } template long long PartBunchBase::getLocalTrackStep() const { return localTrackStep_m; } template void PartBunchBase::setNumBunch(int n) { numBunch_m = n; } template int PartBunchBase::getNumBunch() const { return numBunch_m; } template void PartBunchBase::setGlobalMeanR(Vector_t globalMeanR) { globalMeanR_m = globalMeanR; } template Vector_t PartBunchBase::getGlobalMeanR() { return globalMeanR_m; } template void PartBunchBase::setGlobalToLocalQuaternion(Quaternion_t globalToLocalQuaternion) { globalToLocalQuaternion_m = globalToLocalQuaternion; } template Quaternion_t PartBunchBase::getGlobalToLocalQuaternion() { return globalToLocalQuaternion_m; } template void PartBunchBase::setSteptoLastInj(int n) { SteptoLastInj_m = n; } template int PartBunchBase::getSteptoLastInj() { return SteptoLastInj_m; } template double PartBunchBase::calcMeanPhi() { const int emittedBins = pbin_m->getLastemittedBin(); double phi[emittedBins]; double px[emittedBins]; double py[emittedBins]; double meanPhi = 0.0; for(int ii = 0; ii < emittedBins; ii++) { phi[ii] = 0.0; px[ii] = 0.0; py[ii] = 0.0; } for(unsigned int ii = 0; ii < getLocalNum(); ii++) { px[Bin[ii]] += P[ii](0); py[Bin[ii]] += P[ii](1); } reduce(px, px + emittedBins, px, OpAddAssign()); reduce(py, py + emittedBins, py, OpAddAssign()); for(int ii = 0; ii < emittedBins; ii++) { phi[ii] = calculateAngle(px[ii], py[ii]); meanPhi += phi[ii]; INFOMSG("Bin " << ii << " mean phi = " << phi[ii] * 180.0 / pi - 90.0 << "[degree]" << endl); } meanPhi /= emittedBins; INFOMSG("mean phi of all particles " << meanPhi * 180.0 / pi - 90.0 << "[degree]" << endl); return meanPhi; } // this function reset the BinID for each particles according to its current beta*gamma // it is for multi-turn extraction cyclotron with small energy gain // the bin number can be different with the bunch number template bool PartBunchBase::resetPartBinID2(const double eta) { INFOMSG("Before reset Bin: " << endl); calcGammas_cycl(); int maxbin = pbin_m->getNBins(); size_t partInBin[maxbin]; for(int ii = 0; ii < maxbin; ii++) partInBin[ii] = 0; double pMin0 = 1.0e9; double pMin = 0.0; double maxbinIndex = 0; for(unsigned long int n = 0; n < getLocalNum(); n++) { double temp_betagamma = sqrt(pow(P[n](0), 2) + pow(P[n](1), 2)); if(pMin0 > temp_betagamma) pMin0 = temp_betagamma; } reduce(pMin0, pMin, OpMinAssign()); INFOMSG("minimal beta*gamma = " << pMin << endl); double asinh0 = asinh(pMin); for(unsigned long int n = 0; n < getLocalNum(); n++) { double temp_betagamma = sqrt(pow(P[n](0), 2) + pow(P[n](1), 2)); int itsBinID = floor((asinh(temp_betagamma) - asinh0) / eta + 1.0E-6); Bin[n] = itsBinID; if(maxbinIndex < itsBinID) { maxbinIndex = itsBinID; } if(itsBinID >= maxbin) { ERRORMSG("The bin number limit is " << maxbin << ", please increase the energy interval and try again" << endl); return false; } else partInBin[itsBinID]++; } // partInBin only count particle on the local node. pbin_m->resetPartInBin_cyc(partInBin, maxbinIndex); // after reset Particle Bin ID, update mass gamma of each bin again INFOMSG("After reset Bin: " << endl); calcGammas_cycl(); return true; } template double PartBunchBase::getQ() const { return reference->getQ(); } template double PartBunchBase::getM() const { return reference->getM(); } template double PartBunchBase::getP() const { return reference->getP(); } template double PartBunchBase::getE() const { return reference->getE(); } template void PartBunchBase::resetQ(double q) { const_cast(reference)->setQ(q); } template void PartBunchBase::resetM(double m) { const_cast(reference)->setM(m); } template double PartBunchBase::getdE() { return dE_m; } template double PartBunchBase::getInitialBeta() const { return reference->getBeta(); } template double PartBunchBase::getInitialGamma() const { return reference->getGamma(); } template double PartBunchBase::getGamma(int i) { return 0; } template double PartBunchBase::getBeta(int i) { return 0; } template void PartBunchBase::actT() { // do nothing here }; template const PartData *PartBunchBase::getReference() const { return reference; } template double PartBunchBase::getEmissionDeltaT() { return dist_m->getEmissionDeltaT(); } template Quaternion_t PartBunchBase::getQKs3D() { return QKs3D_m; } template void PartBunchBase::setQKs3D(Quaternion_t q) { QKs3D_m=q; } template Vector_t PartBunchBase::getKs3DRefr() { return Ks3DRefr_m; } template void PartBunchBase::setKs3DRefr(Vector_t r) { Ks3DRefr_m=r; } template Vector_t PartBunchBase::getKs3DRefp() { return Ks3DRefp_m; } template void PartBunchBase::setKs3DRefp(Vector_t p) { Ks3DRefp_m=p; } template void PartBunchBase::iterateEmittedBin(int binNumber) { binemitted_m[binNumber]++; } template void PartBunchBase::calcEMean() { const double totalNp = static_cast(getTotalNum()); const double locNp = static_cast(getLocalNum()); eKin_m = 0.0; for(unsigned int k = 0; k < locNp; k++) { eKin_m += sqrt(dot(P[k], P[k]) + 1.0); } eKin_m -= locNp; eKin_m *= getM() * 1.0e-6; reduce(eKin_m, eKin_m, OpAddAssign()); eKin_m /= totalNp; } template void PartBunchBase::correctEnergy(double avrgp_m) { const double totalNp = static_cast(getTotalNum()); const double locNp = static_cast(getLocalNum()); double avrgp = 0.0; for(unsigned int k = 0; k < locNp; k++) avrgp += sqrt(dot(P[k], P[k])); reduce(avrgp, avrgp, OpAddAssign()); avrgp /= totalNp; for(unsigned int k = 0; k < locNp; k++) P[k](2) = P[k](2) - avrgp + avrgp_m; } template Inform &PartBunchBase::print(Inform &os) { if(getTotalNum() != 0) { // to suppress Nan's Inform::FmtFlags_t ff = os.flags(); double lengthUnitConverter = 1; double pathLength = get_sPos(); if (OpalData::getInstance()->isInOPALCyclMode()) { lengthUnitConverter = 0.001; pathLength = getLPath(); } rmax_m *= lengthUnitConverter; rmin_m *= lengthUnitConverter; os << std::scientific; os << level1 << "\n"; os << "* ************** B U N C H ********************************************************* \n"; os << "* NP = " << getTotalNum() << "\n"; os << "* Qtot = " << std::setw(17) << Util::getChargeString(std::abs(sum(Q))) << " " << "Qi = " << std::setw(17) << Util::getChargeString(std::abs(qi_m)) << "\n"; os << "* Ekin = " << std::setw(17) << Util::getEnergyString(eKin_m) << " " << "dEkin = " << std::setw(17) << Util::getEnergyString(dE_m) << "\n"; os << "* rmax = " << Util::getLengthString(rmax_m, 5) << "\n"; os << "* rmin = " << Util::getLengthString(rmin_m, 5) << "\n"; os << "* rms beam size = " << Util::getLengthString(rrms_m, 5) << "\n"; os << "* rms momenta = " << std::setw(12) << std::setprecision(5) << prms_m << " [beta gamma]\n"; os << "* mean position = " << Util::getLengthString(rmean_m, 5) << "\n"; os << "* mean momenta = " << std::setw(12) << std::setprecision(5) << pmean_m << " [beta gamma]\n"; os << "* rms emittance = " << std::setw(12) << std::setprecision(5) << eps_m << " (not normalized)\n"; os << "* rms correlation = " << std::setw(12) << std::setprecision(5) << rprms_m << "\n"; os << "* hr = " << Util::getLengthString(get_hr(), 5) << "\n"; os << "* dh = " << std::setw(13) << std::setprecision(5) << dh_m * 100 << " [%]\n"; os << "* t = " << std::setw(17) << Util::getTimeString(getT()) << " " << "dT = " << std::setw(17) << Util::getTimeString(getdT()) << "\n"; os << "* spos = " << std::setw(17) << Util::getLengthString(pathLength) << "\n"; os << "* ********************************************************************************** " << endl; os.flags(ff); rmax_m /= lengthUnitConverter; rmin_m /= lengthUnitConverter; } return os; } template size_t PartBunchBase::calcMoments() { double part[2 * Dim]; const unsigned long localNum = getLocalNum(); /* 2 * Dim centroids + Dim * ( 2 * Dim + 1 ) 2nd moments * --> 1st order moments: 0, ..., 2 * Dim - 1 * --> 2nd order moments: 2 * Dim, ..., Dim * ( 2 * Dim + 1 ) * * For a 6x6 matrix we have each 2nd order moment (except diagonal * entries) twice. We only store the upper half of the matrix. */ std::vector loc_moments(2 * Dim + Dim * ( 2 * Dim + 1 )); long int totalNum = this->getTotalNum(); if (OpalData::getInstance()->isInOPALCyclMode()) { for(unsigned long k = 0; k < localNum; ++ k) { if (ID[k] == 0) { part[1] = P[k](0); part[3] = P[k](1); part[5] = P[k](2); part[0] = R[k](0); part[2] = R[k](1); part[4] = R[k](2); unsigned int l = 2 * Dim; for (unsigned int i = 0; i < 2 * Dim; ++i) { loc_moments[i] -= part[i]; for(unsigned int j = 0; j <= i; j++) { loc_moments[l++] -= part[i] * part[j]; } } --totalNum; break; } } allreduce(totalNum, 1, std::less()); } for(unsigned long k = 0; k < localNum; ++ k) { part[1] = P[k](0); part[3] = P[k](1); part[5] = P[k](2); part[0] = R[k](0); part[2] = R[k](1); part[4] = R[k](2); unsigned int l = 2 * Dim; for (unsigned int i = 0; i < 2 * Dim; ++i) { loc_moments[i] += part[i]; for(unsigned int j = 0; j <= i; j++) { loc_moments[l++] += part[i] * part[j]; } } } allreduce(&loc_moments[0], loc_moments.size(), std::plus()); // copy to member variables for (unsigned int i = 0; i< 2 * Dim; ++i) centroid_m[i] = loc_moments[i]; unsigned int l = 2 * Dim; for (unsigned int i = 0; i < 2 * Dim; ++i) { for(unsigned int j = 0; j <= i; j++) { moments_m(i, j) = loc_moments[l++]; moments_m(j, i) = moments_m(i, j); } } return totalNum; } template void PartBunchBase::calcMomentsInitial() { double part[2 * Dim]; for(unsigned int i = 0; i < 2 * Dim; ++i) { centroid_m[i] = 0.0; for(unsigned int j = 0; j <= i; ++j) { moments_m(i, j) = 0.0; moments_m(j, i) = moments_m(i, j); } } for(size_t k = 0; k < pbin_m->getNp(); k++) { for(int binNumber = 0; binNumber < pbin_m->getNBins(); binNumber++) { std::vector p; if(pbin_m->getPart(k, binNumber, p)) { part[0] = p.at(0); part[1] = p.at(3); part[2] = p.at(1); part[3] = p.at(4); part[4] = p.at(2); part[5] = p.at(5); for(unsigned int i = 0; i < 2 * Dim; ++i) { centroid_m[i] += part[i]; for(unsigned int j = 0; j <= i; ++j) { moments_m(i, j) += part[i] * part[j]; } } } } } for(unsigned int i = 0; i < 2 * Dim; ++i) { for(unsigned int j = 0; j < i; ++j) { moments_m(j, i) = moments_m(i, j); } } } // angle range [0~2PI) degree template double PartBunchBase::calculateAngle(double x, double y) { double thetaXY = atan2(y, x); return thetaXY >= 0 ? thetaXY : thetaXY + Physics::two_pi; } template Inform &operator<<(Inform &os, PartBunchBase &p) { return p.print(os); } /* * Virtual member functions */ template void PartBunchBase::runTests() { throw OpalException("PartBunchBase::runTests() ", "No test supported."); } template void PartBunchBase::resetInterpolationCache(bool clearCache) { } template void PartBunchBase::swap(unsigned int i, unsigned int j) { if (i >= getLocalNum() || j >= getLocalNum() || i == j) return; std::swap(R[i], R[j]); std::swap(P[i], P[j]); std::swap(Q[i], Q[j]); std::swap(M[i], M[j]); std::swap(Phi[i], Phi[j]); std::swap(Ef[i], Ef[j]); std::swap(Eftmp[i], Eftmp[j]); std::swap(Bf[i], Bf[j]); std::swap(Bin[i], Bin[j]); std::swap(dt[i], dt[j]); std::swap(PType[i], PType[j]); std::swap(TriID[i], TriID[j]); } template void PartBunchBase::setBCAllPeriodic() { throw OpalException("PartBunchBase::setBCAllPeriodic() ", "Not supported BC."); } template void PartBunchBase::setBCAllOpen() { throw OpalException("PartBunchBase::setBCAllOpen() ", "Not supported BC."); } template void PartBunchBase::setBCForDCBeam() { throw OpalException("PartBunchBase::setBCForDCBeam() ", "Not supported BC."); } template void PartBunchBase::updateFields(const Vector_t& hr, const Vector_t& origin) { } template void PartBunchBase::setup(AbstractParticle* pb) { pb->addAttribute(P); pb->addAttribute(Q); pb->addAttribute(M); pb->addAttribute(Phi); pb->addAttribute(Ef); pb->addAttribute(Eftmp); pb->addAttribute(Bf); pb->addAttribute(Bin); pb->addAttribute(dt); pb->addAttribute(PType); pb->addAttribute(TriID); boundpTimer_m = IpplTimings::getTimer("Boundingbox"); boundpBoundsTimer_m = IpplTimings::getTimer("Boundingbox-bounds"); boundpUpdateTimer_m = IpplTimings::getTimer("Boundingbox-update"); statParamTimer_m = IpplTimings::getTimer("Compute Statistics"); selfFieldTimer_m = IpplTimings::getTimer("SelfField total"); histoTimer_m = IpplTimings::getTimer("Histogram"); distrCreate_m = IpplTimings::getTimer("Create Distr"); distrReload_m = IpplTimings::getTimer("Load Distr"); globalPartPerNode_m = std::unique_ptr(new size_t[Ippl::getNodes()]); lossDs_m = std::unique_ptr(new LossDataSink(std::string("GlobalLosses"), !Options::asciidump)); pmsg_m.release(); // f_stream.release(); /* if(Ippl::getNodes() == 1) { f_stream = std::unique_ptr(new ofstream); f_stream->open("data/dist.dat", ios::out); pmsg_m = std::unique_ptr(new Inform(0, *f_stream, 0)); } */ // set the default IPPL behaviour setMinimumNumberOfParticlesPerCore(0); } template size_t PartBunchBase::getTotalNum() const { return pbase->getTotalNum(); } template size_t PartBunchBase::getLocalNum() const { return pbase->getLocalNum(); } template size_t PartBunchBase::getDestroyNum() const { return pbase->getDestroyNum(); } template size_t PartBunchBase::getGhostNum() const { return pbase->getGhostNum(); } template void PartBunchBase::setTotalNum(size_t n) { pbase->setTotalNum(n); } template void PartBunchBase::setLocalNum(size_t n) { pbase->setLocalNum(n); } template unsigned int PartBunchBase::getMinimumNumberOfParticlesPerCore() const { return pbase->getMinimumNumberOfParticlesPerCore(); } template void PartBunchBase::setMinimumNumberOfParticlesPerCore(unsigned int n) { pbase->setMinimumNumberOfParticlesPerCore(n); } template ParticleLayout & PartBunchBase::getLayout() { return pbase->getLayout(); } template const ParticleLayout& PartBunchBase::getLayout() const { return pbase->getLayout(); } template bool PartBunchBase::getUpdateFlag(UpdateFlags f) const { return pbase->getUpdateFlag(f); } template void PartBunchBase::setUpdateFlag(UpdateFlags f, bool val) { pbase->setUpdateFlag(f, val); } template bool PartBunchBase::singleInitNode() const { return pbase->singleInitNode(); } template void PartBunchBase::resetID() { pbase->resetID(); } template void PartBunchBase::update() { pbase->update(); } template void PartBunchBase::update(const ParticleAttrib& canSwap) { pbase->update(canSwap); } template void PartBunchBase::createWithID(unsigned id) { pbase->createWithID(id); } template void PartBunchBase::create(size_t M) { pbase->create(M); } template void PartBunchBase::globalCreate(size_t np) { pbase->globalCreate(np); } template void PartBunchBase::destroy(size_t M, size_t I, bool doNow) { pbase->destroy(M, I, doNow); } template void PartBunchBase::performDestroy(bool updateLocalNum) { pbase->performDestroy(updateLocalNum); } template void PartBunchBase::ghostDestroy(size_t M, size_t I) { pbase->ghostDestroy(M, I); } template void PartBunchBase::setBeamFrequency(double f) { periodLength_m = Physics::c / f; } template FMatrix PartBunchBase::getSigmaMatrix() { const double N = static_cast(this->getTotalNum()); Vektor rpmean; for (unsigned int i = 0; i < Dim; i++) { rpmean(2*i)= rmean_m(i); rpmean((2*i)+1)= pmean_m(i); } FMatrix sigmaMatrix = moments_m / N; for (unsigned int i = 0; i < 2 * Dim; i++) { for (unsigned int j = 0; j <= i; j++) { sigmaMatrix[i][j] = moments_m(i, j) - rpmean(i) * rpmean(j); sigmaMatrix[j][i] = sigmaMatrix[i][j]; } } return sigmaMatrix; } #endif