11#ifndef PHARE_CORE_PUSHER_BORIS_HPP
22#define PHARE_CORE_PUSHER_BORIS_HPP
33
4+
5+ #include " core/errors.hpp"
6+ #include " core/logger.hpp"
7+ #include " core/numerics/pusher/pusher.hpp"
8+
9+
410#include < array>
511#include < cmath>
612#include < cstddef>
7- #include < algorithm >
13+ #include < sstream >
814#include < iterator>
9- #include < stdexcept>
10- #include " core/numerics/pusher/pusher.hpp"
11- #include " core/utilities/range/range.hpp"
12- #include " core/errors.hpp"
13- #include " core/logger.hpp"
14- #include " core/data/particles/particle.hpp"
15+ #include < algorithm>
16+ #include < exception>
1517
1618namespace PHARE ::core
1719{
@@ -22,6 +24,18 @@ template<std::size_t dim, typename ParticleRange, typename Electromag, typename
2224class BorisPusher
2325 : public Pusher<dim, ParticleRange, Electromag, Interpolator, BoundaryCondition, GridLayout>
2426{
27+ struct MoveTwoCellException : std::exception
28+ {
29+ MoveTwoCellException (double const d, double const v)
30+ : delta{d}
31+ , vel{v}
32+ {
33+ }
34+
35+ double delta, vel;
36+ };
37+
38+
2539public:
2640 using Super
2741 = Pusher<dim, ParticleRange, Electromag, Interpolator, BoundaryCondition, GridLayout>;
@@ -91,19 +105,33 @@ class BorisPusher
91105
92106 rangeOut = firstSelector (rangeOut);
93107
94-
95108 double const dto2m = 0.5 * dt_ / mass;
96109 for (auto idx = rangeOut.ibegin (); idx < rangeOut.iend (); ++idx)
97110 {
98111 auto & currPart = rangeOut.array ()[idx];
99112
100113 // get electromagnetic fields interpolated on the particles of rangeOut stop at newEnd.
101114 // get the particle velocity from t=n to t=n+1
102- accelerate_ (currPart, interpolator (currPart, emFields, layout), dto2m);
115+ auto const & local_em = interpolator (currPart, emFields, layout);
116+ accelerate_ (currPart, local_em, dto2m);
103117
104118 // now advance the particles from t=n+1/2 to t=n+1 using v_{n+1} just calculated
105119 // and get a pointer to the first leaving particle
106- postPushStep_ (rangeOut, idx);
120+ try
121+ {
122+ postPushStep_ (rangeOut, idx);
123+ }
124+ catch (DictionaryException const & bex)
125+ {
126+ auto ex = bex;
127+ auto const & [e, b] = local_em;
128+ for (std::uint16_t i = 0 ; i < 3 ; ++i)
129+ ex (" E_" + std::to_string (i), std::to_string (e[i]));
130+ for (std::uint16_t i = 0 ; i < 3 ; ++i)
131+ ex (" B_" + std::to_string (i), std::to_string (b[i]));
132+ ex (" level" , std::to_string (layout.levelNumber ()));
133+ throw ex;
134+ }
107135 }
108136
109137 return secondSelector (rangeOut);
@@ -130,22 +158,20 @@ class BorisPusher
130158 std::array<int , dim> newCell;
131159 for (std::size_t iDim = 0 ; iDim < dim; ++iDim)
132160 {
133- double delta
161+ double const delta
134162 = partIn.delta [iDim] + static_cast <double >(halfDtOverDl_[iDim] * partIn.v [iDim]);
135163
136- double iCell = std::floor (delta);
137164 if (std::abs (delta) > 2 )
138- {
139- PHARE_LOG_ERROR ( " Error, particle moves more than 1 cell, delta >2 " );
140- }
165+ throw MoveTwoCellException{delta, partIn. v [iDim]};
166+
167+ auto const iCell = static_cast < int >( std::floor (delta));
141168 partOut.delta [iDim] = delta - iCell;
142- newCell[iDim] = static_cast < int >( iCell + partIn.iCell [iDim]) ;
169+ newCell[iDim] = iCell + partIn.iCell [iDim];
143170 }
144171 return newCell;
145172 }
146173
147174
148-
149175 /* * advance the particles in rangeIn of half a time step and store them
150176 * in rangeOut.
151177 * @return the function returns and iterator on the first leaving particle, as
@@ -172,18 +198,39 @@ class BorisPusher
172198 outParticles[outIdx].weight = inParticles[inIdx].weight ;
173199 outParticles[outIdx].v = inParticles[inIdx].v ;
174200
175- auto newCell = advancePosition_ (inParticles[inIdx], outParticles[outIdx]);
176- if (newCell != inParticles[inIdx].iCell )
177- outParticles.change_icell (newCell, outIdx);
201+ try
202+ {
203+ auto newCell = advancePosition_ (inParticles[inIdx], outParticles[outIdx]);
204+ if (newCell != inParticles[inIdx].iCell )
205+ outParticles.change_icell (newCell, outIdx);
206+ }
207+ catch (MoveTwoCellException const & e)
208+ {
209+ std::stringstream ss;
210+ ss << " PrePush Particle moved 2 cells with delta/vel: " ;
211+ ss << e.delta << " /" << e.vel << std::endl;
212+ DictionaryException ex{" cause" , ss.str ()};
213+ throw ex;
214+ }
178215 }
179216 }
180217
181218 void postPushStep_ (ParticleRange& range, std::size_t idx)
182219 {
183- auto & particles = range.array ();
184- auto newCell = advancePosition_ (particles[idx], particles[idx]);
185- if (newCell != particles[idx].iCell )
186- particles.change_icell (newCell, idx);
220+ try
221+ {
222+ auto & particles = range.array ();
223+ auto newCell = advancePosition_ (particles[idx], particles[idx]);
224+ if (newCell != particles[idx].iCell )
225+ particles.change_icell (newCell, idx);
226+ }
227+ catch (MoveTwoCellException const & e)
228+ {
229+ std::stringstream ss;
230+ ss << " PostPush Particle moved 2 cells with delta/vel: " ;
231+ ss << e.delta << " /" << e.vel << std::endl;
232+ throw DictionaryException{}(" cause" , ss.str ());
233+ }
187234 }
188235
189236
0 commit comments