18#include "Manager/BaseManager.h"
19#include "Manager/PicManager.h"
27#include "Random/Distribution.h"
28#include "Random/InverseTransformSampling.h"
29#include "Random/NormalDistribution.h"
30#include "Random/Randn.h"
48template <
typename T,
unsigned Dim>
51template <
typename T,
unsigned Dim>
53 :
public ippl::PicManager<
54 T, Dim, ParticleContainer<T, Dim>, FieldContainer<T, Dim>, LoadBalancer<T, Dim>> {
60 using Base = ippl::ParticleBase<
61 ippl::ParticleSpatialLayout<T, Dim>, Kokkos::DefaultExecutionSpace::memory_space>;
101 std::shared_ptr<BunchStateHandler>
112 std::shared_ptr<VField_t<T, Dim>>
Etmp_m;
114 std::shared_ptr<VField_t<T, Dim>>
Btmp_m;
118 std::unique_ptr<size_t[]>
137 std::vector<double> qi, std::vector<double> mi,
const std::vector<Beam*>& beams,
138 std::vector<size_t> totalParticlesPerBeam,
double lbt, std::string integration_method,
228 for (
const auto& pc : this->getParticleContainers()) {
230 total += pc->getTotalNum();
288 "PartBunch::advance",
289 "Not used: just exists because ippl::PicManager wants it that way.");
295 "PartBunch::par2grid",
296 "Not used: just exists because ippl::PicManager wants it that way.");
302 "PartBunch::grid2par",
303 "Not used: just exists because ippl::PicManager wants it that way.");
352 const auto& containers = this->getParticleContainers();
353 if (containers.size() !=
qi_m.size()) {
355 "PartBunch::setCharge",
356 "Number of particle containers and qi values do not match.");
358 for (
size_t i = 0; i < containers.size(); ++i) {
359 containers[i]->setQ(
qi_m[i]);
369 const auto& containers = this->getParticleContainers();
370 if (containers.size() !=
mi_m.size()) {
372 "PartBunch::setMass",
373 "Number of particle containers and mi values do not match.");
375 for (
size_t i = 0; i < containers.size(); ++i) {
376 containers[i]->setM(
mi_m[i]);
388 const auto& containers = this->getParticleContainers();
389 if (containers.size() !=
qi_m.size()) {
391 "PartBunch::getCharge",
392 "Number of particle containers and qi values do not match.");
394 if (containerIndex >= containers.size()) {
395 throw OpalException(
"PartBunch::getCharge",
"Container index out of range.");
397 return qi_m[containerIndex] * containers[containerIndex]->getTotalNum();
407 if (containerIndex >=
qi_m.size()) {
408 throw OpalException(
"PartBunch::getChargePerParticle",
"Container index out of range.");
410 return qi_m[containerIndex];
420 if (containerIndex >=
mi_m.size()) {
421 throw OpalException(
"PartBunch::getMassPerParticle",
"Container index out of range.");
423 return mi_m[containerIndex];
431 double getQ(
size_t containerIndex = 0)
const {
return this->
getCharge(containerIndex); }
440 double getM(
size_t containerIndex = 0)
const {
441 const auto& containers = this->getParticleContainers();
442 if (containers.size() !=
mi_m.size()) {
444 "PartBunch::getM",
"Number of particle containers and mi values do not match.");
446 if (containerIndex >= containers.size()) {
447 throw OpalException(
"PartBunch::getM",
"Container index out of range.");
449 return mi_m[containerIndex] * containers[containerIndex]->getTotalNum();
458 const auto& containers = this->getParticleContainers();
459 if (containers.size() !=
qi_m.size()) {
461 "PartBunch::getTotalCharge",
462 "Number of particle containers and qi values do not match.");
465 for (
size_t i = 0; i < containers.size(); ++i) {
466 charge +=
qi_m[i] * containers[i]->getTotalNum();
477 const auto& containers = this->getParticleContainers();
478 if (containers.size() !=
mi_m.size()) {
480 "PartBunch::getTotalMass",
481 "Number of particle containers and mi values do not match.");
484 for (
size_t i = 0; i < containers.size(); ++i) {
485 mass +=
mi_m[i] * containers[i]->getTotalNum();
491 return this->pcontainer_m->getStdKineticEnergy();
513 *
gmsg <<
"not implemented:: file: " << __FILE__ <<
" line: " << __LINE__
514 <<
" function: " << __func__ << endl;
520 unsigned int , std::vector<double>& ,
521 std::pair<double, double>& ) {
522 *
gmsg <<
"not implemented:: file: " << __FILE__ <<
" line: " << __LINE__
523 <<
" function: " << __func__ << endl;
528 *
gmsg <<
"not implemented:: file: " << __FILE__ <<
" line: " << __LINE__
529 <<
" function: " << __func__ << endl;
551 Inform&
print(Inform& os);
579 int ret_bins =
static_cast<int>(
bins_m->getCurrentBinCount());
582 if (ret_bins == this->
getBins()->getMaxBinCount()) {
583 Inform m(
"PartBunch::getCurrentNBins");
585 <<
"WARNING: Number of bins is the same as the maximum number of bins, we haven't "
586 "merged bins yet (likely because the simulation is too empty). Returning 1. If "
587 "that is not the case, check e.g. binning parameters."
597 *
gmsg <<
"not implemented:: file: " << __FILE__ <<
" line: " << __LINE__
598 <<
" function: " << __func__ << endl;
614 "Not implemented: shouldn't be called, since this is not the correct way to access "
615 "particle positions.");
623 "Not implemented: shouldn't be called, since this is not the correct way to access "
624 "particle momenta.");
661 *
gmsg <<
"not implemented:: file: " << __FILE__ <<
" line: " << __LINE__
662 <<
" function: " << __func__ << endl;
Defines a structure to hold particles in energy bins and their associated data.
ippl::Vector< T, Dim > Vector_t
typename ippl::detail::ViewType< ippl::Vector< double, Dim >, 1 >::view_type view_type
ippl::Field< ippl::Vector< T, Dim >, Dim, ViewArgs... > VField_t
typename ippl::detail::ViewType< ippl::Vector< double, 3 >, 1 >::view_type view_type
Handler for boundary conditions per spatial dimension.
Field solver wrapper that implements the full binned self-field algorithm.
Vector_t< double, Dim > R(size_t)
Do not use; throws (access positions via ParticleContainer::R).
void computeBoundsForFieldSolve(Vector_t< double, Dim > &lower, Vector_t< double, Dim > &upper)
Computes the spatial bounds for the field solver based on the current particle distribution.
std::vector< bool > pcAtZStop_m
Per-container: frozen at current z-stop until next segment.
Vector_t< double, Dim > rmax_m
Current bunch spatial maximum (from primary container stats).
typename ParticleBinning::CoordinateSelector< ParticleContainer_t > CoordinateSelector_t
BinnedFieldSolver< T, Dim > BinnedFieldSolver_t
void par2grid() override
PicManager hook; throws (scatter handled elsewhere).
void gatherLoadBalanceStatistics()
void setdT(double dt)
Set the global time step.
void performBunchSanityChecks() const
Validate BC handler, solver wiring, field pointers, and layout extents.
std::string getParticleName(size_t i) const
Particle species name for container i (from BEAM PARTICLE input).
std::shared_ptr< VField_t< T, Dim > > getTempEField()
Scratch E field used by the binned solver path.
void computeSelfFields()
Compute the bunch self-fields (binned when available).
std::vector< std::string > particleNames_m
Per-container beam particle names.
void incTrackSteps()
Increment globalTrackStep_m by one.
double getMassPerParticle(size_t containerIndex=0) const
Get the mass per particle for a given particle container.
void advance() override
PicManager hook; throws (tracking does not use this path).
std::shared_ptr< VField_t< T, Dim > > Btmp_m
double getdT() const
Get the global time step.
void pre_run() override
Warm-up: zero rho and run the field solver once (skip full dumps).
void calcLineDensity(unsigned int, std::vector< double > &, std::pair< double, double > &)
Stub; logs only.
void setT(double t)
Set the current simulation time.
std::shared_ptr< AdaptBins_t > getBins() const
Const access to adaptive binning state.
bool isFirstRepartition_m
True until the first ORB-style repartition completes.
void setMass()
Set the per-particle mass for each particle container.
Vector_t< int, Dim > nr_m
Mesh cell count per dimension.
DataSink * dataSink_m
Borrowed diagnostics and dump output sink.
std::array< bool, Dim > decomp_m
Domain decomposition flags (per axis).
Vector_t< double, Dim > rmin_m
double getTotalCharge() const
Get the total charge across all particle containers.
void dumpBinConfig(bool preMerge)
Write bin edges/counts to the data sink when configured.
bool pcAtZStop(size_t i) const
std::shared_ptr< AdaptBins_t > getBins()
Non-const access to adaptive binning state.
FieldSolverCmd * OPALFieldSolver_m
Borrowed parsed FIELD_SOLVER command.
std::shared_ptr< const BunchStateHandler > getBunchStateHandler() const
double calcMeanPhi()
Compatibility stub; logs and returns 0.
void reinitializeGridZ(int nrZ)
Reinitialize the z dimension of the field grid to nrZ cells.
Vector_t< double, Dim > origin_m
Mesh origin (lab coordinates).
void calcBeamParameters()
Update moments and set rmin_m / rmax_m from the primary (first) container.
int nrZBase_m
Base z grid count before any image-charge doubling; used to reset nr_m.
bool hasFieldSolver() const
typename ParticleBinning::AdaptBinsBase< ParticleContainer_t > AdaptBins_t
long long globalTrackStep_m
Global integration step counter.
void do_binaryRepart()
ORB/binary repartition when the load balancer requests it (primary container).
double getT() const
Get the current simulation time.
double getQ(size_t containerIndex=0) const
Alias for getCharge(containerIndex).
std::string integration_method_m
Integrator name (e.g. leapfrog).
double getM(size_t containerIndex=0) const
Get the total mass for a given particle container.
std::shared_ptr< AdaptBins_t > bins_m
Adaptive velocity/gamma binning (optional).
Vector_t< double, Dim > hr_m
Mesh spacing (m).
typename ParticleBinning::GammaSelector< ParticleContainer_t > GammaSelector_t
std::string solver_m
Field solver type string from input.
size_t calcNumPartsOutside(Vector_t< double, Dim >)
Stub; logs and returns 0.
double getCharge(size_t containerIndex=0) const
Get the total charge for a given particle container.
void setReference(const PartData *ref)
Set inside TrackRun::execute.
void setBCHandler(std::shared_ptr< BCHandler_t > bcHandler)
Vector_t< double, Dim > get_origin() const
Cached minimum extent (rmin_m); prefer per-container min/max for multi-beam detail.
int getCurrentNBins() const
Effective bin count for diagnostics (1 if binning inactive or still at max bins).
void incrementT()
Advance time by one global time step.
std::vector< bool > pcActive_m
Per-container: participate in this track segment.
std::shared_ptr< BCHandler_t > bcHandler_m
Field boundary conditions.
Vector_t< double, Dim > P(size_t)
Do not use; throws (access momenta via ParticleContainer::P).
std::shared_ptr< VField_t< T, Dim > > Etmp_m
double lbt_m
Load-balancer timescale parameter.
void setSolver()
Build field solver and load balancer from OPALFieldSolver_m.
double dt_m
Global time step (s).
double t_m
Current simulation time (s).
void setCharge()
Set the per-particle charge for each particle container.
void grid2par() override
PicManager hook; throws (gather handled elsewhere).
void setPcAtZStop(size_t i)
Deactivate container i until the next step-size segment (z-stop reached).
Vector_t< double, Dim > get_maxExtent() const
Cached maximum extent (rmax_m).
ippl::NDIndex< Dim > domain_m
Global mesh index extent per dimension.
void setImageChargeConfiguration(bool enabled, double zPlane)
Set the image-charge configuration for the field solver.
std::shared_ptr< BunchStateHandler > bunchState_m
Bunch state: unitless flag, repartition flag, etc.
const PartData * reference_m
Reference particle data (set by TrackRun::execute).
void setTempEField(std::shared_ptr< VField_t< T, Dim > > Etmp)
Vector_t< double, Dim > getEExtrema()
Stub; logs and returns zero vector.
double rmsDensity_m
Legacy RMS density placeholder (may still appear in stats).
std::shared_ptr< VField_t< T, Dim > > getTempBField()
Scratch B field used by the binned solver path.
void setTempBField(std::shared_ptr< VField_t< T, Dim > > Btmp)
void setShiftedGreensConfiguration(bool enabled, double zPlane)
Set the shifted Green's function Dirichlet-correction configuration.
std::shared_ptr< BunchStateHandler > getBunchStateHandler()
const PartData * getReference() const
typename ParticleContainer_t::bin_index_type binIndex_t
void setZerofaceMaxSteps(int maxSteps)
Set the maximum number of timesteps for which image charges are active (0 = unlimited).
ippl::ParticleBase< ippl::ParticleSpatialLayout< T, Dim >, Kokkos::DefaultExecutionSpace::memory_space > Base
double get_rmsDensity() const
Legacy RMS density field (may be unused).
void setGlobalTrackStep(long long n)
void bunchUpdate()
Refresh mesh from particle extents, update layouts, and recompute moments.
double getTotalMass() const
Get the total mass across all particle containers.
size_t getTotalNumAllContainers() const
Sum of getTotalNum() over all particle containers.
std::string getFieldSolverType()
Backend type string (e.g. FFT, OPEN, CG, NONE).
void refreshPcActiveAfterEmit()
After emission: reactivate non-empty containers not marked at z-stop.
long long getGlobalTrackStep() const
Current global tracking step.
DataSink * getDataSink() const
Vector_t< double, Dim > get_halo() const
Stub; logs and returns zero vector.
std::shared_ptr< BCHandler_t > getBCHandler() const
Current boundary-condition handler.
Inform & print(Inform &os)
Human-readable dump of each container to os.
BinnedFieldSolver_t * getFieldSolver()
Non-const pointer to the concrete BinnedFieldSolver.
void applyGridUpdate(const Vector_t< double, Dim > &lower, const Vector_t< double, Dim > &upper)
Updates the mesh/grid and internal data structures to match the given spatial bounds.
void setBins()
Create adaptive bins from the binning command (VELOCITYZ / GAMMAZ).
bool isPcActive(size_t i) const
void setBins(std::shared_ptr< AdaptBins_t > bins)
size_t getLoadBalance(int p)
void get_bounds(Vector_t< double, Dim > &rmin, Vector_t< double, Dim > &rmax)
Copy cached bunch extent (rmin_m, rmax_m) from calcBeamParameters.
std::vector< double > qi_m
Charge per macroparticle [C], one entry per container.
double getChargePerParticle(size_t containerIndex=0) const
Get the charge per particle for a given particle container.
Vector_t< double, Dim > get_hr() const
Get mesh spacing.
void setZeroFacePlaneDumpFrequency(int frequency)
Configure diagnostic dump frequency for the ZEROFACE plane potential.
void resetPcActive()
At segment start: active if container is non-empty; inactive if empty.
std::unique_ptr< size_t[]> globalPartPerNode_m
Per-rank particle counts for load-balance stats.
void setPcActive(size_t i)
Force container i active (e.g. for containers with pending emission).
std::vector< double > mi_m
Mass per macroparticle [GeV], one entry per container.
int it_m
Iteration counter (legacy / diagnostics).
KOKKOS_INLINE_FUNCTION double getM() const
The constant mass per particle.
Container for all per-particle (and per-simulation) fields tracked during OPALX tracking.
short int bin_index_type
Defines which type to use as a particle bin.
Example struct used to access the binning variable for each particle.
Selects the gamma factor for binning.