2#include <boost/numeric/ublas/io.hpp>
7template <
typename T,
unsigned Dim>
13 std::string integration_method,
14 std::shared_ptr<Distribution> &OPALdistribution,
15 std::shared_ptr<FieldSolverCmd> &OPALFieldSolver)
23 integration_method_m(integration_method),
25 isFirstRepartition_m(true),
33 OPALdist_m(OPALdistribution),
34 OPALFieldSolver_m(OPALFieldSolver) {
39 *
gmsg <<
"PartBunch Constructor" <<
endl;
48 for (
unsigned i = 0; i <
Dim; i++) {
50 this->
decomp_m[i] = domainDecomposition[i];
59 *
gmsg <<
"* FieldContainer set to isAllPeriodic = " << isAllPeriodic <<
endl;
78 this->
fcontainer_m->getMesh(), this->fcontainer_m->getFL()
86 this->
setBins(std::make_shared<AdaptBins_t>(
89 static_cast<bin_index_type
>(
maxBins),
98 this->fcontainer_m->getFL());
115 *
gmsg <<
"* PartBunch constructor done." <<
endl;
118template <
typename T,
unsigned Dim>
127template <
typename T,
unsigned Dim>
130 std::shared_ptr<FieldContainer_t> fc = this->fcontainer_m;
134 if (this->loadbalancer_m->balance(totalP)) {
135 auto* mesh = &fc->getRho().get_mesh();
136 auto* FL = &fc->getFL();
137 this->loadbalancer_m->repartition(FL, mesh, isFirstRepartition_m);
141template <
typename T,
unsigned Dim>
143 std::fill_n(globalPartPerNode_m.get(),
ippl::Comm->size(), 0);
144 globalPartPerNode_m[
ippl::Comm->rank()] = getLocalNum();
145 ippl::Comm->allreduce(globalPartPerNode_m.get(),
147 std::plus<size_t>());
150template <
typename T,
unsigned Dim>
152 if (this->solver_m !=
"")
153 *
gmsg <<
"* Warning solver already initiated but overwrite ..." <<
endl;
155 this->solver_m = solver;
157 this->fcontainer_m->initializeFields(this->solver_m);
159 this->setFieldSolver(std::make_shared<FieldSolver_t>(this->solver_m, &this->fcontainer_m->getRho(), &this->fcontainer_m->getE(),
160 &this->fcontainer_m->getPhi()));
162 this->fsolver_m->initSolver();
165 this->setLoadBalancer(std::make_shared<LoadBalancer_t>(this->lbt_m, this->fcontainer_m, this->pcontainer_m, this->fsolver_m));
167 *
gmsg <<
"* Solver and Load Balancer set" <<
endl;
170template <
typename T,
unsigned Dim>
172 Inform msg(
"EParticleStats");
174 auto pE_view = this->pcontainer_m->E.getView();
175 auto fphi_view = this->fcontainer_m->getPhi().getView();
185 double cc = getCouplingConstant();
190 "check e-field", this->getLocalNum(),
191 KOKKOS_LAMBDA(
const int i,
double& loc_avgE,
double& loc_minEComponent,
192 double& loc_maxEComponent,
double& loc_minE,
double& loc_maxE) {
193 double EX = pE_view[i][0]*cc;
194 double EY = pE_view[i][1]*cc;
195 double EZ = pE_view[i][2]*cc;
197 double ENorm = Kokkos::sqrt(EX*EX + EY*EY + EZ*EZ);
201 loc_minEComponent = EX < loc_minEComponent ? EX : loc_minEComponent;
202 loc_minEComponent = EY < loc_minEComponent ? EY : loc_minEComponent;
203 loc_minEComponent = EZ < loc_minEComponent ? EZ : loc_minEComponent;
205 loc_maxEComponent = EX > loc_maxEComponent ? EX : loc_maxEComponent;
206 loc_maxEComponent = EY > loc_maxEComponent ? EY : loc_maxEComponent;
207 loc_maxEComponent = EZ > loc_maxEComponent ? EZ : loc_maxEComponent;
209 loc_minE = ENorm < loc_minE ? ENorm : loc_minE;
210 loc_maxE = ENorm > loc_maxE ? ENorm : loc_maxE;
212 Kokkos::Sum<T>(avgE), Kokkos::Min<T>(minEComponent),
213 Kokkos::Max<T>(maxEComponent), Kokkos::Min<T>(minE),
214 Kokkos::Max<T>(maxE));
216 if (this->getLocalNum() == 0) {
217 minEComponent = maxEComponent = minE = maxE = avgE = 0.0;
220 MPI_Reduce(myRank == 0 ? MPI_IN_PLACE : &avgE, &avgE, 1, MPI_DOUBLE, MPI_SUM, 0,
ippl::Comm->getCommunicator());
221 MPI_Reduce(myRank == 0 ? MPI_IN_PLACE : &minEComponent, &minEComponent, 1, MPI_DOUBLE, MPI_MIN, 0,
ippl::Comm->getCommunicator());
222 MPI_Reduce(myRank == 0 ? MPI_IN_PLACE : &maxEComponent, &maxEComponent, 1, MPI_DOUBLE, MPI_MAX, 0,
ippl::Comm->getCommunicator());
223 MPI_Reduce(myRank == 0 ? MPI_IN_PLACE : &minE, &minE, 1, MPI_DOUBLE, MPI_MIN, 0,
ippl::Comm->getCommunicator());
224 MPI_Reduce(myRank == 0 ? MPI_IN_PLACE : &maxE, &maxE, 1, MPI_DOUBLE, MPI_MAX, 0,
ippl::Comm->getCommunicator());
226 size_t Np = this->getTotalNum();
227 avgE /= (Np == 0) ? 1 : Np;
229 msg <<
"avgENorm = " << avgE <<
endl;
231 using mdrange_type = Kokkos::MDRangePolicy<Kokkos::Rank<3>>;
234 "check phi", mdrange_type({0,0,0}, {fphi_view.extent(0),fphi_view.extent(1),fphi_view.extent(2)}),
235 KOKKOS_LAMBDA(
const int i,
const int j,
const int k,
double& loc_avgphi) {
236 double phi = fphi_view(i,j,k);
239 Kokkos::Sum<T>(avgphi));
241 MPI_Reduce(myRank == 0 ? MPI_IN_PLACE : &avgphi, &avgphi, 1, MPI_DOUBLE, MPI_SUM, 0,
ippl::Comm->getCommunicator());
242 avgphi /= this->getTotalNum();
243 msg <<
"avgphi = " << avgphi <<
endl;
247template <
typename T,
unsigned Dim>
249 std::shared_ptr<ParticleContainer_t> pc = this->pcontainer_m;
251 auto Rview = pc->R.getView();
252 auto Pview = pc->P.getView();
259 double loc_centroid[2 *
Dim] = {};
260 double loc_moment[2 *
Dim][2 *
Dim] = {};
262 double centroid[2 *
Dim] = {};
263 double moment[2 *
Dim][2 *
Dim] = {};
265 for (
unsigned i = 0; i < 2 *
Dim; i++) {
266 loc_centroid[i] = 0.0;
267 for (
unsigned j = 0; j <= i; j++) {
268 loc_moment[i][j] = 0.0;
269 loc_moment[j][i] = 0.0;
273 for (
unsigned i = 0; i < 2 *
Dim; ++i) {
277 const int k,
double& cent,
double& mom0,
double& mom1,
double& mom2,
278 double& mom3,
double& mom4,
double& mom5) {
279 double part[2 *
Dim];
280 part[0] = Rview(k)[0];
281 part[1] = Pview(k)[0];
282 part[2] = Rview(k)[1];
283 part[3] = Pview(k)[1];
284 part[4] = Rview(k)[2];
285 part[5] = Pview(k)[2];
288 mom0 += part[i] * part[0];
289 mom1 += part[i] * part[1];
290 mom2 += part[i] * part[2];
291 mom3 += part[i] * part[3];
292 mom4 += part[i] * part[4];
293 mom5 += part[i] * part[5];
295 Kokkos::Sum<T>(loc_centroid[i]), Kokkos::Sum<T>(loc_moment[i][0]),
296 Kokkos::Sum<T>(loc_moment[i][1]), Kokkos::Sum<T>(loc_moment[i][2]),
297 Kokkos::Sum<T>(loc_moment[i][3]), Kokkos::Sum<T>(loc_moment[i][4]),
298 Kokkos::Sum<T>(loc_moment[i][5]));
302 MPI_Allreduce(loc_moment, moment, 2 *
Dim * 2 *
Dim, MPI_DOUBLE, MPI_SUM,
ippl::Comm->getCommunicator());
303 MPI_Allreduce(loc_centroid, centroid, 2 *
Dim, MPI_DOUBLE, MPI_SUM,
ippl::Comm->getCommunicator());
306 double rmax_loc[
Dim];
307 double rmin_loc[
Dim];
311 for (
unsigned d = 0; d <
Dim; ++d) {
313 "rel max", this->getLocalNum(),
314 KOKKOS_LAMBDA(
const int i,
double& mm) {
315 double tmp_vel = Rview(i)[d];
316 mm = tmp_vel > mm ? tmp_vel : mm;
318 Kokkos::Max<T>(rmax_loc[d]));
321 "rel min", this->getLocalNum(),
322 KOKKOS_LAMBDA(
const int i,
double& mm) {
323 double tmp_vel = Rview(i)[d];
324 mm = tmp_vel < mm ? tmp_vel : mm;
326 Kokkos::Min<T>(rmin_loc[d]));
329 MPI_Allreduce(rmax_loc, rmax,
Dim, MPI_DOUBLE, MPI_MAX,
ippl::Comm->getCommunicator());
330 MPI_Allreduce(rmin_loc, rmin,
Dim, MPI_DOUBLE, MPI_MIN,
ippl::Comm->getCommunicator());
334 for (
unsigned int i=0; i<
Dim; i++) {
340template <
typename T,
unsigned Dim>
342 this->fcontainer_m->getRho() = 0.0;
343 this->fsolver_m->runSolver();
346template <
typename T,
unsigned Dim>
351 os << std::scientific;
353 os <<
"* ************** B U N C H "
354 "********************************************************* \n";
355 os <<
"* PARTICLES = " << this->getTotalNum() <<
"\n";
356 os <<
"* CHARGE = " << this->qi_m*this->getTotalNum() <<
" (Cb) \n";
357 os <<
"* INTEGRATOR = " << integration_method_m <<
"\n";
361 os <<
"* RMS P = " << this->pcontainer_m->getRmsP() <<
" [beta gamma]\n";
362 os <<
"* Mean R: " << this->pcontainer_m->getMeanR() <<
" [m]\n";
363 os <<
"* Mean P: " << this->pcontainer_m->getMeanP() <<
" [beta gamma]\n";
364 os <<
"* MESH SPACING = " <<
Util::getLengthString( this->fcontainer_m->getMesh().getMeshSpacing(), 5) <<
"\n";
365 os <<
"* COMPDOM INCR = " << this->OPALFieldSolver_m->getBoxIncr() <<
" (%) \n";
366 os <<
"* FIELD LAYOUT = " << this->fcontainer_m->getFL() <<
"\n";
367 os <<
"* Centroid : \n* ";
368 for (
unsigned int i=0; i<2*
Dim; i++) {
369 os << this->pcontainer_m->getCentroid()[i] <<
" ";
371 os <<
endl <<
"* Cov Matrix : \n* ";
372 for (
unsigned int i=0; i<2*
Dim; i++) {
373 for (
unsigned int j=0; j<2*
Dim; j++) {
374 os << this->pcontainer_m->getCovMatrix()(i,j) <<
" ";
379 "********************************************************************************"
386template <
typename T,
unsigned Dim>
392 Inform m (
"bunchUpdate ");
394 auto *mesh = &this->fcontainer_m->getMesh();
395 auto *FL = &this->fcontainer_m->getFL();
397 std::shared_ptr<ParticleContainer_t> pc = this->getParticleContainer();
399 pc->computeMinMaxR();
407 hr_m = (1.0+this->OPALFieldSolver_m->getBoxIncr()/100.)*(l / this->nr_m);
408 mesh->setMeshSpacing(hr);
409 mesh->setOrigin(o-0.5*hr_m*this->OPALFieldSolver_m->getBoxIncr()/100.);
411 pc->getLayout().updateLayout(*FL, *mesh);
414 this->getFieldContainer()->setRMin(o);
415 this->getFieldContainer()->setRMax(
e);
416 this->getFieldContainer()->setHr(hr);
418 this->isFirstRepartition_m =
true;
419 this->loadbalancer_m->initializeORB(FL, mesh);
420 this->loadbalancer_m->repartition(FL, mesh, this->isFirstRepartition_m);
421 this->updateMoments();
424template <
typename T,
unsigned Dim>
432 auto *mesh = &this->fcontainer_m->getMesh();
433 auto *FL = &this->fcontainer_m->getFL();
435 std::shared_ptr<ParticleContainer_t> pc = this->getParticleContainer();
437 pc->computeMinMaxR();
443 hr_m = (1.0+this->OPALFieldSolver_m->getBoxIncr()/100.)*(l / this->nr_m);
444 mesh->setMeshSpacing(hr_m);
445 mesh->setOrigin(o-0.5*hr_m*this->OPALFieldSolver_m->getBoxIncr()/100.);
447 this->getFieldContainer()->setRMin(o);
448 this->getFieldContainer()->setRMax(
e);
449 this->getFieldContainer()->setHr(hr_m);
451 pc->getLayout().updateLayout(*FL, *mesh);
454 this->isFirstRepartition_m =
true;
458 this->updateMoments();
461template <
typename T,
unsigned Dim>
466 std::shared_ptr<AdaptBins_t> bins = this->getBins();
470 bins->doFullRebin(bins->getMaxBinCount());
472 bins->sortContainerByBin();
475 bins->genAdaptiveHistogram();
518 this->fcontainer_m->getRho() = 0.0;
523 *Q = (*Q) * this->pcontainer_m->dt;
525 *Q = (*Q) / this->pcontainer_m->dt;
533 (*rho) = (*rho) / getdT();
536 const double qtot = this->qi_m * this->getTotalNum();
538 size_type localParticles = this->pcontainer_m->getLocalNum();
540 double relError = std::fabs((qtot - (*rho).sum()) / qtot);
542 ippl::Comm->reduce(localParticles, TotalParticles, 1, std::plus<size_type>());
544 if ((
ippl::Comm->rank() == 0) && (relError > 1.0E-13)) {
546 m <<
"Time step: " << it_m
547 <<
" total particles in the sim. " << totalP_m
548 <<
" missing : " << totalP_m-TotalParticles
549 <<
" rel. error in charge conservation: " << relError <<
endl;
554 double cellVolumeInv = 1 / std::reduce(hr_m.begin(), hr_m.end(), 1., std::multiplies<double>());
555 (*rho) = (*rho) * cellVolumeInv;
558 double totalQ = getCharge();
559 if (this->fsolver_m->getStype() !=
"OPEN") {
561 for (
size_t d = 0; d < 3; d++) {
562 size *= rmax_m[d] - rmin_m[d];
564 (*rho) = (*rho) - (totalQ / size);
577 (*rho) = (*rho) / getCouplingConstant();
579 this->fsolver_m->runSolver();
582 gather(this->pcontainer_m->E, this->fcontainer_m->getE(), this->pcontainer_m->R);
586 double cellVolume = std::reduce(hr_m.begin(), hr_m.end(), 1., std::multiplies<double>());
587 m <<
"cellVolume= " << cellVolume <<
endl;
588 m <<
"Sum over E-field after gather = " << this->fcontainer_m->getE().sum() <<
endl;
600template <
typename T,
unsigned Dim>
605 Inform m(
"scatterCICPerBin");
606 m <<
"Scattering binIndex = " << binIndex <<
" to grid." <<
endl;
608 this->fcontainer_m->getRho() = 0.0;
619 if (binIndex == -1) {
621 Q = this->qi_m * this->getTotalNum();
625 Q = this->qi_m * this->bins_m->getNPartInBin(binIndex,
true);
626 scatter(*q, *rho, *R, this->bins_m->getBinIterationPolicy(binIndex), this->bins_m->getHashArray());
629 m <<
"gammz= " << this->pcontainer_m->getMeanP()[2] <<
endl;
632 double relError = std::fabs((Q - (*rho).sum()) / Q);
634 size_type localParticles = this->pcontainer_m->getLocalNum();
635 size_type totalP_check = (binIndex == -1) ? totalP_m : this->pcontainer_m->getTotalNum();
637 m <<
"computeSelfFields sum rho = " << (*rho).sum() <<
", relError = " << relError <<
endl;
639 ippl::Comm->reduce(localParticles, TotalParticles, 1, std::plus<size_type>());
642 if (TotalParticles != totalP_check || relError > 1
e-10) {
643 m <<
"Time step: " << it_m <<
endl;
644 m <<
"Total particles in the sim. " << totalP_check <<
" "
645 <<
"after update: " << TotalParticles <<
endl;
646 m <<
"Rel. error in charge conservation: " << relError <<
endl;
652 double cellVolume = std::reduce(hr.
begin(), hr.
end(), 1., std::multiplies<double>());
654 m <<
"cellVolume= " << cellVolume <<
endl;
656 (*rho) = (*rho) / cellVolume;
659 if (this->fsolver_m->getStype() !=
"OPEN") {
661 for (
unsigned d = 0; d < 3; d++) {
662 size *= rmax[d] - rmin[d];
664 *rho = *rho - (Q / size);
668template <
typename T,
unsigned Dim>
670 Inform ms(
"PartBunch::performBunchSanityChecks");
674 if (!this->getBCHandler()) {
676 "BC Handler not initialized properly.");
678 ms <<
"BC Handler initialized properly." <<
endl;
ippl::detail::size_type size_type
Inform & endl(Inform &inf)
Inform & level1(Inform &inf)
constexpr double e
The value of.
std::string getLengthString(double spos, unsigned int precision=3)
Implementations for FFT constructor/destructor and transforms.
KOKKOS_INLINE_FUNCTION Vector< T, Dim > max(const Vector< T, Dim > &a, const Vector< T, Dim > &b)
RangePolicy< View::rank, typenameView::execution_space, PolicyArgs... >::policy_type getRangePolicy(const View &view, int shift=0)
void gather(Attrib1 &attrib, Field &f, const Attrib2 &pp, const bool addToAttribute=false)
Non-class interface for gathering field data into a particle attribute.
KOKKOS_INLINE_FUNCTION Vector< T, Dim > min(const Vector< T, Dim > &a, const Vector< T, Dim > &b)
void parallel_reduce(const std::string &name, const ExecPolicy &policy, const FunctorType &functor, ReducerArgument &&... reducer)
std::unique_ptr< mpi::Communicator > Comm
void scatter(const Attrib1 &attrib, Field &f, const Attrib2 &pp)
Non-class interface for scattering particle attribute data onto a field.
void gatherLoadBalanceStatistics()
void performBunchSanityChecks() const
Vector_t< double, Dim > rmin_m
std::array< bool, Dim > decomp_m
void pre_run() override
A method that should be used for setting up the simulation.
void calcBeamParameters()
std::shared_ptr< VField_t< T, Dim > > getTempEField()
void scatterCICPerBin(binIndex_t binIndex)
Vector_t< double, Dim > rmax_m
std::shared_ptr< FieldSolverCmd > OPALFieldSolver_m
std::shared_ptr< BCHandler_t > getBCHandler() const
void setBCHandler(std::shared_ptr< BCHandler_t > bcHandler)
typename ParticleContainer_t::bin_index_type binIndex_t
std::shared_ptr< ParticleContainer_t > getParticleContainer()
double dt_m
6x6 matrix of the moments of the beam
void setSolver(std::string solver)
ippl::NDIndex< Dim > domain_m
Vector_t< double, Dim > hr_m
mesh size [m]
void spaceChargeEFieldCheck(Vector_t< double, 3 > efScale)
void setBins(std::shared_ptr< AdaptBins_t > bins)
typename ParticleBinning::CoordinateSelector< ParticleContainer_t > BinningSelector_t
Inform & print(Inform &os)
Vector_t< double, Dim > origin_m
std::shared_ptr< AdaptBins_t > getBins()
std::unique_ptr< size_t[]> globalPartPerNode_m
void setTempEField(std::shared_ptr< VField_t< T, Dim > > Etmp)
short int bin_index_type
Defines which type to use as a particle bin.
The base class for all OPAL exceptions.
void setParticleContainer(std::shared_ptr< ParticleContainer< T, 3 > > pcontainer)
std::shared_ptr< FieldContainer< T, 3 > > fcontainer_m
void setFieldContainer(std::shared_ptr< FieldContainer< T, 3 > > fcontainer)
detail::size_type size_type
typename PLayout::particle_position_type particle_position_type
particle_position_type R
view of particle positions
KOKKOS_INLINE_FUNCTION constexpr iterator begin()
KOKKOS_INLINE_FUNCTION constexpr iterator end()
std::ios_base::fmtflags FmtFlags_t
Timing::TimerRef TimerRef
static TimerRef getTimer(const char *nm)
static void stopTimer(TimerRef t)
static void startTimer(TimerRef t)