2#ifndef OPAL_PARTICLE_CONTAINER_H
3#define OPAL_PARTICLE_CONTAINER_H
13#include "Manager/BaseManager.h"
61template <
typename T,
unsigned Dim = 3>
63 :
public ippl::ParticleBase<
64 ippl::ParticleSpatialLayout<T, Dim>, Kokkos::DefaultExecutionSpace::memory_space> {
76 using Base = ippl::ParticleBase<
77 ippl::ParticleSpatialLayout<T, Dim>, Kokkos::DefaultExecutionSpace::memory_space>;
96 using qm_view_type =
typename ippl::ParticleAttrib<double>::view_type;
110 return QAttr.getView();
120 return MAttr.getView();
126 ippl::ParticleAttrib<double>
dt;
129 ippl::ParticleAttrib<double>
Phi;
132 ippl::ParticleAttrib<bin_index_type>
Bin;
138 typename Base::particle_position_type
P;
141 typename Base::particle_position_type
E;
147 typename Base::particle_position_type
B;
155 ippl::ParticleAttrib<spin_vector_type>
Pol;
167 QView_m(
"ParticleContainer::QView_m", 1),
168 MView_m(
"ParticleContainer::MView_m", 1),
170 this->initialize(
pl_m);
173 Kokkos::deep_copy(
QView_m, 0.0);
174 Kokkos::deep_copy(
MView_m, 0.0);
181 this->addAttribute(
dt);
182 this->addAttribute(
Phi);
183 this->addAttribute(
Bin);
184 this->addAttribute(
P);
185 this->addAttribute(
E);
186 this->addAttribute(
B);
189 this->addAttribute(
QAttr);
190 this->addAttribute(
MAttr);
193 this->addAttribute(
Pol);
201 const size_t nLoc = this->getLocalNum();
235 "ParticleContainer::updateMoments",
236 "BunchStateHandler not set in ParticleContainer (containerState is null).");
239 size_t Np = this->getTotalNum();
240 Np = (Np == 0) ? 1 : Np;
243 size_t Nlocal = this->getLocalNum();
263 size_t Nlocal = this->getLocalNum();
302 size_t Np = this->getTotalNum();
303 Np = (Np == 0) ? 1 : Np;
306 size_t Nlocal = this->getLocalNum();
320 auto view =
QAttr.getView();
325 Kokkos::parallel_for(
326 "ParticleContainer::setQ", n,
327 KOKKOS_LAMBDA(
const size_type i) { view(i) = q; });
337 auto view =
QAttr.getView();
338 if (view.extent(0) == 0) {
342 Kokkos::deep_copy(q, Kokkos::subview(view, 0));
346 Kokkos::deep_copy(q, Kokkos::subview(
QView_m, 0));
362 auto view =
MAttr.getView();
365 Kokkos::parallel_for(
366 "ParticleContainer::setM", n,
367 KOKKOS_LAMBDA(
const size_type i) { view(i) = m; });
377 auto view =
MAttr.getView();
378 if (view.extent(0) == 0) {
382 Kokkos::deep_copy(m, Kokkos::subview(view, 0));
386 Kokkos::deep_copy(m, Kokkos::subview(
MView_m, 0));
452 std::copysign(1.0, bunchDT) * std::sqrt(R[0] * R[0] + R[1] * R[1] + R[2] * R[2]);
461 template <
typename Pusher>
467 sPos_m = pathLengthTarget;
485 auto dtView =
dt.getView();
492 auto qView =
QAttr.getView();
493 Kokkos::parallel_for(
494 "ParticleContainer::scaleDtByCharge(attrs)", n,
495 KOKKOS_LAMBDA(
const size_type i) { dtView(i) *= qView(i); });
498 Kokkos::parallel_for(
499 "ParticleContainer::scaleDtByCharge(single)", n,
500 KOKKOS_LAMBDA(
const size_type i) { dtView(i) *= QView(0); });
513 auto dtView =
dt.getView();
520 auto qView =
QAttr.getView();
521 Kokkos::parallel_for(
522 "ParticleContainer::unscaleDtByCharge(attrs)", n,
523 KOKKOS_LAMBDA(
const size_type i) { dtView(i) /= qView(i); });
526 Kokkos::parallel_for(
527 "ParticleContainer::unscaleDtByCharge(single)", n,
528 KOKKOS_LAMBDA(
const size_type i) { dtView(i) /= QView(0); });
543 "ParticleContainer::switchToUnitlessPositions",
544 "ParticleContainer is already in unitless positions!");
546 auto Rview = this->R.getView();
547 auto dtview = this->dt.getView();
548 const size_type nLocal = this->getLocalNum();
549 Kokkos::parallel_for(
550 "ParticleContainer::switchToUnitlessPositions", nLocal,
566 "ParticleContainer::switchOffUnitlessPositions",
567 "ParticleContainer is already in physical positions!");
569 auto Rview = this->R.getView();
570 auto dtview = this->dt.getView();
571 const size_type nLocal = this->getLocalNum();
572 Kokkos::parallel_for(
573 "ParticleContainer::switchOffUnitlessPositions", nLocal,
601 if (nLocal == 0 && this->getTotalNum() == 0)
return 0;
602 if (sigmasAway <= 0.0)
return 0;
613 double lb0 = meanR[0] - sigmasAway * rmsR[0];
614 double lb1 = meanR[1] - sigmasAway * rmsR[1];
615 double lb2 = meanR[2] - sigmasAway * rmsR[2];
616 double ub0 = meanR[0] + sigmasAway * rmsR[0];
617 double ub1 = meanR[1] + sigmasAway * rmsR[1];
618 double ub2 = meanR[2] + sigmasAway * rmsR[2];
621 auto Rview = this->R.getView();
624 Kokkos::parallel_reduce(
625 "ParticleContainer::markParticlesOutside", nLocal,
627 bool outside = (Rview(i)[0] < lb0 || Rview(i)[0] > ub0)
628 || (Rview(i)[1] < lb1 || Rview(i)[1] > ub1)
629 || (Rview(i)[2] < lb2 || Rview(i)[2] > ub2);
630 const bool newlyMarked = outside && !invalid(i);
631 invalid(i) = invalid(i) || outside;
632 count += newlyMarked ? 1 : 0;
638 ippl::Comm->allreduce(localMarkedNum, globalMarkedNum, 1, std::plus<size_type>());
639 return globalMarkedNum;
656 Inform m(
"ParticleContainer::createParticles");
660 size_type oldLocalNum = this->getLocalNum();
661 this->create(numParticles,
true);
668 auto dtView =
dt.getView();
669 auto phiView =
Phi.getView();
670 auto binView =
Bin.getView();
671 auto eView =
E.getView();
672 auto bView =
B.getView();
673 Kokkos::parallel_for(
674 "ParticleContainer::createParticles::initializeNewSlots", numParticles,
677 invalid(idx) =
false;
687 constexpr int labelWidth = 32;
688 m << level4 << std::left << std::setw(labelWidth) <<
"Requested creation:" << numParticles
689 <<
" particles" << endl;
690 m << level4 << std::setw(labelWidth) <<
"New total number:" << this->getTotalNum()
691 <<
" (local: " << this->getLocalNum() <<
")" << endl;
692 m << level4 << std::setw(labelWidth) <<
"Underlying view capacity:" << newCapacity << endl;
694 if (newCapacity != oldCapacity) {
696 <<
"WARNING: createParticles triggered a reallocation of the underlying particle "
697 "views! This can be a costly operation. To avoid this, consider increasing "
698 "preallocation (BEAM::NALLOC) or the overallocation factor."
704 Inform m(
"ParticleContainer::allocateParticles");
708 if (oldCapacity != 0) {
710 "ParticleContainer::allocateParticles",
711 "Underlying views already allocated. This function is meant to be called on an "
712 "empty container, since it is destructive on existing particles. If you want "
713 "to create particles without deallocating existing ones, use createParticles() "
717 this->alloc(numParticles);
719 m << level4 << std::left << std::setw(32) <<
"Requested allocation:" << numParticles
720 <<
" particles" << endl;
721 m << level4 << std::setw(32) <<
"Size of underlying view:" << this->R.size() << endl;
733 Inform m(
"ParticleContainer::deleteInvalidParticles");
735 const size_type nLocal = this->getLocalNum();
737 if (invalid.extent(0) < nLocal) {
739 "ParticleContainer::deleteInvalidParticles",
740 "InvalidMask extent (" + std::to_string(invalid.extent(0))
741 +
") is smaller than local particle count (" + std::to_string(nLocal)
746 Kokkos::parallel_reduce(
747 "ParticleContainer::deleteInvalidParticles::count", nLocal,
753 ippl::Comm->allreduce(localDestroyNum, globalDestroyNum, 1, std::plus<size_type>());
759 Base::destroy(invalid, localDestroyNum);
762 if (globalDestroyNum > 0) {
770 constexpr int labelWidth = 32;
771 m << level4 << std::left << std::setw(labelWidth)
772 <<
"Requested destruction:" << localDestroyNum <<
" particles" << endl
773 << std::setw(labelWidth) <<
"New total number:" << this->getTotalNum()
774 <<
" (local: " << this->getLocalNum() <<
")" << endl;
776 return globalDestroyNum;
ippl::Vector< T, Dim > Vector_t
typename ippl::ParticleSpatialLayout< T, Dim, Mesh_t< Dim > > PLayout_t
ippl::FieldLayout< Dim > FieldLayout_t
ippl::UniformCartesian< double, 3 > Mesh_t
ippl::detail::size_type size_type
ippl::ParticleAttrib< T > ParticleAttrib
Quaternion getQuaternion(ippl::Vector< double, 3 > u, ippl::Vector< double, 3 > ref)
Return a unit quaternion that rotates vec onto reference.
Rigid spatial transform between a parent frame and a local frame.
ippl::Vector< double, 3 > transformFrom(const ippl::Vector< double, 3 > &r) const
Map a point from the local frame back to the parent frame.
ippl::Vector< double, 3 > rotateFrom(const ippl::Vector< double, 3 > &r) const
Rotate a vector from the local frame back into the parent frame.
void rotateBunchTo(ViewType Pview, size_t nLocal) const
Apply rotateTo() to a Kokkos view of vectors such as momenta.
void transformBunchTo(ViewType Rview, size_t nLocal) const
Apply transformTo() to a Kokkos view of particle positions.
CoordinateSystemTrafo inverted() const
Return the inverse transform.
matrix6x6_t getMoments6x6() const
double getMeanKineticEnergy() const
Vector_t< double, 3 > getMinPosition() const
Vector_t< double, 3 > getMeanMomentum() const
void computeDebyeLength(ippl::ParticleAttrib< Vector_t< double, 3 > >::view_type Pview, size_t Np, size_t Nlocal, double density)
Vector_t< double, 3 > getStandardDeviationPosition() const
Vector_t< double, 3 > getNormalizedEmittance() const
double getTemperature() const
void computeMoments(ippl::ParticleAttrib< Vector_t< double, 3 > >::view_type Rview, ippl::ParticleAttrib< Vector_t< double, 3 > >::view_type Pview, ippl::ParticleAttrib< double >::view_type Mview, size_t Np, size_t Nlocal)
double getDebyeLength() const
void computeMinMaxPosition(ippl::ParticleAttrib< Vector_t< double, 3 > >::view_type Rview, size_t Nlcoal)
double getStdKineticEnergy() const
Vector_t< double, 3 > getStandardDeviationMomentum() const
Vector_t< double, 3 > getMeanPosition() const
Vector_t< double, 3 > getStandardDeviationRP() const
double getPlasmaParameter() const
Vector_t< double, 3 > getMaxPosition() const
Vector_t< double, 3 > getGeometricEmittance() const
Vector_t< double, 6 > getCentroid() const
void setContainerState(std::weak_ptr< BunchStateHandler::ContainerState > containerState)
void setEnergyReferenceMass(double referenceMassGeV, bool rescaleToReference=true)
Vector_t< double, 6 > getMeans() const
double getMeanGammaZ() const
KOKKOS_INLINE_FUNCTION double getM() const
The constant mass per particle.
Container for all per-particle (and per-simulation) fields tracked during OPALX tracking.
Vector_t< double, 3 > getMeanP() const
Vector_t< double, Dim > refPartP_m
void setGlobalProcesses(std::vector< std::unique_ptr< GlobalProcess > > processes)
void setReference(const PartData *ref)
Set reference particle data.
Vector_t< double, 6 > getMeans() const
bool isMomentsDirty() const
void setGlobalToLocalQuaternion(const Quaternion_t &globalToLocalQuaternion)
Set global-to-local rotation quaternion.
CoordinateSystemTrafo & getToLabTrafo()
Get local-to-lab coordinate transformation.
ippl::ParticleAttrib< bool > InvalidMask
particle deletion mask (indicates which particles are deleted every timestep)
void setRefPartR(const Vector_t< double, Dim > &refPartR)
Set the reference particle position.
qm_view_type getQView() const
Vector_t< double, 3 > getMaxR() const
ippl::ParticleAttrib< double > MAttr
Vector_t< double, Dim > & getRefPartP()
Get the reference particle momentum.
double getMeanGammaZ() const
ippl::ParticleAttrib< double > dt
timestep in [s]
const Vector_t< double, Dim > & getRefPartR() const
Get the reference particle position (const).
const CoordinateSystemTrafo & getToLabTrafo() const
Get local-to-lab coordinate transformation (const).
QMStorageMode getQMStorageMode() const
double getTotalMass() const
Get total mass [GeV] in this container.
double getPlasmaParameter() const
ippl::ParticleAttrib< double > Phi
the scalar potential in [Cb/s]
std::vector< std::unique_ptr< GlobalProcess > > globalProcesses_m
Global physics processes attached to this container.
void setRefPartP(const Vector_t< double, Dim > &refPartP)
Set the reference particle momentum.
Vector_t< double, 3 > getRmsP() const
Vector_t< double, 3 > getMinR() const
Vector_t< double, 3 > getRmsRP() const
void scaleDtByCharge()
Scale particle time-step weights by charge before scatter.
Base::particle_position_type B
electric field for gun simulation with bins
ippl::Vector< float, 3 > spin_vector_type
const PartData * reference_m
Vector_t< double, Dim > refPartR_m
Vector_t< double, 3 > getGeometricEmit() const
double computeDebyeLength(double density)
void transformBunch(const CoordinateSystemTrafo &trafo)
Apply coordinate transform to local particles: translate R, rotate P, E, B.
ippl::ParticleAttrib< spin_vector_type > Pol
CoordinateSystemTrafo toLabTrafo_m
size_type markParticlesOutside(double sigmasAway)
Mark particles whose position is more than sigmasAway standard deviations from the bunch mean in any ...
void applyFractionalStep(const Pusher &pusher, double tau, double pathLengthTarget)
Apply a fractional Boris step and update reference/lab transform state.
void switchOffUnitlessPositions()
Restore physical positions from unitless form using each particle's dt[i].
const Vector_t< double, Dim > & getRefPartP() const
Get the reference particle momentum (const).
matrix6x6_t getCovMatrix() const
void setBunchStateHandler(std::shared_ptr< BunchStateHandler > handler)
QMStorageMode qmStorageMode_m
Vector_t< double, Dim > & getRefPartR()
Get the reference particle position.
short Sp
the particle specis
Vector_t< double, 6 > getCentroid() const
Vector_t< double, 3 > getNormEmit() const
void unscaleDtByCharge()
Restore original dt values after scaleDtByCharge().
double getMeanKineticEnergy() const
const std::vector< std::unique_ptr< GlobalProcess > > & getGlobalProcesses() const
void setToLabTrafo(const CoordinateSystemTrafo &toLabTrafo)
Set local-to-lab coordinate transformation.
double getTotalCharge() const
Get total charge [Cb] in this container.
void setEnergyReferenceMass(double referenceMassGeV, bool rescaleToReference=true)
ippl::ParticleAttrib< bin_index_type > Bin
the energy bin the particle is in
void setQ(double q)
Set particle charge for the active Q storage mode.
std::shared_ptr< BunchStateHandler::ContainerState > containerState_m
Vector_t< double, 3 > getMeanR() const
Vector_t< double, 3 > getRmsR() const
double getMassPerParticle() const
Get mass per particle [GeV].
typename ippl::ParticleAttrib< double >::view_type qm_view_type
View types of Q and M values.
short int bin_index_type
Defines which type to use as a particle bin.
void updateRefToLabCSTrafo(double bunchDT)
Advance reference/lab transform state and map bunch accordingly.
const PartData * getReference() const
Get reference particle data.
Base::particle_position_type E
electric field at particle position
Base::particle_position_type P
particle momenta [\beta\gamma]
ParticleContainer(Mesh_t< Dim > &mesh, FieldLayout_t< Dim > &FL, bool spinEnabled=false)
double getChargePerParticle() const
Get charge per particle [Cb].
double getTemperature() const
ippl::ParticleBase< ippl::ParticleSpatialLayout< T, Dim >, Kokkos::DefaultExecutionSpace::memory_space > Base
Alias for the ippl::ParticleBase specialization this container inherits from.
qm_view_type getMView() const
Quaternion_t globalToLocalQuaternion_m
void switchToUnitlessPositions()
Transform positions to unitless coordinates using each particle's dt[i].
double getStdKineticEnergy() const
void createParticles(size_type numParticles)
Create/allocate a specified number of particles.
ippl::ParticleAttrib< double > QAttr
void setM(double m)
Set particle mass for the active M storage mode.
DistributionMoments distMoments_m
double getDebyeLength() const
size_type deleteInvalidParticles()
Delete particles currently marked in InvalidMask.
double get_sPos() const
Get longitudinal position along design trajectory.
void set_sPos(double sPos)
Set longitudinal position along design trajectory.
PLayout_t< T, Dim > & getPL()
bool isUnitlessPositions() const
Quaternion_t getGlobalToLocalQuaternion() const
Get global-to-local rotation quaternion.
void registerAttributes()
void allocateParticles(size_type numParticles)
Quaternion storage and rotation algebra used by OPALX geometry code.
A collection of routines to construct object Attributes and retrieve.
constexpr double c
The velocity of light in m/s.