2#include <boost/numeric/ublas/io.hpp>
7template <
typename T,
unsigned Dim>
9 std::string integration_method, std::shared_ptr<Distribution> &OPALdistribution,
10 std::shared_ptr<FieldSolverCmd> &OPALFieldSolver)
31 static IpplTimings::TimerRef gatherInfoPartBunch = IpplTimings::getTimer(
"gatherInfoPartBunch");
32 IpplTimings::startTimer(gatherInfoPartBunch);
34 *
gmsg <<
"PartBunch Constructor" << endl;
43 for (
unsigned i = 0; i <
Dim; i++) {
45 this->
decomp_m[i] = domainDecomposition[i];
48 bool isAllPeriodic =
true;
64 this->setParticleContainer(std::make_shared<ParticleContainer_t>(
65 this->fcontainer_m->getMesh(), this->fcontainer_m->getFL()));
67 IpplTimings::stopTimer(gatherInfoPartBunch);
72 this->
setBins(std::make_shared<AdaptBins_t>(
75 static_cast<bin_index_type
>(maxBins),
81 this->
getTempEField()->initialize(this->fcontainer_m->getMesh(), this->fcontainer_m->getFL());
84 static IpplTimings::TimerRef setSolverT = IpplTimings::getTimer(
"setSolver");
85 IpplTimings::startTimer(setSolverT);
87 IpplTimings::stopTimer(setSolverT);
89 static IpplTimings::TimerRef prerun = IpplTimings::getTimer(
"prerun");
90 IpplTimings::startTimer(prerun);
92 IpplTimings::stopTimer(prerun);
97template <
typename T,
unsigned Dim>
99 using Base = ippl::ParticleBase<ippl::ParticleSpatialLayout<T, Dim>>;
100 typename Base::particle_position_type* Ep = &this->pcontainer_m->E;
101 typename Base::particle_position_type* R = &this->pcontainer_m->R;
103 gather(*Ep, *Ef, *R);
106template <
typename T,
unsigned Dim>
109 std::shared_ptr<FieldContainer_t> fc = this->fcontainer_m;
114 if (this->loadbalancer_m->balance(totalP, it + 1)) {
115 auto* mesh = &fc->getRho().get_mesh();
116 auto* FL = &fc->getFL();
117 this->loadbalancer_m->repartition(FL, mesh, isFirstRepartition_m);
121template <
typename T,
unsigned Dim>
123 std::fill_n(globalPartPerNode_m.get(), ippl::Comm->size(), 0);
124 globalPartPerNode_m[ippl::Comm->rank()] = getLocalNum();
125 ippl::Comm->allreduce(globalPartPerNode_m.get(), ippl::Comm->size(), std::plus<size_t>());
128template <
typename T,
unsigned Dim>
130 if (this->solver_m !=
"")
131 *
gmsg <<
"* Warning solver already initiated but overwrite ..." << endl;
133 this->solver_m = solver;
135 this->fcontainer_m->initializeFields(this->solver_m);
137 this->setFieldSolver(std::make_shared<FieldSolver_t>(
138 this->solver_m, &this->fcontainer_m->getRho(), &this->fcontainer_m->getE(),
139 &this->fcontainer_m->getPhi()));
141 this->fsolver_m->initSolver();
144 this->setLoadBalancer(std::make_shared<LoadBalancer_t>(this->lbt_m, this->fcontainer_m, this->pcontainer_m, this->fsolver_m));
146 *
gmsg <<
"* Solver and Load Balancer set" << endl;
149template <
typename T,
unsigned Dim>
151 Inform msg(
"EParticleStats");
153 auto pE_view = this->pcontainer_m->E.getView();
154 auto fphi_view = this->fcontainer_m->getPhi().getView();
160 double minEComponent = std::numeric_limits<T>::max();
161 double maxEComponent = std::numeric_limits<T>::min();
162 double minE = std::numeric_limits<T>::max();
163 double maxE = std::numeric_limits<T>::min();
166 int myRank = ippl::Comm->rank();
168 Kokkos::parallel_reduce(
170 KOKKOS_LAMBDA(
const int i,
double& loc_avgE,
double& loc_minEComponent,
171 double& loc_maxEComponent,
double& loc_minE,
double& loc_maxE) {
172 double EX = pE_view[i][0]*cc;
173 double EY = pE_view[i][1]*cc;
174 double EZ = pE_view[i][2]*cc;
176 double ENorm = Kokkos::sqrt(EX*EX + EY*EY + EZ*EZ);
180 loc_minEComponent = EX < loc_minEComponent ? EX : loc_minEComponent;
181 loc_minEComponent = EY < loc_minEComponent ? EY : loc_minEComponent;
182 loc_minEComponent = EZ < loc_minEComponent ? EZ : loc_minEComponent;
184 loc_maxEComponent = EX > loc_maxEComponent ? EX : loc_maxEComponent;
185 loc_maxEComponent = EY > loc_maxEComponent ? EY : loc_maxEComponent;
186 loc_maxEComponent = EZ > loc_maxEComponent ? EZ : loc_maxEComponent;
188 loc_minE = ENorm < loc_minE ? ENorm : loc_minE;
189 loc_maxE = ENorm > loc_maxE ? ENorm : loc_maxE;
191 Kokkos::Sum<T>(avgE), Kokkos::Min<T>(minEComponent),
192 Kokkos::Max<T>(maxEComponent), Kokkos::Min<T>(minE),
193 Kokkos::Max<T>(maxE));
196 minEComponent = maxEComponent = minE = maxE = avgE = 0.0;
199 MPI_Reduce(myRank == 0 ? MPI_IN_PLACE : &avgE, &avgE, 1, MPI_DOUBLE, MPI_SUM, 0, ippl::Comm->getCommunicator());
200 MPI_Reduce(myRank == 0 ? MPI_IN_PLACE : &minEComponent, &minEComponent, 1, MPI_DOUBLE, MPI_MIN, 0, ippl::Comm->getCommunicator());
201 MPI_Reduce(myRank == 0 ? MPI_IN_PLACE : &maxEComponent, &maxEComponent, 1, MPI_DOUBLE, MPI_MAX, 0, ippl::Comm->getCommunicator());
202 MPI_Reduce(myRank == 0 ? MPI_IN_PLACE : &minE, &minE, 1, MPI_DOUBLE, MPI_MIN, 0, ippl::Comm->getCommunicator());
203 MPI_Reduce(myRank == 0 ? MPI_IN_PLACE : &maxE, &maxE, 1, MPI_DOUBLE, MPI_MAX, 0, ippl::Comm->getCommunicator());
206 avgE /= (Np == 0) ? 1 : Np;
208 msg <<
"avgENorm = " << avgE << endl;
210 using mdrange_type = Kokkos::MDRangePolicy<Kokkos::Rank<3>>;
212 Kokkos::parallel_reduce(
213 "check phi", mdrange_type({0,0,0}, {fphi_view.extent(0),fphi_view.extent(1),fphi_view.extent(2)}),
214 KOKKOS_LAMBDA(
const int i,
const int j,
const int k,
double& loc_avgphi) {
215 double phi = fphi_view(i,j,k);
218 Kokkos::Sum<T>(avgphi));
220 MPI_Reduce(myRank == 0 ? MPI_IN_PLACE : &avgphi, &avgphi, 1, MPI_DOUBLE, MPI_SUM, 0, ippl::Comm->getCommunicator());
222 msg <<
"avgphi = " << avgphi << endl;
226template <
typename T,
unsigned Dim>
228 std::shared_ptr<ParticleContainer_t> pc = this->pcontainer_m;
230 auto Rview = pc->R.getView();
231 auto Pview = pc->P.getView();
238 double loc_centroid[2 *
Dim] = {};
239 double loc_moment[2 *
Dim][2 *
Dim] = {};
241 double centroid[2 *
Dim] = {};
242 double moment[2 *
Dim][2 *
Dim] = {};
244 for (
unsigned i = 0; i < 2 *
Dim; i++) {
245 loc_centroid[i] = 0.0;
246 for (
unsigned j = 0; j <= i; j++) {
247 loc_moment[i][j] = 0.0;
248 loc_moment[j][i] = 0.0;
252 for (
unsigned i = 0; i < 2 *
Dim; ++i) {
253 Kokkos::parallel_reduce(
254 "calc moments of particle distr.", ippl::getRangePolicy(Rview),
256 const int k,
double& cent,
double& mom0,
double& mom1,
double& mom2,
257 double& mom3,
double& mom4,
double& mom5) {
258 double part[2 *
Dim];
259 part[0] = Rview(k)[0];
260 part[1] = Pview(k)[0];
261 part[2] = Rview(k)[1];
262 part[3] = Pview(k)[1];
263 part[4] = Rview(k)[2];
264 part[5] = Pview(k)[2];
267 mom0 += part[i] * part[0];
268 mom1 += part[i] * part[1];
269 mom2 += part[i] * part[2];
270 mom3 += part[i] * part[3];
271 mom4 += part[i] * part[4];
272 mom5 += part[i] * part[5];
274 Kokkos::Sum<T>(loc_centroid[i]), Kokkos::Sum<T>(loc_moment[i][0]),
275 Kokkos::Sum<T>(loc_moment[i][1]), Kokkos::Sum<T>(loc_moment[i][2]),
276 Kokkos::Sum<T>(loc_moment[i][3]), Kokkos::Sum<T>(loc_moment[i][4]),
277 Kokkos::Sum<T>(loc_moment[i][5]));
281 MPI_Allreduce(loc_moment, moment, 2 *
Dim * 2 *
Dim, MPI_DOUBLE, MPI_SUM, ippl::Comm->getCommunicator());
282 MPI_Allreduce(loc_centroid, centroid, 2 *
Dim, MPI_DOUBLE, MPI_SUM, ippl::Comm->getCommunicator());
283 ippl::Comm->barrier();
285 double rmax_loc[
Dim];
286 double rmin_loc[
Dim];
290 for (
unsigned d = 0; d <
Dim; ++d) {
291 Kokkos::parallel_reduce(
292 "rel max", this->getLocalNum(),
293 KOKKOS_LAMBDA(
const int i,
double& mm) {
294 double tmp_vel = Rview(i)[d];
295 mm = tmp_vel > mm ? tmp_vel : mm;
297 Kokkos::Max<T>(rmax_loc[d]));
299 Kokkos::parallel_reduce(
300 "rel min", this->getLocalNum(),
301 KOKKOS_LAMBDA(
const int i,
double& mm) {
302 double tmp_vel = Rview(i)[d];
303 mm = tmp_vel < mm ? tmp_vel : mm;
305 Kokkos::Min<T>(rmin_loc[d]));
308 MPI_Allreduce(rmax_loc, rmax,
Dim, MPI_DOUBLE, MPI_MAX, ippl::Comm->getCommunicator());
309 MPI_Allreduce(rmin_loc, rmin,
Dim, MPI_DOUBLE, MPI_MIN, ippl::Comm->getCommunicator());
310 ippl::Comm->barrier();
313 for (
unsigned int i=0; i<
Dim; i++) {
319template <
typename T,
unsigned Dim>
321 this->fcontainer_m->getRho() = 0.0;
322 this->fsolver_m->runSolver();
325template <
typename T,
unsigned Dim>
328 Inform::FmtFlags_t ff = os.flags();
330 os << std::scientific;
331 os << level1 <<
"\n";
332 os <<
"* ************** B U N C H "
333 "********************************************************* \n";
334 os <<
"* PARTICLES = " << this->getTotalNum() <<
"\n";
335 os <<
"* CHARGE = " << this->qi_m*this->getTotalNum() <<
" (Cb) \n";
336 os <<
"* INTEGRATOR = " << integration_method_m <<
"\n";
340 os <<
"* RMS P = " << this->pcontainer_m->getRmsP() <<
" [beta gamma]\n";
341 os <<
"* Mean R: " << this->pcontainer_m->getMeanR() <<
" [m]\n";
342 os <<
"* Mean P: " << this->pcontainer_m->getMeanP() <<
" [beta gamma]\n";
343 os <<
"* MESH SPACING = " <<
Util::getLengthString( this->fcontainer_m->getMesh().getMeshSpacing(), 5) <<
"\n";
344 os <<
"* COMPDOM INCR = " << this->OPALFieldSolver_m->getBoxIncr() <<
" (%) \n";
345 os <<
"* FIELD LAYOUT = " << this->fcontainer_m->getFL() <<
"\n";
346 os <<
"* Centroid : \n* ";
347 for (
unsigned int i=0; i<2*
Dim; i++) {
348 os << this->pcontainer_m->getCentroid()[i] <<
" ";
350 os << endl <<
"* Cov Matrix : \n* ";
351 for (
unsigned int i=0; i<2*
Dim; i++) {
352 for (
unsigned int j=0; j<2*
Dim; j++) {
353 os << this->pcontainer_m->getCovMatrix()(i,j) <<
" ";
358 "********************************************************************************"
365template <
typename T,
unsigned Dim>
371 Inform m (
"bunchUpdate ");
373 auto *mesh = &this->fcontainer_m->getMesh();
374 auto *FL = &this->fcontainer_m->getFL();
378 pc->computeMinMaxR();
382 ippl::Vector<double, 3> o = pc->getMinR() - std::numeric_limits<T>::lowest();
383 ippl::Vector<double, 3> e = pc->getMaxR() + std::numeric_limits<T>::lowest();
384 ippl::Vector<double, 3> l = e - o;
387 mesh->setMeshSpacing(hr);
390 pc->getLayout().updateLayout(*FL, *mesh);
393 this->getFieldContainer()->setRMin(o);
394 this->getFieldContainer()->setRMax(e);
395 this->getFieldContainer()->setHr(hr);
398 this->loadbalancer_m->initializeORB(FL, mesh);
403template <
typename T,
unsigned Dim>
411 auto *mesh = &this->fcontainer_m->getMesh();
412 auto *FL = &this->fcontainer_m->getFL();
416 pc->computeMinMaxR();
418 ippl::Vector<double, 3> o = pc->getMinR();
419 ippl::Vector<double, 3> e = pc->getMaxR();
420 ippl::Vector<double, 3> l = e - o;
423 mesh->setMeshSpacing(
hr_m);
426 this->getFieldContainer()->setRMin(o);
427 this->getFieldContainer()->setRMax(e);
428 this->getFieldContainer()->setHr(
hr_m);
430 pc->getLayout().updateLayout(*FL, *mesh);
434 this->loadbalancer_m->initializeORB(FL, mesh);
440template <
typename T,
unsigned Dim>
442 static IpplTimings::TimerRef completeBinningT = IpplTimings::getTimer(
"bTotalBinningT");
445 std::shared_ptr<AdaptBins_t> bins = this->getBins();
448 IpplTimings::startTimer(completeBinningT);
449 bins->doFullRebin(bins->getMaxBinCount());
451 bins->sortContainerByBin();
454 bins->genAdaptiveHistogram();
455 IpplTimings::stopTimer(completeBinningT);
460 static IpplTimings::TimerRef SolveTimer = IpplTimings::getTimer(
"SolveTimer");
461 IpplTimings::startTimer(SolveTimer);
494 ippl::ParticleAttrib<T>* Q = &this->pcontainer_m->Q;
495 typename Base::particle_position_type* R = &this->pcontainer_m->R;
497 this->fcontainer_m->getRho() = 0.0;
500 scatter(*Q, *rho, *R);
503 const double qtot = this->qi_m * this->getTotalNum();
505 size_type localParticles = this->pcontainer_m->getLocalNum();
507 double relError = std::fabs((qtot - (*rho).sum()) / qtot);
509 ippl::Comm->reduce(localParticles, TotalParticles, 1, std::plus<size_type>());
511 if ((ippl::Comm->rank() == 0) && (relError > 1.0E-13)) {
512 Inform m(
"computeSelfFields w CICScatter ", INFORM_ALL_NODES);
513 m <<
"Time step: " << it_m
514 <<
" total particles in the sim. " << totalP_m
515 <<
" missing : " << totalP_m-TotalParticles
516 <<
" rel. error in charge conservation: " << relError << endl;
526 this->fsolver_m->runSolver();
528 gather(this->pcontainer_m->E, this->fcontainer_m->getE(), this->pcontainer_m->R);
531 Inform m(
"computeSelfFields w CICScatter ", INFORM_ALL_NODES);
532 double cellVolume = std::reduce(hr_m.begin(), hr_m.end(), 1., std::multiplies<double>());
533 m <<
"cellVolume= " << cellVolume << endl;
534 m <<
"Sum over E-field after gather = " << this->fcontainer_m->getE().sum() << endl;
546template <
typename T,
unsigned Dim>
551 Inform m(
"scatterCICPerBin");
552 m <<
"Scattering binIndex = " << binIndex <<
" to grid." << endl;
554 this->fcontainer_m->
getRho() = 0.0;
556 ippl::ParticleAttrib<T>* q = &this->pcontainer_m->Q;
557 typename Base::particle_position_type*
R = &this->pcontainer_m->R;
565 if (binIndex == -1) {
568 scatter(*q, *rho, *
R);
571 Q = this->
qi_m * this->
bins_m->getNPartInBin(binIndex,
true);
572 scatter(*q, *rho, *
R, this->
bins_m->getBinIterationPolicy(binIndex), this->bins_m->getHashArray());
575 m <<
"gammz= " << this->pcontainer_m->getMeanP()[2] << endl;
578 double relError = std::fabs((
Q - (*rho).sum()) /
Q);
580 size_type localParticles = this->pcontainer_m->getLocalNum();
581 size_type totalP_check = (binIndex == -1) ?
totalP_m : this->pcontainer_m->getTotalNum();
583 m <<
"computeSelfFields sum rho = " << (*rho).sum() <<
", relError = " << relError << endl;
585 ippl::Comm->reduce(localParticles, TotalParticles, 1, std::plus<size_type>());
587 if (ippl::Comm->rank() == 0) {
588 if (TotalParticles != totalP_check || relError > 1e-10) {
589 m <<
"Time step: " <<
it_m << endl;
590 m <<
"Total particles in the sim. " << totalP_check <<
" "
591 <<
"after update: " << TotalParticles << endl;
592 m <<
"Rel. error in charge conservation: " << relError << endl;
598 double cellVolume = std::reduce(hr.begin(), hr.end(), 1., std::multiplies<double>());
600 m <<
"cellVolume= " << cellVolume << endl;
602 (*rho) = (*rho) / cellVolume;
605 if (this->fsolver_m->getStype() !=
"OPEN") {
607 for (
unsigned d = 0; d < 3; d++) {
608 size *= rmax[d] - rmin[d];
610 *rho = *rho - (
Q / size);
ippl::Field< double, Dim, ViewArgs... > Field_t
ippl::Field< ippl::Vector< T, Dim >, Dim, ViewArgs... > VField_t
ippl::Vector< T, Dim > Vector_t
ippl::ParticleBase< ippl::ParticleSpatialLayout< T, Dim > > Base
FieldContainer< double, 3 > FieldContainer_t
ippl::detail::size_type size_type
std::string getLengthString(double spos, unsigned int precision=3)
long long localTrackStep_m
step in a TRACK command
void gatherLoadBalanceStatistics()
Vector_t< double, Dim > rmin_m
Solver_t< T, Dim > solver_m
std::array< bool, Dim > decomp_m
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
bool isFirstRepartition_m
Vector_t< T, Dim > RefPartR_m
double getRho(int x, int y, int z)
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
long long globalTrackStep_m
if multiple TRACK commands
size_t getLocalNum() const
void setSolver(std::string solver)
Vector_t< double, Dim > R(size_t i)
std::string integration_method_m
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
double getCouplingConstant() const
size_t getTotalNum() const
Vector_t< T, Dim > RefPartP_m
std::shared_ptr< Distribution > OPALdist_m
std::shared_ptr< AdaptBins_t > getBins()
ParticleAttrib< double > Q
std::unique_ptr< size_t[]> globalPartPerNode_m
std::shared_ptr< AdaptBins_t > bins_m
void setTempEField(std::shared_ptr< VField_t< T, Dim > > Etmp)