particles.hpp
Go to the documentation of this file.
00001 00005 /* Copyright (c) 2005-2011 Taneli Kalvas. All rights reserved. 00006 * 00007 * You can redistribute this software and/or modify it under the terms 00008 * of the GNU General Public License as published by the Free Software 00009 * Foundation; either version 2 of the License, or (at your option) 00010 * any later version. 00011 * 00012 * This library is distributed in the hope that it will be useful, but 00013 * WITHOUT ANY WARRANTY; without even the implied warranty of 00014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00015 * General Public License for more details. 00016 * 00017 * You should have received a copy of the GNU General Public License 00018 * along with this library (file "COPYING" included in the package); 00019 * if not, write to the Free Software Foundation, Inc., 51 Franklin 00020 * Street, Fifth Floor, Boston, MA 02110-1301 USA 00021 * 00022 * If you have questions about your rights to use or distribute this 00023 * software, please contact Berkeley Lab's Technology Transfer 00024 * Department at TTD@lbl.gov. Other questions, comments and bug 00025 * reports should be sent directly to the author via email at 00026 * taneli.kalvas@jyu.fi. 00027 * 00028 * NOTICE. This software was developed under partial funding from the 00029 * U.S. Department of Energy. As such, the U.S. Government has been 00030 * granted for itself and others acting on its behalf a paid-up, 00031 * nonexclusive, irrevocable, worldwide license in the Software to 00032 * reproduce, prepare derivative works, and perform publicly and 00033 * display publicly. Beginning five (5) years after the date 00034 * permission to assert copyright is obtained from the U.S. Department 00035 * of Energy, and subject to any subsequent five (5) year renewals, 00036 * the U.S. Government is granted for itself and others acting on its 00037 * behalf a paid-up, nonexclusive, irrevocable, worldwide license in 00038 * the Software to reproduce, prepare derivative works, distribute 00039 * copies to the public, perform publicly and display publicly, and to 00040 * permit others to do so. 00041 */ 00042 00043 #ifndef PARTICLES_HPP 00044 #define PARTICLES_HPP 1 00045 00046 00047 #include <vector> 00048 #include <string> 00049 #include <gsl/gsl_errno.h> 00050 #include "geometry.hpp" 00051 #include "scalarfield.hpp" 00052 #include "vectorfield.hpp" 00053 #include "vec3d.hpp" 00054 #include "callback.hpp" 00055 00056 00057 /* Integer error value that is supposed to differ from internal GSL 00058 * error values */ 00059 #define IBSIMU_DERIV_ERROR 201 00060 00061 00069 enum particle_status_e { 00070 PARTICLE_OK = 0, 00071 PARTICLE_OUT, 00072 PARTICLE_COLL, 00073 PARTICLE_BADDEF, 00074 PARTICLE_TIME, 00075 PARTICLE_NSTP 00076 }; 00077 00078 00079 00080 /* ************************************************************************************* * 00081 * Particle point classes * 00082 * ************************************************************************************* */ 00083 00084 00089 class ParticlePBase 00090 { 00091 00092 }; 00093 00094 00100 class ParticleP2D : public ParticlePBase 00101 { 00102 double _x[5]; 00104 public: 00105 00108 ParticleP2D() {} 00109 00112 ParticleP2D( double t, double x, double vx, double y, double vy ) { 00113 _x[0] = t; _x[1] = x; _x[2] = vx; _x[3] = y; _x[4] = vy; 00114 } 00115 00118 ParticleP2D( std::istream &s ) { 00119 _x[0] = read_double( s ); 00120 _x[1] = read_double( s ); 00121 _x[2] = read_double( s ); 00122 _x[3] = read_double( s ); 00123 _x[4] = read_double( s ); 00124 } 00125 00128 static geom_mode_e geom_mode() { return(MODE_2D); } 00129 00132 static size_t dim() { return(2); } 00133 00136 static size_t size() { return(5); } 00137 00149 static int get_derivatives( double t, const double *x, double *dxdt, void *data ); 00150 00155 static int trajectory_intersections_at_plane( std::vector<ParticleP2D> &intsc, 00156 int crd, double val, 00157 const ParticleP2D &x1, 00158 const ParticleP2D &x2, 00159 int extrapolate = 0 ); 00160 00165 static const std::string IQ_unit() { return( "A/m" ); } 00166 00169 Vec3D location() const { return( Vec3D( _x[1], _x[3], 0.0 ) ); } 00170 00173 Vec3D velocity() const { return( Vec3D( _x[2], _x[4], 0.0 ) ); } 00174 00177 double speed() { return( sqrt(_x[2]*_x[2] + _x[4]*_x[4]) ); } 00178 00181 double &operator[]( int i ) { return( _x[i] ); } 00182 00185 const double &operator[]( int i ) const { return( _x[i] ); } 00186 00189 double &operator()( int i ) { return( _x[i] ); } 00190 00193 const double &operator()( int i ) const { return( _x[i] ); } 00194 00195 ParticleP2D operator+( const ParticleP2D &pp ) const { 00196 ParticleP2D res; 00197 res[0] = _x[0] + pp[0]; 00198 res[1] = _x[1] + pp[1]; 00199 res[2] = _x[2] + pp[2]; 00200 res[3] = _x[3] + pp[3]; 00201 res[4] = _x[4] + pp[4]; 00202 return( res ); 00203 } 00204 00205 ParticleP2D operator-( const ParticleP2D &pp ) const { 00206 ParticleP2D res; 00207 res[0] = _x[0] - pp[0]; 00208 res[1] = _x[1] - pp[1]; 00209 res[2] = _x[2] - pp[2]; 00210 res[3] = _x[3] - pp[3]; 00211 res[4] = _x[4] - pp[4]; 00212 return( res ); 00213 } 00214 00215 ParticleP2D operator*( double x ) const { 00216 ParticleP2D res; 00217 res[0] = _x[0]*x; 00218 res[1] = _x[1]*x; 00219 res[2] = _x[2]*x; 00220 res[3] = _x[3]*x; 00221 res[4] = _x[4]*x; 00222 return( res ); 00223 } 00224 00227 void save( std::ostream &s ) const { 00228 write_double( s, _x[0] ); 00229 write_double( s, _x[1] ); 00230 write_double( s, _x[2] ); 00231 write_double( s, _x[3] ); 00232 write_double( s, _x[4] ); 00233 } 00234 00235 friend ParticleP2D operator*( double x, const ParticleP2D &pp ); 00236 }; 00237 00238 00239 inline std::ostream &operator<<( std::ostream &os, const ParticleP2D &pp ) 00240 { 00241 os << "(" 00242 << std::setw(12) << pp(0) << ", " 00243 << std::setw(12) << pp(1) << ", " 00244 << std::setw(12) << pp(2) << ", " 00245 << std::setw(12) << pp(3) << ", " 00246 << std::setw(12) << pp(4) << ")"; 00247 return( os ); 00248 } 00249 00250 00251 inline ParticleP2D operator*( double x, const ParticleP2D &pp ) 00252 { 00253 ParticleP2D res; 00254 res[0] = pp[0]*x; 00255 res[1] = pp[1]*x; 00256 res[2] = pp[2]*x; 00257 res[3] = pp[3]*x; 00258 res[4] = pp[4]*x; 00259 return( res ); 00260 } 00261 00262 00268 class ParticlePCyl : public ParticlePBase 00269 { 00270 double _x[6]; 00272 public: 00273 00276 ParticlePCyl() {} 00277 00280 ParticlePCyl( double t, double x, double vx, double r, double vr, double w ) { 00281 _x[0] = t; _x[1] = x; _x[2] = vx; _x[3] = r; _x[4] = vr; _x[5] = w; 00282 } 00283 00286 ParticlePCyl( std::istream &s ) { 00287 _x[0] = read_double( s ); 00288 _x[1] = read_double( s ); 00289 _x[2] = read_double( s ); 00290 _x[3] = read_double( s ); 00291 _x[4] = read_double( s ); 00292 _x[5] = read_double( s ); 00293 } 00294 00297 static geom_mode_e geom_mode() { return(MODE_CYL); } 00298 00301 static size_t dim() { return(2); } 00302 00305 static size_t size() { return(6); } 00306 00323 static int get_derivatives( double t, const double *x, double *dxdt, void *data ); 00324 00329 static int trajectory_intersections_at_plane( std::vector<ParticlePCyl> &intsc, 00330 int crd, double val, 00331 const ParticlePCyl &x1, 00332 const ParticlePCyl &x2, 00333 int extrapolate = 0 ); 00334 00339 static const std::string IQ_unit() { return( "A" ); } 00340 00343 Vec3D location() const { return( Vec3D( _x[1], _x[3], 0.0 ) ); } 00344 00347 Vec3D velocity() const { return( Vec3D( _x[2], _x[4], _x[5]*_x[3] ) ); } 00348 00351 double speed() { return( sqrt(_x[2]*_x[2] + _x[4]*_x[4] + _x[3]*_x[3]*_x[5]*_x[5]) ); } 00352 00355 double &operator[]( int i ) { return( _x[i] ); } 00356 00359 const double &operator[]( int i ) const { return( _x[i] ); } 00360 00363 double &operator()( int i ) { return( _x[i] ); } 00364 00367 const double &operator()( int i ) const { return( _x[i] ); } 00368 00369 ParticlePCyl operator+( const ParticlePCyl &pp ) const { 00370 ParticlePCyl res; 00371 res[0] = _x[0] + pp[0]; 00372 res[1] = _x[1] + pp[1]; 00373 res[2] = _x[2] + pp[2]; 00374 res[3] = _x[3] + pp[3]; 00375 res[4] = _x[4] + pp[4]; 00376 res[5] = _x[5] + pp[5]; 00377 return( res ); 00378 } 00379 00380 ParticlePCyl operator-( const ParticlePCyl &pp ) const { 00381 ParticlePCyl res; 00382 res[0] = _x[0] - pp[0]; 00383 res[1] = _x[1] - pp[1]; 00384 res[2] = _x[2] - pp[2]; 00385 res[3] = _x[3] - pp[3]; 00386 res[4] = _x[4] - pp[4]; 00387 res[5] = _x[5] - pp[5]; 00388 return( res ); 00389 } 00390 00391 ParticlePCyl operator*( double x ) const { 00392 ParticlePCyl res; 00393 res[0] = _x[0]*x; 00394 res[1] = _x[1]*x; 00395 res[2] = _x[2]*x; 00396 res[3] = _x[3]*x; 00397 res[4] = _x[4]*x; 00398 res[5] = _x[5]*x; 00399 return( res ); 00400 } 00401 00404 void save( std::ostream &s ) const { 00405 write_double( s, _x[0] ); 00406 write_double( s, _x[1] ); 00407 write_double( s, _x[2] ); 00408 write_double( s, _x[3] ); 00409 write_double( s, _x[4] ); 00410 write_double( s, _x[5] ); 00411 } 00412 00413 friend ParticlePCyl operator*( double x, const ParticlePCyl &pp ); 00414 }; 00415 00416 00417 inline std::ostream &operator<<( std::ostream &os, const ParticlePCyl &pp ) 00418 { 00419 os << "(" 00420 << std::setw(12) << pp(0) << ", " 00421 << std::setw(12) << pp(1) << ", " 00422 << std::setw(12) << pp(2) << ", " 00423 << std::setw(12) << pp(3) << ", " 00424 << std::setw(12) << pp(4) << ", " 00425 << std::setw(12) << pp(5) << ")"; 00426 return( os ); 00427 } 00428 00429 00430 inline ParticlePCyl operator*( double x, const ParticlePCyl &pp ) 00431 { 00432 ParticlePCyl res; 00433 res[0] = pp[0]*x; 00434 res[1] = pp[1]*x; 00435 res[2] = pp[2]*x; 00436 res[3] = pp[3]*x; 00437 res[4] = pp[4]*x; 00438 res[5] = pp[5]*x; 00439 return( res ); 00440 } 00441 00442 00448 class ParticleP3D : public ParticlePBase 00449 { 00450 double _x[7]; 00452 public: 00453 00456 ParticleP3D() {} 00457 00460 ParticleP3D( double t, double x, double vx, double y, double vy, double z, double vz ) { 00461 _x[0] = t; _x[1] = x; _x[2] = vx; _x[3] = y; _x[4] = vy; _x[5] = z; _x[6] = vz; 00462 } 00463 00466 ParticleP3D( std::istream &s ) { 00467 _x[0] = read_double( s ); 00468 _x[1] = read_double( s ); 00469 _x[2] = read_double( s ); 00470 _x[3] = read_double( s ); 00471 _x[4] = read_double( s ); 00472 _x[5] = read_double( s ); 00473 _x[6] = read_double( s ); 00474 } 00475 00478 static geom_mode_e geom_mode() { return(MODE_3D); } 00479 00482 static size_t dim() { return(3); } 00483 00486 static size_t size() { return(7); } 00487 00501 static int get_derivatives( double t, const double *x, double *dxdt, void *data ); 00502 00507 static int trajectory_intersections_at_plane( std::vector<ParticleP3D> &intsc, 00508 int crd, double val, 00509 const ParticleP3D &x1, 00510 const ParticleP3D &x2, 00511 int extrapolate = 0 ); 00512 00517 static const std::string IQ_unit() { return( "A" ); } 00518 00521 Vec3D location() const { return( Vec3D( _x[1], _x[3], _x[5] ) ); } 00522 00525 Vec3D velocity() const { return( Vec3D( _x[2], _x[4], _x[6] ) ); } 00526 00529 double speed() { return( sqrt(_x[2]*_x[2] + _x[4]*_x[4] + _x[6]*_x[6]) ); } 00530 00533 double &operator[]( int i ) { return( _x[i] ); } 00534 00537 const double &operator[]( int i ) const { return( _x[i] ); } 00538 00541 double &operator()( int i ) { return( _x[i] ); } 00542 00545 const double &operator()( int i ) const { return( _x[i] ); } 00546 00547 ParticleP3D operator+( const ParticleP3D &pp ) const { 00548 ParticleP3D res; 00549 res[0] = _x[0] + pp[0]; 00550 res[1] = _x[1] + pp[1]; 00551 res[2] = _x[2] + pp[2]; 00552 res[3] = _x[3] + pp[3]; 00553 res[4] = _x[4] + pp[4]; 00554 res[5] = _x[5] + pp[5]; 00555 res[6] = _x[6] + pp[6]; 00556 return( res ); 00557 } 00558 00559 ParticleP3D operator-( const ParticleP3D &pp ) const { 00560 ParticleP3D res; 00561 res[0] = _x[0] - pp[0]; 00562 res[1] = _x[1] - pp[1]; 00563 res[2] = _x[2] - pp[2]; 00564 res[3] = _x[3] - pp[3]; 00565 res[4] = _x[4] - pp[4]; 00566 res[5] = _x[5] - pp[5]; 00567 res[6] = _x[6] - pp[6]; 00568 return( res ); 00569 } 00570 00571 ParticleP3D operator*( double x ) const { 00572 ParticleP3D res; 00573 res[0] = _x[0]*x; 00574 res[1] = _x[1]*x; 00575 res[2] = _x[2]*x; 00576 res[3] = _x[3]*x; 00577 res[4] = _x[4]*x; 00578 res[5] = _x[5]*x; 00579 res[6] = _x[6]*x; 00580 return( res ); 00581 } 00582 00585 void save( std::ostream &s ) const { 00586 write_double( s, _x[0] ); 00587 write_double( s, _x[1] ); 00588 write_double( s, _x[2] ); 00589 write_double( s, _x[3] ); 00590 write_double( s, _x[4] ); 00591 write_double( s, _x[5] ); 00592 write_double( s, _x[6] ); 00593 } 00594 00595 friend ParticleP3D operator*( double x, const ParticleP3D &pp ); 00596 }; 00597 00598 00599 inline std::ostream &operator<<( std::ostream &os, const ParticleP3D &pp ) 00600 { 00601 os << "(" 00602 << std::setw(12) << pp(0) << ", " 00603 << std::setw(12) << pp(1) << ", " 00604 << std::setw(12) << pp(2) << ", " 00605 << std::setw(12) << pp(3) << ", " 00606 << std::setw(12) << pp(4) << ", " 00607 << std::setw(12) << pp(5) << ", " 00608 << std::setw(12) << pp(6) << ")"; 00609 return( os ); 00610 } 00611 00612 00613 inline ParticleP3D operator*( double x, const ParticleP3D &pp ) 00614 { 00615 ParticleP3D res; 00616 res[0] = pp[0]*x; 00617 res[1] = pp[1]*x; 00618 res[2] = pp[2]*x; 00619 res[3] = pp[3]*x; 00620 res[4] = pp[4]*x; 00621 res[5] = pp[5]*x; 00622 res[6] = pp[6]*x; 00623 return( res ); 00624 } 00625 00626 00627 00628 00629 /* ************************************************************************************** * 00630 * Particle classes * 00631 * ************************************************************************************** */ 00632 00633 00638 class ParticleBase 00639 { 00640 protected: 00641 00642 particle_status_e _status; 00643 double _IQ; 00654 double _q; 00655 double _m; 00657 ParticleBase( double IQ, double q, double m ) 00658 : _status(PARTICLE_OK), _q(q) { 00659 _m = fabs(m); 00660 if( _q < 0 ) 00661 _IQ = -fabs(IQ); 00662 else 00663 _IQ = fabs(IQ); 00664 } 00665 00668 ParticleBase( std::istream &s ) { 00669 _status = (particle_status_e)read_int32( s ); 00670 _IQ = read_double( s ); 00671 _q = read_double( s ); 00672 _m = read_double( s ); 00673 } 00674 00675 ~ParticleBase() {} 00676 00677 public: 00678 00681 particle_status_e get_status() { return( _status ); } 00682 00685 void set_status( particle_status_e status ) { _status = status; } 00686 00692 double IQ() const { return( _IQ ); } 00693 00696 double q() const { return( _q ); } 00697 00700 double m() const { return( _m ); } 00701 00704 double qm() const { return( _q/_m ); } 00705 00708 void save( std::ostream &s ) const { 00709 write_int32( s, _status ); 00710 write_double( s, _IQ ); 00711 write_double( s, _q ); 00712 write_double( s, _m ); 00713 } 00714 }; 00715 00716 00725 template<class PP> class Particle : public ParticleBase 00726 { 00727 std::vector<PP> _trajectory; 00728 PP _x; 00730 public: 00731 00740 Particle( double IQ, double q, double m, const PP &x ) 00741 : ParticleBase(IQ,q,m), _x(x) {} 00742 00745 Particle( std::istream &s ) 00746 : ParticleBase( s ) { 00747 00748 uint32_t N = read_int32( s ); 00749 _trajectory.reserve( N ); 00750 for( uint32_t a = 0; a < N; a++ ) 00751 _trajectory.push_back( PP( s ) ); 00752 _x = PP( s ); 00753 } 00754 00757 ~Particle() {} 00758 00761 double &operator()( int i ) { return( _x(i) ); } 00762 00765 const double &operator()( int i ) const { return( _x(i) ); } 00766 00769 double &operator[]( int i ) { return( _x(i) ); } 00770 00773 const double &operator[]( int i ) const { return( _x(i) ); } 00774 00777 Vec3D location() const { return( _x.location() ); } 00778 00781 Vec3D velocity() const { return( _x.velocity() ); } 00782 00785 PP &x() { return( _x ); } 00786 00789 const PP &x() const { return( _x ); } 00790 00793 PP &traj( int i ) { return( _trajectory[i] ); } 00794 00797 const PP &traj( int i ) const { return( _trajectory[i] ); } 00798 00801 size_t traj_size( void ) const { return( _trajectory.size() ); } 00802 00805 void add_trajectory_point( const PP &x ) { _trajectory.push_back( x ); } 00806 00809 void copy_trajectory( const std::vector<PP> &traj ) { _trajectory = traj; } 00810 00813 void clear_trajectory( void ) { _trajectory.clear(); } 00814 00817 void save( std::ostream &s ) const { 00818 ParticleBase::save( s ); 00819 write_int32( s, _trajectory.size() ); 00820 for( uint32_t a = 0; a < _trajectory.size(); a++ ) 00821 _trajectory[a].save( s ); 00822 _x.save( s ); 00823 } 00824 00827 void debug_print( std::ostream &os ) const { 00828 size_t a; 00829 os << "**Particle\n"; 00830 switch( _status ) { 00831 case PARTICLE_OK: 00832 os << "stat = PARTICLE_OK\n"; 00833 break; 00834 case PARTICLE_OUT: 00835 os << "stat = PARTICLE_OUT\n"; 00836 break; 00837 case PARTICLE_COLL: 00838 os << "stat = PARTICLE_COLL\n"; 00839 break; 00840 case PARTICLE_BADDEF: 00841 os << "stat = PARTICLE_BADDEF\n"; 00842 break; 00843 case PARTICLE_TIME: 00844 os << "stat = PARTICLE_TIME\n"; 00845 break; 00846 case PARTICLE_NSTP: 00847 os << "stat = PARTICLE_NSTP\n"; 00848 break; 00849 } 00850 os << "IQ = " << _IQ << "\n"; 00851 os << "q = " << _q << "\n"; 00852 os << "m = " << _m << "\n"; 00853 os << "x = " << _x << "\n"; 00854 os << "Trajectory:\n"; 00855 for( a = 0; a < _trajectory.size(); a++ ) 00856 os << "x[" << a << "] = " << _trajectory[a] << "\n"; 00857 00858 /* 00859 std::cout << "Trajectory:\n"; 00860 for( a = 0; a < _trajectory.size(); a++ ) { 00861 std::cout << "x[" << a << "] = ("; 00862 uint32_t b; 00863 const PP &tp = _trajectory[a]; 00864 if( tp.size() > 0 ) { 00865 for( b = 0; b < tp.size()-1; b++ ) 00866 std::cout << tp[b] << ", "; 00867 std::cout << tp[b] << ")\n"; 00868 } else { 00869 std::cout << ")\n"; 00870 } 00871 } 00872 */ 00873 } 00874 }; 00875 00876 00881 typedef Particle<ParticleP2D> Particle2D; 00882 00883 00888 typedef Particle<ParticlePCyl> ParticleCyl; 00889 00890 00895 typedef Particle<ParticleP3D> Particle3D; 00896 00897 00898 00901 struct ParticleIteratorData { 00902 ScalarField *_scharge; 00903 const VectorField *_efield; 00904 const VectorField *_bfield; 00905 const Geometry *_geom; 00907 double _qm; 00908 const CallbackFunctorD_V *_bsup_cb; 00909 bool _relativistic; 00911 ParticleIteratorData( ScalarField *scharge, const VectorField *efield, 00912 const VectorField *bfield, const Geometry *geom ) 00913 : _scharge(scharge), _efield(efield), _bfield(bfield), 00914 _geom(geom), _qm(0.0), _bsup_cb(0), _relativistic(false) {} 00915 00918 void set_bfield_suppression_callback( const CallbackFunctorD_V *bsup_cb ) { 00919 _bsup_cb = bsup_cb; 00920 } 00921 00924 void set_relativistic( bool enable ) { 00925 _relativistic = enable; 00926 } 00927 00928 }; 00929 00930 00931 00932 #endif 00933