Navigation

Main Page
Download
Support
Installation
Tutorial
Examples
Reference Manual
   Version 1.0.6dev
      Class Index
      File List
   Version 1.0.6
   Version 1.0.5new_solver
   Version 1.0.5dev
   Version 1.0.5b
   Version 1.0.4dev
   Version 1.0.4
Publications


Hosted by Get Ion Beam Simulator at SourceForge.net. Fast, secure and Free Open Source software downloads
particledatabaseimp.hpp
Go to the documentation of this file.
1 
5 /* Copyright (c) 2005-2013,2015,2022 Taneli Kalvas. All rights reserved.
6  *
7  * You can redistribute this software and/or modify it under the terms
8  * of the GNU General Public License as published by the Free Software
9  * Foundation; either version 2 of the License, or (at your option)
10  * any later version.
11  *
12  * This library is distributed in the hope that it will be useful, but
13  * WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15  * General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this library (file "COPYING" included in the package);
19  * if not, write to the Free Software Foundation, Inc., 51 Franklin
20  * Street, Fifth Floor, Boston, MA 02110-1301 USA
21  *
22  * If you have questions about your rights to use or distribute this
23  * software, please contact Berkeley Lab's Technology Transfer
24  * Department at TTD@lbl.gov. Other questions, comments and bug
25  * reports should be sent directly to the author via email at
26  * taneli.kalvas@jyu.fi.
27  *
28  * NOTICE. This software was developed under partial funding from the
29  * U.S. Department of Energy. As such, the U.S. Government has been
30  * granted for itself and others acting on its behalf a paid-up,
31  * nonexclusive, irrevocable, worldwide license in the Software to
32  * reproduce, prepare derivative works, and perform publicly and
33  * display publicly. Beginning five (5) years after the date
34  * permission to assert copyright is obtained from the U.S. Department
35  * of Energy, and subject to any subsequent five (5) year renewals,
36  * the U.S. Government is granted for itself and others acting on its
37  * behalf a paid-up, nonexclusive, irrevocable, worldwide license in
38  * the Software to reproduce, prepare derivative works, distribute
39  * copies to the public, perform publicly and display publicly, and to
40  * permit others to do so.
41  */
42 
43 #ifndef PARTICLEDATABASEIMP_HPP
44 #define PARTICLEDATABASEIMP_HPP 1
45 
46 
47 #include "ibsimu.hpp"
48 #include "statusprint.hpp"
49 #include "timer.hpp"
50 #include "file.hpp"
51 #include "particles.hpp"
52 #include "particleiterator.hpp"
53 #include "particlestepper.hpp"
55 
56 
58 
59 protected:
60 
61  const Geometry &_geom;
62  double _epsabs;
63  double _epsrel;
66  uint32_t _maxsteps;
67  double _maxt;
68  bool _save_points;
69  uint32_t _trajdiv;
71  bool _mirror[6];
73  double _rhosum;
77  uint32_t _iteration;
87  ParticleDataBaseImp( ParticleDataBase *pdb, const Geometry &geom );
88 
89  ParticleDataBaseImp( ParticleDataBase *pdb, std::istream &s, const Geometry &geom );
90 
92 
93  const ParticleDataBaseImp &operator=( const ParticleDataBaseImp &pdb );
94 
99  static double energy_to_velocity( double E, double m );
100 
101  void save( std::ostream &os ) const;
102 
103 public:
104 
105  virtual ~ParticleDataBaseImp();
106 
107  void set_accuracy( double epsabs, double epsrel );
108 
109  void set_bfield_suppression( const CallbackFunctorD_V *functor );
110 
111  void set_trajectory_handler_callback( TrajectoryHandlerCallback *thand_cb );
112 
113  void set_trajectory_end_callback( TrajectoryEndCallback *tend_cb );
114 
115  void set_trajectory_surface_collision_callback( TrajectorySurfaceCollisionCallback *tsur_cb );
116 
117  void set_relativistic( bool enable );
118 
119  void set_surface_collision( bool surface_collision );
120 
121  void set_polyint( bool polyint );
122 
123  bool get_polyint( void ) const;
124 
125  void set_trajectory_interpolation( trajectory_interpolation_e intrp );
126 
127  trajectory_interpolation_e get_trajectory_interpolation( void ) const;
128 
129  void set_scharge_deposition( scharge_deposition_e type );
130 
131  scharge_deposition_e get_scharge_deposition( void ) const;
132 
133  void set_max_steps( uint32_t maxsteps );
134 
135  void set_max_time( double maxt );
136 
137  void set_save_all_points( bool save_points );
138 
139  void set_save_trajectories( uint32_t div );
140 
141  uint32_t get_save_trajectories( void ) const;
142 
143  void set_mirror( const bool mirror[6] );
144 
145  void get_mirror( bool mirror[6] ) const;
146 
147  int get_iteration_number( void ) const;
148 
149  double get_rhosum( void ) const;
150 
151  void set_rhosum( double rhosum );
152 
153  const ParticleStatistics &get_statistics( void ) const;
154 
155  virtual geom_mode_e geom_mode() const = 0;
156 
157  virtual size_t size( void ) const = 0;
158 
159  virtual size_t traj_size( uint32_t i ) const = 0;
160 
161  virtual double traj_length( uint32_t i ) const = 0;
162 
163  virtual void trajectory_point( double &t, Vec3D &loc, Vec3D &vel, uint32_t i, uint32_t j ) const = 0;
164 
165  virtual void trajectories_at_plane( TrajectoryDiagnosticData &tdata,
166  coordinate_axis_e axis,
167  double val,
168  const std::vector<trajectory_diagnostic_e> &diagnostics ) const = 0;
169 
170  virtual void clear( void ) = 0;
171 
172  virtual void clear_trajectories( void ) = 0;
173 
174  virtual void clear_trajectory( size_t a ) = 0;
175 
176  virtual void reset_trajectories( void ) = 0;
177 
178  virtual void reset_trajectory( size_t a ) = 0;
179 
180  virtual void reserve( size_t size ) = 0;
181 
182  virtual void build_trajectory_density_field( MeshScalarField &tdens ) const = 0;
183 
184  virtual void iterate_trajectories( MeshScalarField &scharge, const VectorField &efield,
185  const VectorField &bfield ) = 0;
186 
187  virtual void step_particles( MeshScalarField &scharge, const VectorField &efield,
188  const VectorField &bfield, double dt ) = 0;
189 
190  void debug_print( std::ostream &os ) const;
191 };
192 
193 
194 template<class PP> class ParticleDataBasePPImp : public ParticleDataBaseImp {
195 
198  static void add_diagnostics( TrajectoryDiagnosticData &tdata, const PP &x,
199  const Particle<PP> &p, int crd, int index ) {
200  //std::cout << "add_diagnostics():\n";
201  for( size_t a = 0; a < tdata.diag_size(); a++ ) {
202  //std::cout << " diagnostic[" << a << "] = " << tdata.diagnostic(a) << "\n";
203 
204  double data = 0.0;
205  switch( tdata.diagnostic( a ) ) {
206  case DIAG_NONE:
207  data = 0.0;
208  break;
209  case DIAG_T:
210  data = x[0];
211  break;
212  case DIAG_X:
213  data = x[1];
214  break;
215  case DIAG_VX:
216  data = x[2];
217  break;
218  case DIAG_Y:
219  case DIAG_R:
220  data = x[3];
221  break;
222  case DIAG_VY:
223  case DIAG_VR:
224  data = x[4];
225  break;
226  case DIAG_Z:
227  data = x[5];
228  break;
229  case DIAG_VZ:
230  data = x[6];
231  break;
232  case DIAG_W:
233  data = x[5];
234  break;
235  case DIAG_VTHETA:
236  data = x[5]*x[3];
237  break;
238  case DIAG_XP:
239  data = x[2]/x[2*crd+2];
240  break;
241  case DIAG_YP:
242  case DIAG_RP:
243  data = x[4]/x[2*crd+2];
244  break;
245  case DIAG_AP:
246  data = x[3]*x[5]/x[2*crd+2];
247  break;
248  case DIAG_ZP:
249  data = x[6]/x[2*crd+2];
250  break;
251  case DIAG_CURR:
252  data = p.IQ();
253  break;
254  case DIAG_QM:
255  data = (p.q()/CHARGE_E) / (p.m()/MASS_U);
256  break;
257  case DIAG_CHARGE:
258  data = p.q()/CHARGE_E;
259  break;
260  case DIAG_MASS:
261  data = p.m()/MASS_U;
262  break;
263  case DIAG_EK:
264  {
265  double beta = x.velocity().norm2()/SPEED_C;
266  if( beta < 1.0e-4 )
267  data = 0.5*p.m()*x.velocity().ssqr()/CHARGE_E;
268  else if( beta >= 1.0 )
269  throw( ErrorUnimplemented( ERROR_LOCATION, "particle velocity over light speed" ) );
270  else {
271  double gamma = 1.0 / sqrt( 1.0 - beta*beta );
272  double Ek = p.m()*SPEED_C2*( gamma - 1.0 );
273  data = Ek/CHARGE_E;
274  }
275  break;
276  }
277  case DIAG_NO:
278  data = index;
279  break;
280  default:
282  break;
283  }
284  //std::cout << " adding data = " << data << "\n";
285  tdata.add_data( a, data );
286  }
287  }
288 
289 protected:
290 
291  std::vector<Particle<PP> *> _particles;
298  if( _geom.geom_mode() != PP::geom_mode() )
299  throw( Error( ERROR_LOCATION, "Differing geometry modes" ) );
300  }
301 
304  ParticleDataBasePPImp( ParticleDataBase *pdb, std::istream &s, const Geometry &geom )
305  : ParticleDataBaseImp(pdb,s,geom), _scheduler(_particles) {
306 
307  uint32_t N = read_int32( s );
308  ibsimu.message( 1 ) << "Reading " << N << " particles.\n";
309  _particles.reserve( N );
310  for( uint32_t a = 0; a < N; a++ )
311  _particles.push_back( new Particle<PP>( s ) );
312 
313  ibsimu.dec_indent();
314  }
315 
320 
321  _particles.reserve( pdb._particles.size() );
322  for( size_t a = 0; a < pdb._particles.size(); a++ )
323  _particles.push_back( new Particle<PP>( *pdb._particles[a] ) );
324  }
325 
329 
330  for( size_t a; a < pdb._particles.size(); a++ )
331  delete _particles[a];
332  _particles.clear();
333  _particles.reserve( pdb._particles.size() );
334  for( size_t a = 0; a < pdb._particles.size(); a++ )
335  _particles.push_back( new Particle<PP>( *pdb._particles[a] ) );
336  return( *this );
337  }
338 
339 public:
340 
341  virtual ~ParticleDataBasePPImp() {
342  // Delete particles
343  for( size_t a = 0; a < _particles.size(); a++ )
344  delete( _particles[a] );
345  }
346 
347  virtual geom_mode_e geom_mode() const {
348  return( PP::geom_mode() );
349  }
350 
351  virtual size_t size( void ) const {
352  return( _particles.size() );
353  }
354 
355  Particle<PP> &particle( uint32_t i ) {
356  return( *_particles[i] );
357  }
358 
359  const Particle<PP> &particle( uint32_t i ) const {
360  return( *_particles[i] );
361  }
362 
363  virtual double traj_length( uint32_t i ) const {
364 
365  size_t N = _particles[i]->traj_size();
366  double len = 0.0;
367  if( N < 2 )
368  return( 0.0 );
369  Vec3D x1 = _particles[i]->traj(0).location();
370  for( size_t b = 1; b < N; b++ ) {
371  Vec3D x2 = _particles[i]->traj(b).location();
372  len += norm2(x2-x1);
373  x1 = x2;
374  }
375 
376  return( len );
377  }
378 
379  virtual size_t traj_size( uint32_t i ) const {
380  return( _particles[i]->traj_size() );
381  }
382 
383  const PP &trajectory_point( uint32_t i, uint32_t j ) const {
384  return( _particles[i]->traj(j) );
385  }
386 
387  virtual void trajectory_point( double &t, Vec3D &loc, Vec3D &vel, uint32_t i, uint32_t j ) const {
388  PP x = _particles[i]->traj(j);
389  t = x[0];
390  loc = x.location();
391  vel = x.velocity();
392  }
393 
394  virtual void trajectories_at_plane( std::vector< Particle<PP> > &tdata,
395  coordinate_axis_e axis,
396  double val ) const {
397 
398  ibsimu.message( 1 ) << "Making trajectory diagnostics at "
399  << coordinate_axis_string[axis] << " = " << val << "\n";
400  ibsimu.inc_indent();
401 
402  // Check query
403  switch( PP::geom_mode() ) {
404  case MODE_1D:
405  throw( Error( ERROR_LOCATION, "unsupported dimension number" ) );
406  break;
407  case MODE_2D:
408  if( axis == AXIS_R || axis == AXIS_Z )
409  throw( Error( ERROR_LOCATION, "nonexistent axis" ) );
410  break;
411  case MODE_CYL:
412  if( axis == AXIS_Y || axis == AXIS_Z )
413  throw( Error( ERROR_LOCATION, "nonexistent axis" ) );
414  break;
415  case MODE_3D:
416  if( axis == AXIS_R )
417  throw( Error( ERROR_LOCATION, "nonexistent axis" ) );
418  break;
419  default:
420  throw( Error( ERROR_LOCATION, "unsupported dimension number" ) );
421  }
422 
423  // Prepare output vector
424  tdata.clear();
425 
426  // Set coordinate index
427  int crd;
428  switch( axis ) {
429  case AXIS_X:
430  crd = 0;
431  break;
432  case AXIS_Y:
433  case AXIS_R:
434  crd = 1;
435  break;
436  case AXIS_Z:
437  crd = 2;
438  break;
439  default:
440  throw( Error( ERROR_LOCATION, "unsupported axis" ) );
441  }
442 
443  // Scan through particle trajectory points
444  double Isum = 0.0;
445  std::vector<PP> intsc;
446  for( size_t a = 0; a < _particles.size(); a++ ) {
447  size_t N = _particles[a]->traj_size();
448  if( N < 2 )
449  continue;
450  PP x1 = _particles[a]->traj(0);
451  for( size_t b = 1; b < N; b++ ) {
452  PP x2 = _particles[a]->traj(b);
453  intsc.clear();
454  size_t nintsc;
455  if( b == 1 )
456  nintsc = PP::trajectory_intersections_at_plane( intsc, crd, val, x1, x2, -1 );
457  else if( b == N-1 )
458  nintsc = PP::trajectory_intersections_at_plane( intsc, crd, val, x1, x2, +1 );
459  else
460  nintsc = PP::trajectory_intersections_at_plane( intsc, crd, val, x1, x2, 0 );
461  for( size_t c = 0; c < nintsc; c++ ) {
462  Isum += _particles[a]->IQ();
463  tdata.push_back( Particle<PP>( _particles[a]->IQ(), _particles[a]->q(),
464  _particles[a]->m(), intsc[c] ) );
465  }
466 
467  x1 = x2;
468  }
469  }
470 
471  ibsimu.message( 1 ) << "number of trajectories = " << tdata.size() << "\n";
472  if( PP::geom_mode() == MODE_2D )
473  ibsimu.message( 1 ) << "total current = " << Isum << " A/m\n";
474  else
475  ibsimu.message( 1 ) << "total current = " << Isum << " A\n";
476  ibsimu.dec_indent();
477  }
478 
479  virtual void trajectories_at_plane( TrajectoryDiagnosticData &tdata,
480  coordinate_axis_e axis,
481  double val,
482  const std::vector<trajectory_diagnostic_e> &diagnostics ) const {
483 
484  ibsimu.message( 1 ) << "Making trajectory diagnostics at "
485  << coordinate_axis_string[axis] << " = " << val << "\n";
486  ibsimu.inc_indent();
487 
488  // Check query
489  switch( PP::geom_mode() ) {
490  case MODE_1D:
491  throw( Error( ERROR_LOCATION, "unsupported dimension number" ) );
492  break;
493  case MODE_2D:
494  if( axis == AXIS_R || axis == AXIS_Z )
495  throw( Error( ERROR_LOCATION, "nonexistent axis" ) );
496  break;
497  case MODE_CYL:
498  if( axis == AXIS_Y || axis == AXIS_Z )
499  throw( Error( ERROR_LOCATION, "nonexistent axis" ) );
500  break;
501  case MODE_3D:
502  if( axis == AXIS_R )
503  throw( Error( ERROR_LOCATION, "nonexistent axis" ) );
504  break;
505  default:
506  throw( Error( ERROR_LOCATION, "unsupported dimension number" ) );
507  }
508 
509  // Check diagnostics query validity
510  for( size_t a = 0; a < diagnostics.size(); a++ ) {
511  if( diagnostics[a] == DIAG_NONE )
512  throw( Error( ERROR_LOCATION, "invalid diagnostics query \'DIAG_NONE\'" ) );
513  else if( PP::geom_mode() != MODE_CYL && (diagnostics[a] == DIAG_R ||
514  diagnostics[a] == DIAG_VR ||
515  diagnostics[a] == DIAG_RP ||
516  diagnostics[a] == DIAG_W ||
517  diagnostics[a] == DIAG_VTHETA ||
518  diagnostics[a] == DIAG_AP) )
519  throw( Error( ERROR_LOCATION, "invalid diagnostics query for geometry type" ) );
520  else if( PP::geom_mode() != MODE_3D && (diagnostics[a] == DIAG_Z ||
521  diagnostics[a] == DIAG_VZ ||
522  diagnostics[a] == DIAG_ZP) )
523  throw( Error( ERROR_LOCATION, "invalid diagnostics query for geometry type" ) );
524  else if( diagnostics[a] == DIAG_O ||
525  diagnostics[a] == DIAG_VO ||
526  diagnostics[a] == DIAG_OP ||
527  diagnostics[a] == DIAG_P ||
528  diagnostics[a] == DIAG_VP ||
529  diagnostics[a] == DIAG_PP ||
530  diagnostics[a] == DIAG_Q ||
531  diagnostics[a] == DIAG_VQ )
532  throw( Error( ERROR_LOCATION, "invalid diagnostics query for trajectories_at_plane()\n"
533  "use trajectories_at_free_plane()" ) );
534  }
535 
536  // Prepare output vector
537  tdata.clear();
538  for( size_t a = 0; a < diagnostics.size(); a++ ) {
539  tdata.add_data_column( diagnostics[a] );
540  }
541 
542  // Set coordinate index
543  int crd;
544  switch( axis ) {
545  case AXIS_X:
546  crd = 0;
547  break;
548  case AXIS_Y:
549  case AXIS_R:
550  crd = 1;
551  break;
552  case AXIS_Z:
553  crd = 2;
554  break;
555  default:
556  throw( Error( ERROR_LOCATION, "unsupported axis" ) );
557  }
558 
559  // Scan through particle trajectory points
560  double Isum = 0.0;
561  std::vector<PP> intsc;
562  for( size_t a = 0; a < _particles.size(); a++ ) {
563  size_t N = _particles[a]->traj_size();
564  if( N < 2 )
565  continue;
566  PP x1 = _particles[a]->traj(0);
567  for( size_t b = 1; b < N; b++ ) {
568  PP x2 = _particles[a]->traj(b);
569  intsc.clear();
570  size_t nintsc;
571  if( b == 1 )
572  nintsc = PP::trajectory_intersections_at_plane( intsc, crd, val, x1, x2, -1 );
573  else if( b == N-1 )
574  nintsc = PP::trajectory_intersections_at_plane( intsc, crd, val, x1, x2, +1 );
575  else
576  nintsc = PP::trajectory_intersections_at_plane( intsc, crd, val, x1, x2, 0 );
577  for( size_t c = 0; c < nintsc; c++ ) {
578  Isum += _particles[a]->IQ();
579  add_diagnostics( tdata, intsc[c], *_particles[a], crd, a );
580  }
581 
582  x1 = x2;
583  }
584  }
585 
586  ibsimu.message( 1 ) << "number of trajectories = " << tdata.traj_size() << "\n";
587  if( PP::geom_mode() == MODE_2D )
588  ibsimu.message( 1 ) << "total current = " << Isum << " A/m\n";
589  else
590  ibsimu.message( 1 ) << "total current = " << Isum << " A\n";
591  ibsimu.dec_indent();
592  }
593 
594  virtual void clear( void ) {
595  for( size_t a = 0; a < _particles.size(); a++ )
596  delete( _particles[a] );
597  _particles.clear();
598  _rhosum = 0.0;
599  }
600 
601  virtual void clear_trajectories( void ) {
602  for( uint32_t a = 0; a < _particles.size(); a++ )
603  _particles[a]->clear_trajectory();
604  }
605 
606  virtual void clear_trajectory( size_t a ) {
607  if( a >= _particles.size() )
608  throw( ErrorRange( ERROR_LOCATION, a, _particles.size() ) );
609  _particles[a]->clear_trajectory();
610  }
611 
612  virtual void reset_trajectories( void ) {
613  for( uint32_t a = 0; a < _particles.size(); a++ )
614  _particles[a]->reset_trajectory();
615  }
616 
617  virtual void reset_trajectory( size_t a ) {
618  if( a >= _particles.size() )
619  throw( ErrorRange( ERROR_LOCATION, a, _particles.size() ) );
620  _particles[a]->reset_trajectory();
621  }
622 
623  virtual void reserve( size_t size ) {
624  _particles.reserve( size );
625  }
626 
627  void add_particle( const Particle<PP> &pp ) {
629  try {
630  _particles.push_back( new Particle<PP>( pp ) );
631  } catch( const std::bad_alloc & ) {
632  throw( ErrorNoMem( ERROR_LOCATION, "Out of memory adding particle" ) );
633  }
635  }
636 
637  void add_particle( double IQ, double q, double m, const PP &x ) {
638  add_particle( Particle<PP>( IQ, CHARGE_E*q, MASS_U*m, x ) );
639  }
640 
641  virtual void iterate_trajectories( MeshScalarField &scharge, const VectorField &efield,
642  const VectorField &bfield ) {
643 
644  Timer t;
645  ibsimu.message( 1 ) << "Calculating particle trajectories\n";
646  ibsimu.inc_indent();
647  if( _surface_collision )
648  ibsimu.message( 1 ) << "Using surface collision model\n";
649  else
650  ibsimu.message( 1 ) << "Using solid collision model\n";
651  if( _relativistic )
652  ibsimu.message( 1 ) << "Using relativistic iterator\n";
653  else
654  ibsimu.message( 1 ) << "Using non-relativistic iterator\n";
655  _iteration++;
656 
657  StatusPrint sp;
658  if( ibsimu.output_is_cout() ) {
659  std::stringstream ss;
660  ss << " " << "0 / " << _particles.size();
661  sp.print( ss.str() );
662  }
663 
664  // Check geometry mode
665  if( _geom.geom_mode() != PP::geom_mode() )
666  throw( Error( ERROR_LOCATION, "Differing geometry modes" ) );
667  if( _geom != scharge )
668  throw( Error( ERROR_LOCATION, "Space charge mesh differs from geometry" ) );
669 
670  // Clear space charge
671  scharge.clear();
672 
673  // Reset statistics
674  _stat.reset( _geom.number_of_boundaries() );
675 
676  // Check number of particles
677  if( _particles.size() == 0 ) {
678  ibsimu.message( 1 ) << "no particles to calculate\n";
679  ibsimu.dec_indent();
680  return;
681  }
682 
683  // Make solvers
684  pthread_mutex_t scharge_mutex = PTHREAD_MUTEX_INITIALIZER;
685  std::vector<ParticleIterator<PP> *> iterators;
686  for( uint32_t a = 0; a < ibsimu.get_thread_count(); a++ ) {
687 
688  iterators.push_back( new ParticleIterator<PP>( PARTICLE_ITERATOR_ADAPTIVE, _epsabs, _epsrel,
690  _save_points, _trajdiv, _mirror, &scharge,
691  &scharge_mutex, &efield, &bfield, &_geom ) );
692  iterators[a]->set_trajectory_handler_callback( _thand_cb );
693  iterators[a]->set_trajectory_end_callback( _tend_cb, _pdb );
694  iterators[a]->set_trajectory_surface_collision_callback( _tsur_cb );
695  iterators[a]->set_bfield_suppression_callback( _bsup_cb );
696  iterators[a]->set_relativistic( _relativistic );
697  iterators[a]->set_surface_collision( _surface_collision );
698  }
699 
700  // Run scheduler
701  _scheduler.run( iterators );
702 
703  // Print statistics
704  if( ibsimu.output_is_cout() ) {
705  while( !_scheduler.wait_finish() ) {
706  std::stringstream ss;
707  ss << " " << _scheduler.get_solved_count() << " / "
709  sp.print( ss.str() );
710  }
711  }
712 
713  // Finish scheduler
714  _scheduler.finish();
715 
716  // Print final statistics
717  if( ibsimu.output_is_cout() ) {
718  std::stringstream ss;
719  ss << " " << _scheduler.get_solved_count() << " / "
720  << _scheduler.get_problem_count() << " Done\n";
721  sp.print( ss.str(), true );
722  }
723 
724  if( _scheduler.is_error() ) {
725  // Throw the error
726  std::vector<Error> err;
727  std::vector<int32_t> part;
728  _scheduler.get_errors( err, part );
729  throw( err[0] );
730  }
731 
732  // Collect statistics. Free all allocated memory.
733  for( uint32_t a = 0; a < ibsimu.get_thread_count(); a++ ) {
734  ParticleStatistics stat = iterators[a]->get_statistics();
735  _stat += stat;
736  delete iterators[a];
737  }
738 
740  scharge_finalize_linear( scharge );
741  else
742  scharge_finalize_pic( scharge );
743 
744  t.stop();
745  ibsimu.message( 1 ) << "Particle histories (" << _particles.size() << " total):\n";
746  ibsimu.message( 1 ) << " flown = " << _stat.bound_collisions() << "\n";
747  ibsimu.message( 1 ) << " time limited = " << _stat.end_time() << "\n";
748  ibsimu.message( 1 ) << " step count limited = " << _stat.end_step() << "\n";
749  ibsimu.message( 1 ) << " bad definitions = " << _stat.end_baddef() << "\n";
750  for( size_t a = 1; a <= _stat.number_of_boundaries(); a++ ) {
751  ibsimu.message( 1 ) << " beam to boundary " << a << " = " << _stat.bound_current(a)
752  << " " << PP::IQ_unit() << " (" << _stat.bound_collisions(a) << " particles)" << "\n";
753  }
754  ibsimu.message( 1 ) << " total steps = " << _stat.sum_steps() << "\n";
755  ibsimu.message( 1 ) << " steps per particle (ave) = " <<
756  _stat.sum_steps()/(double)_particles.size() << "\n";
757  ibsimu.message( 1 ) << "time used = " << t << "\n";
758  ibsimu.dec_indent();
759  }
760 
761 
762  virtual void step_particles( MeshScalarField &scharge, const VectorField &efield,
763  const VectorField &bfield, double dt ) {
764 
765  Timer t;
766  ibsimu.message( 1 ) << "Stepping particles\n";
767  ibsimu.inc_indent();
768 
769  // Clear space charge
770  scharge.clear();
771 
772  // Go through particles
773  ParticleStepper<PP> ps( dt, _trajdiv, _mirror, &scharge,
774  &efield, &bfield, &_geom );
775  for( uint32_t a = 0; a < _particles.size(); a++ ) {
776  if( (*_particles[a])[0] == 0 )
777  ps.initialize( _particles[a], a );
778  ps.step( _particles[a], a );
779  }
780 
781  // Finalize charge
782  scharge_finalize_step_pic( scharge );
783 
784  t.stop();
785  ibsimu.message( 1 ) << "time used = " << t << "\n";
786  ibsimu.dec_indent();
787  }
788 
789 
790  void save( std::ostream &os ) const {
791 
792  ParticleDataBaseImp::save( os );
793 
794  write_int32( os, _particles.size() );
795  for( uint32_t a = 0; a < _particles.size(); a++ )
796  _particles[a]->save( os );
797  }
798 
799 
800  void debug_print( std::ostream &os ) const {
801  ParticleDataBaseImp::debug_print( os );
802 
803  for( uint32_t a = 0; a < _particles.size(); a++ ) {
804  os << "Particle " << a << ":\n";
805  _particles[a]->debug_print( os );
806  }
807  }
808 
809 };
810 
811 
816 class ParticleDataBase2DImp : public ParticleDataBasePPImp<ParticleP2D> {
817 
818  void add_tdens_from_segment( MeshScalarField &tdens, double IQ,
819  ParticleP2D &x1, ParticleP2D &x2 ) const;
820 
821 public:
822 
823  ParticleDataBase2DImp( ParticleDataBase *pdb, const Geometry &geom );
824 
826 
827  ParticleDataBase2DImp( ParticleDataBase *pdb, std::istream &s, const Geometry &geom );
828 
829  virtual ~ParticleDataBase2DImp();
830 
831  const ParticleDataBase2DImp &operator=( const ParticleDataBase2DImp &pdb );
832 
833  virtual void build_trajectory_density_field( MeshScalarField &tdens ) const;
834 
835  void add_2d_beam_with_velocity( uint32_t N, double J, double q, double m,
836  double v, double dvp, double dvt,
837  double x1, double y1, double x2, double y2 );
838 
839  void add_2d_beam_with_energy( uint32_t N, double J, double q, double m,
840  double E, double Tp, double Tt,
841  double x1, double y1, double x2, double y2 );
842 
843  void add_2d_KV_beam_with_emittance( uint32_t N, double I, double q, double m,
844  double a, double b, double e,
845  double Ex, double x0, double y0 );
846 
847  void add_2d_gaussian_beam_with_emittance( uint32_t N, double I, double q, double m,
848  double a, double b, double e,
849  double Ex, double x0, double y0 );
850 
851  void save( std::ostream &os ) const;
852 
853  void debug_print( std::ostream &os ) const;
854 };
855 
856 
857 
862 class ParticleDataBaseCylImp : public ParticleDataBasePPImp<ParticlePCyl> {
863 
864  void add_tdens_from_segment( MeshScalarField &tdens, double IQ,
865  ParticlePCyl &x1, ParticlePCyl &x2 ) const;
866 
867  static uint32_t bisect_cumulative_array( const std::vector<double> &cum, double x );
868 
869 public:
870 
871  ParticleDataBaseCylImp( ParticleDataBase *pdb, const Geometry &geom );
872 
874 
875  ParticleDataBaseCylImp( ParticleDataBase *pdb, std::istream &s, const Geometry &geom );
876 
877  virtual ~ParticleDataBaseCylImp();
878 
879  const ParticleDataBaseCylImp &operator=( const ParticleDataBaseCylImp &pdb );
880 
881  virtual void build_trajectory_density_field( MeshScalarField &tdens ) const;
882 
883  void add_2d_beam_with_total_energy( uint32_t N, double J, double q, double m,
884  double Etot, const ScalarField &epot,
885  double Tp, double Tt,
886  double x1, double y1, double x2, double y2 );
887 
888  void add_2d_beam_with_energy( uint32_t N, double J, double q, double m,
889  double E, double Tp, double Tt,
890  double x1, double y1, double x2, double y2 );
891 
892  void add_2d_beam_with_velocity( uint32_t N, double J, double q, double m,
893  double v, double dvp, double dvt,
894  double x1, double y1, double x2, double y2 );
895 
896  void add_2d_full_gaussian_beam( uint32_t N, double I, double q, double m,
897  double Ex, double Tp, double Tt,
898  double x0, double dr );
899 
900  void add_2d_gaussian_beam_with_emittance( uint32_t N, double I, double q, double m,
901  double a, double b, double e,
902  double Ex, double x0 );
903 
904  void export_path_manager_data( const std::string &filename,
905  double ref_E, double ref_q, double ref_m,
906  double val, uint32_t Np ) const;
907 
908  void save( std::ostream &os ) const;
909 
910  void debug_print( std::ostream &os ) const;
911 };
912 
913 
918 class ParticleDataBase3DImp : public ParticleDataBasePPImp<ParticleP3D> {
919 
920  void add_tdens_from_segment( MeshScalarField &tdens, double IQ,
921  ParticleP3D &x1, ParticleP3D &x2 ) const;
922 
923  bool free_plane_mirror_enabled( uint32_t axism ) const;
924  ParticleP3D free_plane_mirror( const ParticleP3D &p, uint32_t axism ) const;
925 public:
926 
927  ParticleDataBase3DImp( ParticleDataBase *pdb, const Geometry &geom );
928 
930 
931  ParticleDataBase3DImp( ParticleDataBase *pdb, std::istream &s, const Geometry &geom );
932 
933  virtual ~ParticleDataBase3DImp();
934 
935  const ParticleDataBase3DImp &operator=( const ParticleDataBase3DImp &pdb );
936 
937  virtual void build_trajectory_density_field( MeshScalarField &tdens ) const;
938 
939  void add_cylindrical_beam_with_total_energy( uint32_t N, double J, double q, double m,
940  double Etot, const ScalarField &epot,
941  double Tp, double Tt, Vec3D c,
942  Vec3D dir1, Vec3D dir2, double r );
943 
944  void add_cylindrical_beam_with_energy( uint32_t N, double J, double q, double m,
945  double E, double Tp, double Tt, Vec3D c,
946  Vec3D dir1, Vec3D dir2, double r );
947 
948  void add_cylindrical_beam_with_velocity( uint32_t N, double J, double q, double m,
949  double v, double dvp, double dvt, Vec3D c,
950  Vec3D dir1, Vec3D dir2, double r );
951 
952  void add_rectangular_beam_with_energy( uint32_t N, double J, double q, double m,
953  double E, double Tp, double Tt, Vec3D c,
954  Vec3D dir1, Vec3D dir2, double size1, double size2 );
955 
956  void add_rectangular_beam_with_velocity( uint32_t N, double J, double q, double m,
957  double v, double dvp, double dvt, Vec3D c,
958  Vec3D dir1, Vec3D dir2, double size1, double size2 );
959 
960  void add_3d_KV_beam_with_emittance( uint32_t N, double I, double q, double m,
961  double E0,
962  double a1, double b1, double e1,
963  double a2, double b2, double e2,
964  Vec3D c, Vec3D dir1, Vec3D dir2 );
965 
966  void add_3d_waterbag_beam_with_emittance( uint32_t N, double I, double q, double m,
967  double E0,
968  double a1, double b1, double e1,
969  double a2, double b2, double e2,
970  Vec3D c, Vec3D dir1, Vec3D dir2 );
971 
972  void add_3d_gaussian_beam_with_emittance( uint32_t N, double I, double q, double m,
973  double E0,
974  double a1, double b1, double e1,
975  double a2, double b2, double e2,
976  Vec3D c, Vec3D dir1, Vec3D dir2 );
977 
978  void trajectories_at_free_plane( TrajectoryDiagnosticData &tdata,
979  Vec3D c, Vec3D o, Vec3D p,
980  const std::vector<trajectory_diagnostic_e> &diagnostics ) const;
981 
982  void export_path_manager_data( const std::string &filename,
983  double ref_E, double ref_q, double ref_m,
984  Vec3D c, Vec3D o, Vec3D p ) const;
985 
986  void save( std::ostream &os ) const;
987 
988  void debug_print( std::ostream &os ) const;
989 };
990 
991 
992 #endif
993 
Definition: callback.hpp:61
Error class for memory allocation errors.
Definition: error.hpp:196
Error class for index range checking errors.
Definition: error.hpp:283
Error class to use if requested feature is unimplemented.
Definition: error.hpp:229
Basic error class.
Definition: error.hpp:153
Geometry defining class.
Definition: geometry.hpp:180
uint32_t number_of_boundaries() const
Return number of boundaries.
Definition: geometry.cpp:287
uint32_t get_thread_count(void)
Get the number of threads used for calculation.
Definition: ibsimu.hpp:203
void dec_indent(void)
Decrease message indentation.
Definition: ibsimu.cpp:143
bool output_is_cout()
Return if message output file is stdout.
Definition: ibsimu.cpp:184
std::ostream & message(message_type_e type, int32_t level)
Print message output.
Definition: ibsimu.cpp:111
void inc_indent(void)
Increase message indentation.
Definition: ibsimu.cpp:136
Scalar field class.
Definition: meshscalarfield.hpp:70
void clear()
Clears the field.
Definition: meshscalarfield.cpp:121
geom_mode_e geom_mode(void) const
Returns geometry mode.
Definition: mesh.hpp:108
double q() const
Return particle charge (q) [C].
Definition: particles.hpp:710
double m() const
Return particle mass (m) [kg].
Definition: particles.hpp:714
double IQ() const
Return current or charge carried by trajectory or particle cloud [A/C].
Definition: particles.hpp:706
ParticleDataBase2D implementation.
Definition: particledatabaseimp.hpp:816
ParticleDataBase3D implementation.
Definition: particledatabaseimp.hpp:918
ParticleDataBaseCyl implementation.
Definition: particledatabaseimp.hpp:862
Definition: particledatabaseimp.hpp:57
double _epsrel
Relative error limit for calculation.
Definition: particledatabaseimp.hpp:63
bool _save_points
Save all points?
Definition: particledatabaseimp.hpp:68
scharge_deposition_e _scharge_dep
Space charge deposition type.
Definition: particledatabaseimp.hpp:65
bool _surface_collision
Surface collision model.
Definition: particledatabaseimp.hpp:79
uint32_t _trajdiv
Divisor for saved trajectories, if 3, every third trajectory is saved.
Definition: particledatabaseimp.hpp:69
ParticleStatistics _stat
Particle statistics.
Definition: particledatabaseimp.hpp:75
uint32_t _iteration
Iteration number.
Definition: particledatabaseimp.hpp:77
bool _mirror[6]
Boundary particle mirroring.
Definition: particledatabaseimp.hpp:71
static double energy_to_velocity(double E, double m)
Convert energy to velocity.
Definition: particledatabaseimp.cpp:125
trajectory_interpolation_e _intrp
Trajectory interpolation type.
Definition: particledatabaseimp.hpp:64
double _rhosum
Sum of space charge density in defined beams (C/m3).
Definition: particledatabaseimp.hpp:73
ParticleDataBase * _pdb
Particle database pointer.
Definition: particledatabaseimp.hpp:85
const CallbackFunctorD_V * _bsup_cb
Location dependent magnetic field suppression.
Definition: particledatabaseimp.hpp:81
double _maxt
Maximum particle time in simulation.
Definition: particledatabaseimp.hpp:67
TrajectoryHandlerCallback * _thand_cb
Trajectory handler callback.
Definition: particledatabaseimp.hpp:82
TrajectorySurfaceCollisionCallback * _tsur_cb
Trajectory surface collision callback.
Definition: particledatabaseimp.hpp:84
bool _relativistic
Relativistic particle iteration.
Definition: particledatabaseimp.hpp:78
double _epsabs
Absolute error limit for calculation.
Definition: particledatabaseimp.hpp:62
uint32_t _maxsteps
Maximum number of steps to calculate.
Definition: particledatabaseimp.hpp:66
TrajectoryEndCallback * _tend_cb
Trajectory collision callback.
Definition: particledatabaseimp.hpp:83
Definition: particledatabaseimp.hpp:194
std::vector< Particle< PP > * > _particles
Particles.
Definition: particledatabaseimp.hpp:291
ParticleDataBasePPImp(ParticleDataBase *pdb, std::istream &s, const Geometry &geom)
Constructor from stream, using API pdb.
Definition: particledatabaseimp.hpp:304
ParticleDataBasePPImp(const ParticleDataBasePPImp &pdb)
Copy constructor.
Definition: particledatabaseimp.hpp:318
ParticleDataBasePPImp(ParticleDataBase *pdb, const Geometry &geom)
Constructor, using API pdb.
Definition: particledatabaseimp.hpp:296
Scheduler< ParticleIterator< PP >, Particle< PP >, Error > _scheduler
Scheduler for solver.
Definition: particledatabaseimp.hpp:292
const ParticleDataBasePPImp & operator=(const ParticleDataBasePPImp &pdb)
Copy assignment operator.
Definition: particledatabaseimp.hpp:328
Particle database base class.
Definition: particledatabase.hpp:191
Particle iterator class for continuous Vlasov-type iteration.
Definition: particleiterator.hpp:280
Particle point class for 2D.
Definition: particles.hpp:103
Particle point class for 3D.
Definition: particles.hpp:459
Particle point class for cylindrical coordinates.
Definition: particles.hpp:275
Particle iteration statistics.
Definition: particlestatistics.hpp:57
Definition: particlestepper.hpp:56
Particle class in some geometry.
Definition: particles.hpp:740
Scalar field.
Definition: scalarfield.hpp:55
Scheduler class for implementing consumer-producer threading.
Definition: scheduler.hpp:87
size_t get_errors(Cont1 &e, Cont2 &pi)
Fetch errors and indices of corresponding problems.
Definition: scheduler.hpp:447
void unlock_mutex(void)
Unlock mutex.
Definition: scheduler.hpp:502
uint32_t get_problem_count(void)
Return number of problems.
Definition: scheduler.hpp:430
uint32_t get_solved_count(void)
Return number of solved problems.
Definition: scheduler.hpp:420
bool is_error(void)
Return true on errors.
Definition: scheduler.hpp:404
bool finish(void)
Wait for all problems to be solved.
Definition: scheduler.hpp:556
void lock_mutex(void)
Lock mutex for adding problems.
Definition: scheduler.hpp:494
void run(std::vector< Solv * > solv)
Run threads with N solvers.
Definition: scheduler.hpp:467
bool wait_finish(void)
Call for solvers to finish when problems are solved.
Definition: scheduler.hpp:528
A tool for printing running status on command line.
Definition: statusprint.hpp:53
void print(const std::string &str, bool force=false)
Print str to output.
Definition: statusprint.cpp:66
Class for measuring code runtime in cpu time and realtime.
Definition: timer.hpp:54
void stop(void)
Stop timer.
Definition: timer.cpp:61
Class for trajectory diagnostic data.
Definition: trajectorydiagnostics.hpp:129
void add_data(size_t i, double x)
Add data point to i:th diagnostic column.
Definition: trajectorydiagnostics.hpp:221
void clear()
Clear all data and diagnostic types.
Definition: trajectorydiagnostics.hpp:155
size_t traj_size() const
Return number of trajectories in data.
Definition: trajectorydiagnostics.hpp:173
trajectory_diagnostic_e diagnostic(size_t i) const
Return i:th diagnostic type.
Definition: trajectorydiagnostics.hpp:181
void add_data_column(trajectory_diagnostic_e diag)
Add data column with type diag.
Definition: trajectorydiagnostics.hpp:161
size_t diag_size() const
Return number of data columns.
Definition: trajectorydiagnostics.hpp:167
Trajectory end callback.
Definition: particledatabase.hpp:71
Trajectory handler callback.
Definition: particledatabase.hpp:58
Trajectory surface collision callback.
Definition: particledatabase.hpp:86
Three dimensional vector.
Definition: vec3d.hpp:58
Vector field.
Definition: vectorfield.hpp:56
#define ERROR_LOCATION
Macro for setting error location when throwing errors.
Definition: error.hpp:83
void write_int32(std::ostream &s, int32_t value)
Write int32_t value into stream os.
Definition: file.cpp:70
int32_t read_int32(std::istream &s)
Read int32_t from stream is.
Definition: file.cpp:135
Bindary file writing and reading tools.
IBSimu ibsimu
Global instance of class IBSimu.
Definition: ibsimu.cpp:289
Ion Beam Simulator global settings.
double norm2(const Vector &vec)
Definition: mvector.cpp:474
Particle iterator
Particle and particle point objects
Particle stepper using Boris leap-frog
void scharge_finalize_pic(MeshScalarField &scharge)
Finalize space charge calculation.
Definition: scharge.cpp:64
Subroutine for printing running status line on command line.
Timer for cputime and realtime
Trajectory diagnostics.
const char * coordinate_axis_string[]
String describing axis names without unit.
Definition: types.cpp:46
trajectory_interpolation_e
Trajectory interpolation type.
Definition: types.hpp:153
coordinate_axis_e
Coordinate axis identifier.
Definition: types.hpp:170
@ AXIS_R
R axis.
Definition: types.hpp:173
@ AXIS_X
X axis.
Definition: types.hpp:171
@ AXIS_Y
Y axis.
Definition: types.hpp:172
@ AXIS_Z
Z axis.
Definition: types.hpp:174
geom_mode_e
Geometry mode enum.
Definition: types.hpp:59
@ MODE_3D
3D geometry
Definition: types.hpp:63
@ MODE_1D
1D geometry
Definition: types.hpp:60
@ MODE_CYL
Cylindrically symmetric geometry.
Definition: types.hpp:62
@ MODE_2D
2D geometry
Definition: types.hpp:61
scharge_deposition_e
Space charge depostition type.
Definition: types.hpp:161
@ SCHARGE_DEPOSITION_LINEAR
Deposition to nodes as a linear function of distance to closet trajectory segment.
Definition: types.hpp:163
@ DIAG_R
Radial position (m)
Definition: types.hpp:202
@ DIAG_Y
Y-axis position (m)
Definition: types.hpp:201
@ DIAG_OP
, where direction q is normal to diagnostic plane (rad)
Definition: types.hpp:220
@ DIAG_O
O-axis position (m)
Definition: types.hpp:209
@ DIAG_VQ
Q-axis velocity (m/s)
Definition: types.hpp:214
@ DIAG_CHARGE
Particle charge (e)
Definition: types.hpp:225
@ DIAG_NONE
Dummy diagnostic. Does nothing.
Definition: types.hpp:197
@ DIAG_XP
, where direction q is normal to diagnostic plane (rad)
Definition: types.hpp:215
@ DIAG_VO
O-axis velocity (m/s)
Definition: types.hpp:210
@ DIAG_VZ
Z-axis velocity (m/s)
Definition: types.hpp:208
@ DIAG_VR
Radial velocity (m/s)
Definition: types.hpp:204
@ DIAG_EK
Kinetic energy (eV)
Definition: types.hpp:223
@ DIAG_P
P-axis position (m)
Definition: types.hpp:211
@ DIAG_MASS
Particle mass (u)
Definition: types.hpp:226
@ DIAG_PP
, where direction q is normal to diagnostic plane (rad)
Definition: types.hpp:221
@ DIAG_Z
Z-axis position (m)
Definition: types.hpp:207
@ DIAG_X
X-axis position (m)
Definition: types.hpp:199
@ DIAG_VTHETA
Tangential velocity (m/s)
Definition: types.hpp:206
@ DIAG_CURR
Current (I)
Definition: types.hpp:222
@ DIAG_VY
Y-axis velocity (m/s)
Definition: types.hpp:203
@ DIAG_W
Angular velocity (rad/s)
Definition: types.hpp:205
@ DIAG_YP
, where direction q is normal to diagnostic plane (rad)
Definition: types.hpp:216
@ DIAG_Q
Q-axis position (m)
Definition: types.hpp:213
@ DIAG_NO
Particle index number. Useful for debugging.
Definition: types.hpp:227
@ DIAG_ZP
, where direction q is normal to diagnostic plane (rad)
Definition: types.hpp:219
@ DIAG_RP
, where direction q is normal to diagnostic plane (rad)
Definition: types.hpp:217
@ DIAG_T
Time (s)
Definition: types.hpp:198
@ DIAG_AP
, where direction q is normal to diagnostic plane (rad)
Definition: types.hpp:218
@ DIAG_VP
P-axis velocity (m/s)
Definition: types.hpp:212
@ DIAG_VX
X-axis velocity (m/s)
Definition: types.hpp:200
@ DIAG_QM
Charge per mass (e/u)
Definition: types.hpp:224


Reference manual for Ion Beam Simulator 1.0.6dev
Generated by Doxygen 1.9.1 on Thu Sep 11 2025 09:37:24.