19#ifndef OPAL_PartBunch_HPP
20#define OPAL_PartBunch_HPP
29#include "Particle/ParticleAttrib.h"
30#include "Particle/ParticleLayout.h"
38#include "PoissonSolvers/FFTOpenPoissonSolver.h"
39#include "PoissonSolvers/FFTPeriodicPoissonSolver.h"
40#include "PoissonSolvers/P3MSolver.h"
42#include "PoissonSolvers/PoissonCG.h"
44using ippl::detail::ConditionalType, ippl::detail::VariantFromConditionalTypes;
46template <
typename T =
double,
unsigned Dim = 3>
50template <
typename T =
double,
unsigned Dim = 3>
53template <
typename T =
double,
unsigned Dim = 3>
55 ConditionalType<Dim == 3, ippl::FFTOpenPoissonSolver<VField_t<T, Dim>,
Field_t<Dim>>>;
57template <
typename T =
double,
unsigned Dim = 3>
61template <
class PLayout,
typename T,
unsigned Dim = 3>
62class PartBunch :
public ippl::ParticleBase<PLayout> {
63 using Base = ippl::ParticleBase<PLayout>;
205 this->addAttribute(
Q);
206 this->addAttribute(
M);
207 this->addAttribute(
P);
208 this->addAttribute(
E);
209 this->addAttribute(
Phi);
210 this->addAttribute(
Ef);
211 this->addAttribute(
Eftmp);
212 this->addAttribute(
Bf);
213 this->addAttribute(
Bin);
214 this->addAttribute(
dt);
219 for (
unsigned int i = 0; i <
Dim; i++) {
263 <<
"Could not set total charge in PartBunch::setCharge based on this->getTotalNum"
372 for (
unsigned int i = 0; i <
Dim; i++)
373 grid[i] = domain[i].length();
391 bool fromAnalyticDensity =
false;
392 bool res =
orb.binaryRepartition(this->
R, fl, fromAnalyticDensity);
395 std::cout <<
"Could not repartition!" << std::endl;
404 std::vector<int> res(ippl::Comm->size());
405 double threshold = 1.0;
406 double equalPart = (double)totalP / ippl::Comm->size();
407 double dev = std::abs((
double)this->
getLocalNum() - equalPart) / totalP;
408 if (dev > threshold) {
411 MPI_Allgather(&local, 1, MPI_INT, res.data(), 1, MPI_INT, ippl::Comm->getCommunicator());
413 for (
unsigned int i = 0; i < res.size(); i++) {
422 for (
int i = 0; i < ippl::Comm->size(); i++)
455 static IpplTimings::TimerRef tupdateLayout = IpplTimings::getTimer(
"updateLayout");
456 IpplTimings::startTimer(tupdateLayout);
457 this->EFD_m.updateLayout(fl);
458 this->EFDMag_m.updateLayout(fl);
462 layout.updateLayout(fl, mesh);
463 IpplTimings::stopTimer(tupdateLayout);
464 static IpplTimings::TimerRef tupdatePLayout = IpplTimings::getTimer(
"updatePB");
465 IpplTimings::startTimer(tupdatePLayout);
467 IpplTimings::stopTimer(tupdatePLayout);
486 const int dimIdx = (
dcBeam_m ? 2 : 3);
499 for (
int i = 0; i < dimIdx; i++) {
501 if (length < 1e-10) {
514 for (
int i = 0; i < dimIdx; ++i) {
542 std::vector<size_t> tmpbinemitted;
552 if (haveEnergyBins) {
555 for (
unsigned int i = 0; i < localNum; i++) {
556 if (this->
Bin(i) < 0) {
560 }
else if (haveEnergyBins) {
561 tmpbinemitted[this->
Bin(i)]++;
575 std::unique_ptr<size_t[]> tmpbinemitted;
584 tmpbinemitted[i] = 0;
586 for (
unsigned int i = 0; i < localNum; i++) {
587 if (this->
Bin(i) < 0) {
591 tmpbinemitted[this->
Bin(i)]++;
594 Inform dmsg(
"destroy: ", INFORM_ALL_NODES);
595 for (
size_t i = 0; i < localNum; i++) {
596 if ((this->
Bin(i) < 0)) {
614 ippl::Comm->reduce(newTotalNum, newTotalNum, 1, std::plus<size_t>());
619 return totalNum - newTotalNum;
643 this->setParticleBC(ippl::BC::PERIODIC);
657 for (
unsigned int i = 0; i <
Dim; i++)
658 nr_m[i] = domain[i].length();
660 for (
int i = 0; i < 3; i++)
661 hr_m[i] = (ur[i] - ll[i]) /
nr_m[i];
678 void swap(
unsigned int i,
unsigned int j) {
682 std::swap(this->
R(i), this->
R(j));
683 std::swap(this->
P(i), this->
P(j));
684 std::swap(this->
Q(i), this->
Q(j));
685 std::swap(this->
M(i), this->
M(j));
686 std::swap(this->
Phi(i), this->
Phi(j));
707 ippl::Comm->barrier();
708 std::cout <<
"Rank " << ippl::Comm->rank() <<
" has "
710 <<
" percent of the total particles " << std::endl;
711 ippl::Comm->barrier();
716 bool hasToReset =
false;
722 if (use_dt_per_particle)
741 std::size_t localnum = 0;
744 for (
unsigned long k = 0; k < this->
getLocalNum(); ++k)
745 if (std::abs(this->
R(k)(0) - meanR(0)) > x(0)
746 || std::abs(this->
R(k)(1) - meanR(1)) > x(1)
747 || std::abs(this->
R(k)(2) - meanR(2)) > x(2)) {
753 size_t npOutside = std::accumulate(
755 std::plus<size_t>());
770 unsigned int nBins, std::vector<double>& lineDensity, std::pair<double, double>& meshInfo) {
780 double length = rmax(2) - rmin(2);
781 double zmin = rmin(2) -
dh_m * length, zmax = rmax(2) +
dh_m * length;
782 double hz = (zmax - zmin) / (nBins - 2);
783 double perMeter = 1.0 / hz;
786 lineDensity.resize(nBins, 0.0);
787 std::fill(lineDensity.begin(), lineDensity.end(), 0.0);
790 for (
unsigned int i = 0; i < lN; ++i) {
791 const double z = this->
R(i)(2) - 0.5 * hz;
792 unsigned int idx = (z - zmin) / hz;
793 double tau = (z - zmin) / hz - idx;
802 meshInfo.first = zmin;
803 meshInfo.second = hz;
871 Inform::FmtFlags_t ff = os.flags();
875 os << std::scientific;
876 os << level1 <<
"\n";
877 os <<
"* ************** B U N C H "
878 "********************************************************* \n";
911 "********************************************************************************** "
923 auto view =
P.getView();
927 Kokkos::parallel_reduce(
928 "Particle Energy", view.extent(0),
929 KOKKOS_LAMBDA(
const int i,
double& valL) {
930 double myVal =
dot(view(i), view(i)).apply();
933 Kokkos::Sum<double>(Energy));
936 double gEnergy = 0.0;
938 MPI_Reduce(&Energy, &gEnergy, 1, MPI_DOUBLE, MPI_SUM, 0, ippl::Comm->getCommunicator());
940 Inform csvout(NULL,
"data/energy.csv", Inform::APPEND);
941 csvout.precision(10);
942 csvout.setf(std::ios::scientific, std::ios::floatfield);
944 csvout << iteration <<
" " << gEnergy << endl;
946 ippl::Comm->barrier();
958 gather(this->E,
EFD_m, this->
R);
965 Inform m(
"scatter ");
970 static IpplTimings::TimerRef sumTimer = IpplTimings::getTimer(
"CheckCharge");
971 IpplTimings::startTimer(sumTimer);
974 unsigned int Total_particles = 0;
975 unsigned int local_particles = this->
getLocalNum();
978 &local_particles, &Total_particles, 1, MPI_UNSIGNED, MPI_SUM, 0,
979 ippl::Comm->getCommunicator());
981 double rel_error = std::fabs((
Q_m - Q_grid) /
Q_m);
982 m <<
"Rel. error in charge conservation = " << rel_error << endl;
984 if (ippl::Comm->rank() == 0) {
985 if (Total_particles != totalP || rel_error > 1e-10) {
986 std::cout <<
"Total particles in the sim. " << totalP <<
" "
987 <<
"after update: " << Total_particles << std::endl;
988 std::cout <<
"Total particles not matched in iteration: " << iteration << std::endl;
989 std::cout <<
"Q grid: " << Q_grid <<
"Q particles: " <<
Q_m << std::endl;
990 std::cout <<
"Rel. error in charge conservation: " << rel_error << std::endl;
995 IpplTimings::stopTimer(sumTimer);
1058 &local_particles, &total_particles, 1, MPI_UNSIGNED_LONG, MPI_SUM, 0,
1059 ippl::Comm->getCommunicator());
1072 return pbin_m->getLastemittedBin();
1093 return (
pbin_m !=
nullptr);
1165 double min[2 *
Dim];
1167 for (
unsigned int i = 0; i <
Dim; ++i) {
1168 min[2 * i] = rmin[i];
1169 min[2 * i + 1] = -rmax[i];
1174 for (
unsigned int i = 0; i <
Dim; ++i) {
1175 rmin[i] = min[2 * i];
1176 rmax[i] = -min[2 * i + 1];
1182 if (localNum == 0) {
1183 double maxValue = 1e8;
1191 for (
size_t i = 1; i < localNum; ++i) {
1192 for (
unsigned short d = 0; d < 3u; ++d) {
1193 if (rmin(d) > this->
R(i)(d))
1194 rmin(d) = this->
R(i)(d);
1195 else if (rmax(d) < this->
R(i)(d))
1196 rmax(d) = this->
R(i)(d);
1205 std::pair<Vector_t<T, Dim>,
double> sphere;
1206 sphere.first = 0.5 * (rmin + rmax);
1207 sphere.second = std::sqrt(
dot(rmax - sphere.first, rmax - sphere.first));
1216 std::pair<Vector_t<T, Dim>,
double> sphere;
1217 sphere.first = 0.5 * (rmin + rmax);
1218 sphere.second = std::sqrt(
dot(rmax - sphere.first, rmax - sphere.first));
1224 bounds(this->P, min, max);
double dot(const Vector3D &lhs, const Vector3D &rhs)
Vector dot product.
VariantFromConditionalTypes< FFTSolver_t< T, Dim >, P3MSolver_t< T, Dim >, OpenSolver_t< T, Dim > > Solver_t
ConditionalType< Dim==2||Dim==3, ippl::FFTPeriodicPoissonSolver< VField_t< T, Dim >, Field_t< Dim > > > FFTSolver_t
PartBunch< PLayout_t< double, 3 >, double, 3 > PartBunch_t
ConditionalType< Dim==3, ippl::FFTOpenPoissonSolver< VField_t< T, Dim >, Field_t< Dim > > > OpenSolver_t
ConditionalType< Dim==3, ippl::P3MSolver< VField_t< T, Dim >, Field_t< Dim > > > P3MSolver_t
ippl::FieldLayout< Dim > FieldLayout_t
ippl::Field< double, Dim, ViewArgs... > Field_t
ippl::Field< ippl::Vector< T, Dim >, Dim, ViewArgs... > VField_t
ippl::UniformCartesian< double, 3 > Mesh_t
ippl::Vector< T, Dim > Vector_t
ippl::Field< T, Dim, Mesh_t< Dim >, Centering_t< Dim >, ViewArgs... > Field
ippl::detail::size_type size_type
ippl::ParticleAttrib< T > ParticleAttrib
ippl::OrthogonalRecursiveBisection< Field< double, Dim >, T > ORB
int getSteptoLastInj() const
long long localTrackStep_m
std::array< bool, Dim > isParallel_m
ParticleAttrib< int > bunchNum
void updateDomainLength(Vector_t< int, 3 > &grid)
void gatherLoadBalanceStatistics()
void initializeORB(FieldLayout_t< Dim > &fl, Mesh_t< Dim > &mesh)
Vector_t< T, Dim > get_hr() const
ParticleAttrib< double > Phi
double getMassPerParticle() const
void setBeamFrequency(double v)
void setMass(double mass)
Vector_t< T, Dim > get_prms() const
void getLocalBounds(Vector_t< T, Dim > &rmin, Vector_t< T, Dim > &rmax) const
double centroid_m[2 *Dim]
void updateFields(const Vector_t< T, Dim > &, const Vector_t< T, Dim > &origin)
Vector_t< double, Dim > rmin_m
VField_t< double, Dim > eg_m
Solver_t< double, Dim > solver_m
ParticleLayout< double, 3 > & getLayout()
size_t getNumberOfEmissionSteps()
void repartition(FieldLayout_t< Dim > &fl, Mesh_t< Dim > &mesh)
void setBinCharge(int bin, double q)
Set the charge of one bin to the value of q and all other to zero.
std::unique_ptr< Inform > pmsg_m
const Mesh_t< Dim > & getMesh() const
Field< double, Dim > phi_m
UnitState_t stateOfLastBoundP_m
Vector_t< double, Dim > globalMeanR_m
const PartData * reference
void setChargeZeroPart(double q)
Vector_t< T, Dim > get_99_99Percentile() const
std::pair< Vector_t< double, 3 >, Vector_t< double, 3 > > VectorPair_t
ParticleAttrib< Vector_t< double, Dim > > Ef
size_t calcNumPartsOutside(Vector_t< T, Dim > x)
returns the number of particles outside of a box defined by x
Vector_t< T, Dim > get_normalizedEps_99Percentile() const
PartBunch & operator=(const PartBunch &)=delete
void setLocalTrackStep(long long n)
step in a TRACK command
int getLastEmittedEnergyBin()
size_t getLoadBalance(int p) const
void setPType(const std::string &type)
void calcBeamParameters()
Vector_t< T, Dim > get_maxExtent() const
Vector_t< T, Dim > get_pmean() const
ParticleAttrib< int > Bin
double getQ() const
Access to reference data.
void swap(unsigned int i, unsigned int j)
std::pair< Vector_t< T, Dim >, double > getLocalBoundingSphere()
ParticleAttrib< double > M
bool resetPartBinID2(const double eta)
void setBinCharge(int bin)
Set the charge of all other the ones in bin to zero.
void resetInterpolationCache(bool clearCache=false)
void resetQ(double q)
Set reference data.
Vector_t< double, Dim > rmax_m
void setPBins(PartBins *pbin)
std::pair< Vector_t< T, Dim >, double > getBoundingSphere()
void switchToUnitlessPositions(bool use_dt_per_particle=false)
double getCharge() const
get the total charge per simulation particle
double getInitialBeta() const
void get_PBounds(Vector_t< T, Dim > &min, Vector_t< T, Dim > &max) const
Vector_t< T, Dim > get_rrms() const
std::unique_ptr< size_t[]> binemitted_m
Vector_t< T, Dim > get_halo() const
Vector_t< T, Dim > get_origin() const
Vector_t< double, Dim > RefPartR_m
Vector_t< double, Dim > nr_m
short getNumBunch() const
double getRho(int x, int y, int z)
void calcBeamParametersInitial()
double getGamma(int i) const
Vector_t< T, Dim > get_68Percentile() const
bool balance(unsigned int totalP)
void setTEmission(double t)
void setLocalBinCount(size_t num, int bin)
ParticleAttrib< double > dt
double get_meanKineticEnergy()
int getNumberOfEnergyBins()
long long getLocalTrackStep() const
void gatherStatistics(unsigned int totalP)
void get_bounds(Vector_t< T, Dim > &rmin, Vector_t< T, Dim > &rmax) const
double calculateAngle(double x, double y)
long long globalTrackStep_m
size_t getLocalNum() const
std::vector< size_t > bunchTotalNum_m
void setZ(int i, double zcoo)
double calcMeanPhi()
calculate average angle of longitudinal direction of bins
Vector_t< double, Dim > R(size_t i)
Vector_t< T, Dim > get_99Percentile() const
Vector_t< T, Dim > get_normalizedEps_99_99Percentile() const
void calcLineDensity(unsigned int nBins, std::vector< double > &lineDensity, std::pair< double, double > &meshInfo)
calculates the 1d line density (not normalized) and append it to a file.
Vector_t< T, Dim > get_rmean() const
double getChargePerParticle() const
get the macro particle charge
ParticleAttrib< Vector_t< double, Dim > > P
Vector_t< T, Dim > getGlobalMeanR()
void setSteptoLastInj(int n)
ParticleAttrib< Vector_t< double, Dim > > Eftmp
void setStepsPerTurn(int n)
Vector_t< T, Dim > get_pmean_Distribution() const
Vector_t< T, Dim > get_emit() const
ippl::BConds< Field< T, Dim >, Dim > bc_type
const PartData * getReference() const
VField_t< double, Dim > EFD_m
Vector_t< T, Dim > get_95Percentile() const
VectorPair_t getEExtrema()
std::unique_ptr< std::ofstream > f_stream
void setEnergyBins(int numberOfEnergyBins)
Vector_t< T, Dim > get_centroid() const
void setGlobalTrackStep(long long n)
step in multiple TRACK commands
PartBunch(PLayout &pl, Vector_t< double, Dim > hr, Vector_t< double, Dim > rmin, Vector_t< double, Dim > rmax, std::array< bool, Dim > decomp, double Qtot)
Vector_t< double, Dim > hr_m
long long getGlobalTrackStep() const
void scatterCIC(unsigned int totalP, int iteration)
void initialize(FieldLayout_t< Dim > &fl, Mesh_t< Dim > &mesh)
ParticleAttrib< Vector_t< double, Dim > > E
double getInitialGamma() const
std::vector< size_t > bunchLocalNum_m
void updateLayout(FieldLayout_t< Dim > &fl, Mesh_t< Dim > &mesh)
Inform & print(Inform &os)
double getBeta(int i) const
FieldLayout_t< Dim > & getFieldLayout()
Vector_t< T, Dim > get_normalizedEps_95Percentile() const
void switchOffUnitlessPositions(bool use_dt_per_particle=false)
double couplingConstant_m
void setMassZeroPart(double mass)
Vector_t< T, Dim > get_normalizedEps_68Percentile() const
double getCouplingConstant() const
size_t getTotalNum() const
void calcGammas()
Compute the gammas of all bins.
void set_meshEnlargement(double dh)
void computeSelfFields(int b)
double getEmissionDeltaT()
Vector_t< double, Dim > RefPartP_m
Vector_t< T, Dim > get_rprms() const
void setCouplingConstant(double c)
void setGlobalMeanR(Vector_t< T, Dim > globalMeanR)
bool getFieldSolverType() const
Return the fieldsolver type if we have a fieldsolver.
void dumpData(int iteration)
ippl::ParticleBase< PLayout > Base
void setNumBunch(short n)
int getStepsPerTurn() const
ParticleAttrib< double > Q
double getBinGamma(int bin)
Get gamma of one bin.
Vector_t< T, Dim > get_norm_emit() const
std::unique_ptr< size_t[]> globalPartPerNode_m
ParticleAttrib< Vector_t< double, Dim > > Bf
size_t emitParticles(double eZ)
Emit particles in the given bin i.e. copy the particles from the bin structure into the particle cont...
CoordinateSystemTrafo toLabTrafo_m
std::unique_ptr< double[]> bingamma_m