It maintains the trajectory for a reference particle and computes the field for all particles in the bunch related to that reference.
A Bunch is created in PreUserTrackingAction() when tracking a reference particle. The tracks in the bunch are added in beginCollectiveTracking(). The fields from the Bunch are computed in computeField(), which is called by collectiveStep(), and they are then used for tracking via addFieldValue().
The grid for PoissonConvolve3D is always centered at the reference particle, and moves with it between time steps. No solution is possible if any charge is at or very close to the boundary, so the specified percentile of the charge distribution is used to determine the size of the grid, keeping the percentile of the distribution between MINGRID and MAXGRID of the grid size. Any charge located >SUPPRESSGRID of the grid size is suppressed (in x, y, or z).
The challenge is to provide suitably accurate boundary conditions without taking too much CPU. For a perfectly Gaussian bunch that can be done by applying an approximation grid 4 or 8 times smaller than the Poisson3D grid. For a cylindrical bunch that does not work. So for now it is left up to the user to specify the approximation grid size. Unlike the Poisson3D grid, the approximation grid can be any size. An attempt is made to merge cells with tiny charge (<1% of the total) with its neighbor, but this does not always reduce the number of approximation charges very much.
This version requires the reference particle's momentum to be parallel to the z axis.
Public Member Functions | |
Bunch (G4ParticleDefinition *def, int nx, int ny, int nz, double dx, double dy, double dz, double _charge, double _maxBeta, bool _fixedGrid, double _percentile, int nxApprox, int nyApprox, int nzApprox, int _minActive) | |
void | addReferencePoint (const G4Track *track) |
add a point to the reference trajectory. | |
void | addReferencePoint (double t, G4ThreeVector pos, G4ThreeVector mom) |
add a point to the reference trajectory. | |
int | nTrajectoryPoints () |
nTrajectoryPoints() returns the # points in the reference trajectory | |
int | getNParticles () const |
getNParticles() returns # particles in bunch | |
G4ParticleDefinition * | getDefinition () |
getParticleDefinition() | |
bool | addTrack (G4Track *t) |
Add a track to the Bunch. returns false if this track is not part of this bunch. | |
int | size () |
int | getNapprox () |
int | getMinActive () |
G4ThreeVector | getBound () |
bool | getReferencePos4Mom (double time, G4ThreeVector &position, G4LorentzVector &fourMomentum) const |
Interpolate in the point[] vector to get position and 4-momentum of the reference for this bunch. Returns true if OK, false if time is after the valid range for this reference. If time is before the reference was created, its first two trajectory points are linearly extrapolated backwards. Because it must search for the enclosing points of the trajectory, this is most efficient when time does not jump very much (it starts the search at the place in the trajectory of the previous call). (Note: the const is a lie, but is required by BLElementField; only index is modified, which is essentially benign.). | |
bool | init () |
init() initializes the computation, sizing the grid for the initial bunch, and computing the field for the initial time step. Called after all tracks are added to the bunch, before stepping. Returns false if failure. | |
bool | isInBunch (G4Track *track) |
isInBunch() returns true if this track is in the bunch. Tracks are selected by these criteria: same particle as reference within bound_x,bound_y,bound_z of the bunch's reference traj. v/c in the bunch's beam frame less than maxBeta | |
bool | computeField () |
All tracks in the bunch are added into the PoissonConvolve3D and the field is computed. returns false if current step time is beyond the range of the bunch's reference. | |
bool | resizeGrid (bool force=false) |
resizes the grid, based on current tracks. returns true if grid was resized. | |
void | addFieldValue (const G4double point[4], G4double field[6]) const |
addFieldValue adds the field for this bunch to field[]. | |
Static Public Member Functions | |
static void | testEfield () |
testEfield() will test the units and value of the E field in the beam frame for a point charge. | |
static void | testBfield () |
testBfield() will test the B field in the lab frame for a bunch that is a line of moving charges, 1000 Amps. | |
static void | setVerbose (int v) |
setVerbose() sets the debug print level | |
static void | setUseApproximationOnly (int v) |
setUseApproximationOnly() sets it | |
Private Attributes | |
std::vector< Point > | point |
unsigned | index |
double | prevTime |
G4ParticleDefinition * | definition |
double | charge |
double | maxBeta |
double | bound_x |
double | bound_y |
double | bound_z |
int | nParticles |
double | percentile |
int | minActive |
PoissonConvolve3D * | poisson |
bool | goodGuess |
bool | fixedGrid |
Approx | approx |
std::vector< G4Track * > | tracks |
BLRunManager * | runManager |
Static Private Attributes | |
static const double | extrapolateFrac = 0.01 |
static const double | minDeltaT = 1.0e-6*ns |
static int | verbose = 0 |
static int | useApproximationOnly = 0 |
Friends | |
class | Approx |
Classes | |
class | Approx |
class Approx does a 3-d histogram of the charge to generate an approximation for PoissonConvolve3D. Within each bin (voxel) it use the mean position and the total charge. More... | |
struct | Point |
Bunch::Bunch | ( | G4ParticleDefinition * | def, | |
int | nx, | |||
int | ny, | |||
int | nz, | |||
double | dx, | |||
double | dy, | |||
double | dz, | |||
double | _charge, | |||
double | _maxBeta, | |||
bool | _fixedGrid, | |||
double | _percentile, | |||
int | nxApprox, | |||
int | nyApprox, | |||
int | nzApprox, | |||
int | _minActive | |||
) | [inline] |
References approx, bound_x, bound_y, bound_z, charge, definition, fixedGrid, BLRunManager::getObject(), goodGuess, index, maxBeta, minActive, nParticles, percentile, poisson, prevTime, Bunch::Approx::reset(), and runManager.
00144 : 00145 point(), approx(nxApprox,nyApprox,nzApprox), tracks() 00146 { index=0; prevTime=-DBL_MAX; definition=def; 00147 charge=_charge; maxBeta=_maxBeta; fixedGrid=_fixedGrid; 00148 bound_x=dx; bound_y=dy; bound_z=dz; 00149 nParticles=0; percentile=_percentile; minActive=_minActive; 00150 poisson = new PoissonConvolve3D(nx,ny,nz,-dx,dx,-dy,dy,-dz,dz); 00151 goodGuess=false; runManager=BLRunManager::getObject(); 00152 approx.reset(this); 00153 }
void Bunch::addReferencePoint | ( | const G4Track * | track | ) | [inline] |
add a point to the reference trajectory.
References minDeltaT, point, and prevTime.
Referenced by BLCMDspacecharge::UserSteppingAction().
00156 { 00157 double time=track->GetGlobalTime(); 00158 if(time >= prevTime+minDeltaT) { // valid for prevTime=-DBL_MAX 00159 point.push_back(Point(time, track->GetPosition(), 00160 track->GetMomentum())); 00161 prevTime = time; 00162 } 00163 }
void Bunch::addReferencePoint | ( | double | t, | |
G4ThreeVector | pos, | |||
G4ThreeVector | mom | |||
) | [inline] |
int Bunch::nTrajectoryPoints | ( | ) | [inline] |
nTrajectoryPoints() returns the # points in the reference trajectory
References point.
Referenced by BLCMDspacecharge::PostUserTrackingAction().
00170 { return point.size(); }
int Bunch::getNParticles | ( | ) | const [inline] |
G4ParticleDefinition* Bunch::getDefinition | ( | ) | [inline] |
bool Bunch::addTrack | ( | G4Track * | t | ) | [inline] |
Add a track to the Bunch. returns false if this track is not part of this bunch.
References isInBunch(), and tracks.
int Bunch::getNapprox | ( | ) | [inline] |
G4ThreeVector Bunch::getBound | ( | ) | [inline] |
bool Bunch::getReferencePos4Mom | ( | double | time, | |
G4ThreeVector & | position, | |||
G4LorentzVector & | fourMomentum | |||
) | const |
Interpolate in the point[] vector to get position and 4-momentum of the reference for this bunch. Returns true if OK, false if time is after the valid range for this reference. If time is before the reference was created, its first two trajectory points are linearly extrapolated backwards. Because it must search for the enclosing points of the trajectory, this is most efficient when time does not jump very much (it starts the search at the place in the trajectory of the previous call). (Note: the const is a lie, but is required by BLElementField; only index is modified, which is essentially benign.).
References BLAssert, definition, index, minDeltaT, point, and verbose.
Referenced by addFieldValue(), computeField(), init(), isInBunch(), and resizeGrid().
00619 { 00620 // find the current entry in point[] -- return false if beyond the end. 00621 while(time < point[index].time && index > 0) 00622 --((Bunch*)this)->index; // discard const 00623 while(index+1 < point.size()-1 && time > point[index+1].time) { 00624 ++((Bunch*)this)->index; // discard const 00625 } 00626 if(index+1 >= point.size()) return false; 00627 if(!(index+1 < point.size())) 00628 printf("index=%d point.size=%ld time=%.3f last_time=%.3f\n", 00629 index,(long)point.size(),time,point[point.size()-1].time); 00630 BLAssert(index+1 < point.size()); 00631 00632 // Because minDeltaT was imposed while filling point[], we know the 00633 // points are distinct. 00634 double dt = point[index+1].time - point[index].time; 00635 BLAssert(dt >= minDeltaT); 00636 00637 // interpolate linearly. Works correctly even if time < point[0].time. 00638 double f=(time-point[index].time)/dt; 00639 position = (1.0-f)*point[index].position + f*point[index+1].position; 00640 G4ThreeVector momentum = (1.0-f)*point[index].momentum + 00641 f*point[index+1].momentum; 00642 fourMomentum.setVectM(momentum,definition->GetPDGMass()); 00643 00644 if(verbose >= 3) printf("Bunch::getReferencePos4Mom(%.4f) " 00645 "pos=%.3f,%.3f,%.3f 4-mom=%.3f,%.3f,%.3f,%.3f\n", 00646 time,position[0],position[1],position[2], 00647 fourMomentum[0],fourMomentum[1],fourMomentum[2], 00648 fourMomentum[3]); 00649 00650 return true; 00651 }
bool Bunch::init | ( | ) |
init() initializes the computation, sizing the grid for the initial bunch, and computing the field for the initial time step. Called after all tracks are added to the bunch, before stepping. Returns false if failure.
References bound_x, bound_y, bound_z, computeField(), getReferencePos4Mom(), BLRunManager::getStepTime(), minActive, poisson, resizeGrid(), runManager, tracks, PoissonConvolve3D::updatePosition(), and verbose.
00654 { 00655 if(minActive < 0) 00656 minActive = (tracks.size() * (-minActive))/100; 00657 00658 resizeGrid(true); 00659 00660 // get position and gamma of reference 00661 G4double time=runManager->getStepTime(); 00662 G4ThreeVector refPos; 00663 G4LorentzVector ref4mom; 00664 if(!getReferencePos4Mom(time,refPos,ref4mom)) { 00665 if(verbose >= 3) printf("Bunch::init returning false\n"); 00666 return false; 00667 } 00668 G4double gamma=ref4mom.gamma(); 00669 00670 poisson->updatePosition(-bound_x,bound_x,-bound_y, 00671 bound_y,-gamma*bound_z,gamma*bound_z); 00672 00673 bool retval=computeField(); 00674 00675 return retval; 00676 }
bool Bunch::isInBunch | ( | G4Track * | track | ) |
isInBunch() returns true if this track is in the bunch. Tracks are selected by these criteria: same particle as reference within bound_x,bound_y,bound_z of the bunch's reference traj. v/c in the bunch's beam frame less than maxBeta
same particle as reference
within bound_x,bound_y,bound_z of the bunch's reference traj.
v/c in the bunch's beam frame less than maxBeta
References bound_x, bound_y, bound_z, definition, getReferencePos4Mom(), maxBeta, and verbose.
Referenced by addTrack().
00679 { 00680 // track must be alive 00681 G4TrackStatus trackStatus = track->GetTrackStatus(); 00682 if(trackStatus != fAlive && trackStatus != fStopButAlive) { 00683 if(verbose >= 3) printf("Not in bunch, not alive\n"); 00684 return false; 00685 } 00686 00687 /// same particle as reference 00688 if(track->GetDefinition() != definition) { 00689 if(verbose >= 3) printf("Not in bunch, wrong particle\n"); 00690 return false; 00691 } 00692 00693 /// within bound_x,bound_y,bound_z of the bunch's reference traj. 00694 G4ThreeVector refPos; 00695 G4LorentzVector ref4mom; 00696 if(!getReferencePos4Mom(track->GetGlobalTime(),refPos,ref4mom)) { 00697 if(verbose >= 3) printf("Not in bunch, time too large\n"); 00698 return false; 00699 } 00700 G4ThreeVector p = track->GetPosition() - refPos; 00701 if(fabs(p.x()) > bound_x || fabs(p.y()) > bound_y || 00702 fabs(p.z()) > bound_z) { 00703 if(verbose >= 3) printf("Not in bunch, too far away\n"); 00704 return false; 00705 } 00706 00707 /// v/c in the bunch's beam frame less than maxBeta 00708 G4ThreeVector boost=ref4mom.findBoostToCM(); 00709 G4LorentzVector v; 00710 v.setVectM(track->GetMomentum(),track->GetDefinition()->GetPDGMass()); 00711 if(v.boost(boost).beta() > maxBeta) { 00712 if(verbose >= 3) 00713 printf("Not in bunch, beta=%.4f > %.4f=maxBeta\n", 00714 v.boost(boost).beta(),maxBeta); 00715 return false; 00716 } 00717 00718 if(verbose >= 3) printf("Is in bunch\n"); 00719 return true; 00720 }
bool Bunch::computeField | ( | ) |
All tracks in the bunch are added into the PoissonConvolve3D and the field is computed. returns false if current step time is beyond the range of the bunch's reference.
References approx, bound_x, bound_y, bound_z, charge, Bunch::Approx::computeApprox(), definition, extrapolateFrac, fixedGrid, BLRunManager::getDeltaT(), getReferencePos4Mom(), BLRunManager::getStepTime(), Bunch::Approx::getVector(), goodGuess, minActive, nParticles, poisson, Bunch::Approx::putCharge(), PoissonConvolve3D::putCharge(), Bunch::Approx::reset(), resizeGrid(), runManager, PoissonConvolve3D::setApproximation(), PoissonConvolve3D::solve(), SUPPRESSGRID, tracks, PoissonConvolve3D::updatePosition(), useApproximationOnly, verbose, and PoissonConvolve3D::zeroRhs().
Referenced by init().
00723 { 00724 if(verbose >= 3) printf("Bunch::computeField entered\n"); 00725 00726 // get position and gamma of reference 00727 G4double time=runManager->getStepTime(); 00728 G4ThreeVector refPos; 00729 G4LorentzVector ref4mom; 00730 if(!getReferencePos4Mom(time,refPos,ref4mom)) { 00731 printf("***Bunch: Invalid Reference\n"); 00732 return false; 00733 } 00734 G4double gamma=ref4mom.gamma(); 00735 if(verbose >= 3) 00736 printf("Bunch::computeField t=%.3f refPos=%.3f,%.3f,%.3f gamma=%.4f\n", 00737 time,refPos[0],refPos[1],refPos[2],gamma); 00738 00739 00740 // resize the grid, if necessary 00741 if(fixedGrid == 0) { 00742 if(resizeGrid()) { 00743 poisson->updatePosition(-bound_x,bound_x,-bound_y, 00744 bound_y,-gamma*bound_z,gamma*bound_z); 00745 goodGuess = false; 00746 } 00747 } 00748 00749 poisson->zeroRhs(); 00750 nParticles = 0; 00751 approx.reset(this); 00752 00753 int nSuppress=0; 00754 for(unsigned i=0; i<tracks.size(); ++i) { 00755 G4Track *track = tracks[i]; 00756 if(!track) continue; 00757 G4TrackStatus trackStatus = track->GetTrackStatus(); 00758 if(trackStatus != fAlive && trackStatus != fStopButAlive) { 00759 tracks[i] = 0; // erase is expensive for large # tracks 00760 continue; 00761 } 00762 00763 G4ThreeVector p=track->GetPosition(); 00764 double dt=track->GetGlobalTime() - runManager->getStepTime(); 00765 G4double dtExtrapolate=runManager->getDeltaT()*extrapolateFrac; 00766 if(fabs(dt) > dtExtrapolate) 00767 p -= dt * track->GetVelocity(); 00768 p -= refPos; 00769 if(fabs(p.x()) > bound_x*SUPPRESSGRID || 00770 fabs(p.y()) > bound_y*SUPPRESSGRID || 00771 fabs(p.z()) > bound_z*SUPPRESSGRID) { 00772 if(verbose >= 3) printf("spacecharge: suppressed " 00773 "p=%.3f,%.3f,%.3f\n",p[0],p[1],p[2]); 00774 ++nSuppress; 00775 continue; 00776 } 00777 double c=charge*definition->GetPDGCharge(); 00778 if(!poisson->putCharge(p.x(),p.y(),gamma*p.z(),c/epsilon0)) { 00779 printf("***Not in Poisson grid; p=%.3f,%.3f,%.3f\n", 00780 p.x(),p.y(),p.z()); 00781 continue; 00782 } 00783 approx.putCharge(p.x(),p.y(),gamma*p.z(),c/epsilon0); 00784 ++nParticles; 00785 } 00786 00787 if(nParticles < minActive) { 00788 printf("***Bunch: Too few tracks; have %d, require %d\n", 00789 nParticles,minActive); 00790 return false; 00791 } 00792 00793 if(nSuppress > 0) { 00794 if(verbose >= 2) 00795 printf("Bunch::computeField suppressed %d tracks\n", 00796 nSuppress); 00797 } 00798 00799 // Solve Poisson's equation in the beam frame. 00800 approx.computeApprox(); 00801 poisson->setApproximation(approx.getVector()); 00802 if(useApproximationOnly == 0) { 00803 if(verbose >= 3) printf("Bunch::computeField calling solve\n"); 00804 poisson->solve(); 00805 } 00806 00807 goodGuess = true; 00808 00809 if(verbose >= 3) printf("Bunch::computeField returning true\n"); 00810 return true; 00811 }
bool Bunch::resizeGrid | ( | bool | force = false |
) |
resizes the grid, based on current tracks. returns true if grid was resized.
References bound_x, bound_y, bound_z, extrapolateFrac, fixedGrid, BLRunManager::getDeltaT(), getReferencePos4Mom(), BLRunManager::getStepTime(), MAXGRID, MINGRID, percentile, runManager, tracks, and verbose.
Referenced by computeField(), and init().
00814 { 00815 if(fixedGrid != 0) return false; 00816 00817 // get position of reference 00818 G4double time=runManager->getStepTime(); 00819 G4ThreeVector refPos; 00820 G4LorentzVector ref4mom; 00821 getReferencePos4Mom(time,refPos,ref4mom); 00822 00823 // histogram x,y,z for tracks in Bunch 00824 // (histograms extend to twice the bounds.) 00825 const int NHIST=200; 00826 int histX[NHIST], histY[NHIST], histZ[NHIST]; 00827 for(int i=0; i<NHIST; ++i) 00828 histX[i] = histY[i] = histZ[i] = 0; 00829 double dx=2.0*bound_x/NHIST; 00830 double dy=2.0*bound_y/NHIST; 00831 double dz=2.0*bound_z/NHIST; 00832 int n=0; 00833 for(unsigned i=0; i<tracks.size(); ++i) { 00834 G4Track *track = tracks[i]; 00835 if(track == 0) continue; 00836 G4TrackStatus trackStatus = track->GetTrackStatus(); 00837 if(trackStatus != fAlive && trackStatus != fStopButAlive) { 00838 tracks[i] = 0; // erase is expensive for large # tracks 00839 continue; 00840 } 00841 G4ThreeVector p=track->GetPosition(); 00842 double dt=track->GetGlobalTime() - runManager->getStepTime(); 00843 G4double dtExtrapolate=runManager->getDeltaT()*extrapolateFrac; 00844 if(fabs(dt) > dtExtrapolate) 00845 p -= dt * track->GetVelocity(); 00846 p -= refPos; 00847 ++n; 00848 int ix=(int)(fabs(p.x())/dx); 00849 if(ix > NHIST-1) ix=NHIST-1; 00850 ++histX[ix]; 00851 int iy=(int)(fabs(p.y())/dy); 00852 if(iy > NHIST-1) iy=NHIST-1; 00853 ++histY[iy]; 00854 int iz=(int)(fabs(p.z())/dz); 00855 if(iz > NHIST-1) iz=NHIST-1; 00856 ++histZ[iz]; 00857 } 00858 if(n == 0) return false; 00859 00860 int need=(int)(percentile*n/100.0); 00861 double avg = (MINGRID+MAXGRID)/2.0; 00862 00863 static bool first=true; 00864 if(first) printf("bound: %.3f,%.3f,%.3f\n",bound_x,bound_y,bound_z); 00865 00866 // find percentile in x, and set bound_x so it's in [MINGRID,MAXGRID] 00867 int t=0, ix=0, iy=0, iz=0; 00868 for(ix=0; ix<NHIST; ++ix) { 00869 t += histX[ix]; 00870 if(t >= need) break; 00871 }; 00872 double new_x = ix*dx; 00873 if(new_x < MINGRID*bound_x || new_x > MAXGRID*bound_x) { 00874 bound_x = new_x/avg; 00875 force = true; 00876 } 00877 00878 // find percentile in y, and set bound_y so it's in [MINGRID,MAXGRID] 00879 t = 0; 00880 for(iy=0; iy<NHIST; ++iy) { 00881 t += histY[iy]; 00882 if(t >= need) break; 00883 }; 00884 double new_y = iy*dy; 00885 if(new_y < MINGRID*bound_y || new_y > MAXGRID*bound_y) { 00886 bound_y = new_y/avg; 00887 force = true; 00888 } 00889 00890 // find percentile in z, and set bound_z so it's in [MINGRID,MAXGRID] 00891 t = 0; 00892 for(iz=0; iz<NHIST; ++iz) { 00893 t += histZ[iz]; 00894 if(t >= need) break; 00895 }; 00896 double new_z = iz*dz; 00897 if(new_z < MINGRID*bound_z || new_z > MAXGRID*bound_z) { 00898 bound_z = new_z/avg; 00899 force = true; 00900 } 00901 00902 if(!force) return false; 00903 00904 if(verbose >= 2) printf("Bunch new grid size:%.3f,%.3f,%.3f\n", 00905 bound_x,bound_y,bound_z); 00906 return true; 00907 }
void Bunch::addFieldValue | ( | const G4double | point[4], | |
G4double | field[6] | |||
) | const |
addFieldValue adds the field for this bunch to field[].
References PoissonConvolve3D::approxE(), BLRunManager::getDeltaT(), PoissonConvolve3D::getE(), getReferencePos4Mom(), BLRunManager::getStepTime(), nParticles, poisson, runManager, useApproximationOnly, and verbose.
00910 { 00911 // return if no particles in bunch 00912 if(nParticles == 0) return; 00913 00914 // check extrapolation of reference position is OK 00915 G4double stepTime = runManager->getStepTime(); 00916 G4double deltaT = runManager->getDeltaT(); 00917 00918 // get position of reference 00919 G4ThreeVector pos; 00920 G4LorentzVector ref4mom; 00921 if(!getReferencePos4Mom(point[3],pos,ref4mom)) 00922 return; 00923 G4ThreeVector boost=ref4mom.findBoostToCM(); 00924 double gamma=ref4mom.gamma(); 00925 if(verbose >= 3) printf("Bunch::addFieldValue: t=%.3f refPos=%.3f,%.3f,%.3f point=%.3f,%.3f,%.3f\n",point[3],pos[0],pos[1],pos[2],point[0],point[1],point[2]); 00926 00927 G4ThreeVector Ebeam; 00928 if(useApproximationOnly) 00929 Ebeam = poisson->approxE(point[0]-pos[0], 00930 point[1]-pos[1],gamma*(point[2]-pos[2])); 00931 else 00932 Ebeam = poisson->getE(point[0]-pos[0], 00933 point[1]-pos[1],gamma*(point[2]-pos[2])); 00934 00935 // boost of EM fields from Jefimenko, AJP _64_(5), p618 (1996), 00936 // eq12-17 with xyz->zxy and B'=0; boost[] is beta[]=v[]/c_light; 00937 // There is an additional minus sign in boost[] from findBoostToCM(). 00938 // Reference is parallel to the z axis. 00939 double f[6]; 00940 f[0] = gamma*boost[2]*Ebeam[1]/c_light; // Bx 00941 f[1] = -gamma*boost[2]*Ebeam[0]/c_light; // By 00942 f[2] = 0.0; // Bz 00943 f[3] = gamma*Ebeam[0]; // Ex 00944 f[4] = gamma*Ebeam[1]; // Ey 00945 f[5] = Ebeam[2]; // Ez 00946 00947 if(verbose >= 3) 00948 printf("Bunch::addFieldValue(%.3f,%.3f,%.3f,%.3f)\n" 00949 " pos=%.3f,%.3f,%.3f boost=%.3f,%.3f,%.3f " 00950 "gamma=%.3f Ebeam=%.3f,%.3f,%.3f\n" 00951 " B=%.3f,%.3f,%.3f E=%.3f,%.3f,%.3f\n", 00952 point[0]/mm,point[1]/mm,point[2]/mm,point[3]/ns, 00953 pos[0]/mm,pos[1]/mm,pos[2]/mm, 00954 boost[0],boost[1],boost[2],gamma, 00955 Ebeam[0]/(megavolt/meter), 00956 Ebeam[1]/(megavolt/meter), 00957 Ebeam[2]/(megavolt/meter), 00958 f[0]/tesla,f[1]/tesla,f[2]/tesla, 00959 f[3]/(megavolt/meter),f[4]/(megavolt/meter), 00960 f[5]/(megavolt/meter)); 00961 00962 field[0] += f[0]; 00963 field[1] += f[1]; 00964 field[2] += f[2]; 00965 field[3] += f[3]; 00966 field[4] += f[4]; 00967 field[5] += f[5]; 00968 }
void Bunch::testEfield | ( | ) | [static] |
testEfield() will test the units and value of the E field in the beam frame for a point charge.
References BLAssert, PoissonConvolve3D::defaultApproximation(), E, PoissonConvolve3D::getE(), PoissonConvolve3D::putCharge(), PoissonConvolve3D::solve(), and PoissonConvolve3D::zeroRhs().
Referenced by BLCMDspacecharge::command().
00971 { 00972 /* UNITS TEST 00973 E = k*Q/r/r, k=8.987551787E9 (Newton*meter*meter/Coulomb/Coulomb) 00974 And remember that 1 volt/meter == 1 Newton/Coulomb. 00975 So a 1 Coulomb charge has E=8.99E3 MV/m at a distance of 1 meter. 00976 1 coulomb = 6.24150E+18 e+. 00977 */ 00978 const double HW=100.0*mm; // half-width of grid 00979 PoissonConvolve3D *p = new PoissonConvolve3D(33,33,33,-HW,HW,-HW,HW,-HW,HW); 00980 p->zeroRhs(); 00981 p->putCharge(0.0,0.0,0.0,6.24150E+18/epsilon0); 00982 p->defaultApproximation(); 00983 p->solve(); 00984 G4ThreeVector E = p->getE(1.0*meter,0.0,0.0); 00985 printf("spacecharge: testEfield: E field should be %.2f MV/m: %.2f\n", 00986 8987.55, E.x()/(megavolt/meter)); 00987 BLAssert(fabs(E.x()/(megavolt/meter)-8987.55) < 0.1 && \ 00988 fabs(E.y()/(megavolt/meter)) < 0.1 && \ 00989 fabs(E.z()/(megavolt/meter)) < 0.1); 00990 /*** 00991 // check for continuity at the edge of the grid. 00992 printf("#x Phi Ex\n"); 00993 for(double x=0.9*HW; x<1.1*HW; x+=0.01*HW) { 00994 E = p->getE(x,0.0,0.0); 00995 printf("%.2f %.5g %.1f\n",x,p->phi(x,0.0,0.0), 00996 E.x()/(megavolt/meter)); 00997 } 00998 ***/ 00999 delete p; 01000 }
void Bunch::testBfield | ( | ) | [static] |
testBfield() will test the B field in the lab frame for a bunch that is a line of moving charges, 1000 Amps.
References BLAssert, E, PoissonConvolve3D::getE(), PoissonConvolve3D::putCharge(), PoissonConvolve3D::setApproximation(), PoissonConvolve3D::solve(), and PoissonConvolve3D::zeroRhs().
Referenced by BLCMDspacecharge::command().
01003 { 01004 /* Magnetic field test 01005 A uniform current of 1000 Amps, at radius 0.1 m, has B=0.002 T. 01006 1000 Amps = 0.001C charges 1 cm apart moving at 10000 m/s. 01007 */ 01008 double c=0.001*coulomb; 01009 double beta=10000*meter/second/c_light; 01010 double gamma=1.0/sqrt(1.0-beta*beta); 01011 double d=1.0*cm; 01012 PoissonConvolve3D *p = new PoissonConvolve3D(129,129,129,-1000.0,1000.0, 01013 -1000.0,1000.0,-gamma*1000.0,gamma*1000.0); 01014 p->zeroRhs(); 01015 std::vector<Charge> v; 01016 for(double z=-50.0*d; z<50.01*d; z+=d) { 01017 v.push_back(Charge(0.0,0.0,gamma*z,c/epsilon0)); 01018 p->putCharge(0.0,0.0,gamma*z,c/epsilon0); 01019 } 01020 p->setApproximation(v); 01021 p->solve(); 01022 G4ThreeVector E = p->getE(0.1*meter,0.0,0.0); 01023 double By = gamma*beta*E[0]/c_light; // By 01024 printf("spacecharge: testBfield: By should be 0.002 tesla: %.6f\n", 01025 By/tesla); 01026 BLAssert(By-0.002*tesla < 0.00005*tesla); 01027 }
static void Bunch::setVerbose | ( | int | v | ) | [inline, static] |
setVerbose() sets the debug print level
References verbose.
Referenced by BLCMDspacecharge::command().
00239 { verbose=v; }
static void Bunch::setUseApproximationOnly | ( | int | v | ) | [inline, static] |
setUseApproximationOnly() sets it
References useApproximationOnly.
Referenced by BLCMDspacecharge::command().
00242 { useApproximationOnly=v; }
friend class Approx [friend] |
const double Bunch::extrapolateFrac = 0.01 [static, private] |
Referenced by computeField(), and resizeGrid().
const double Bunch::minDeltaT = 1.0e-6*ns [static, private] |
Referenced by addReferencePoint(), and getReferencePos4Mom().
std::vector<Point> Bunch::point [private] |
Referenced by addReferencePoint(), getReferencePos4Mom(), and nTrajectoryPoints().
unsigned Bunch::index [private] |
Referenced by Bunch(), and getReferencePos4Mom().
double Bunch::prevTime [private] |
Referenced by addReferencePoint(), and Bunch().
G4ParticleDefinition* Bunch::definition [private] |
Referenced by Bunch(), computeField(), getDefinition(), getReferencePos4Mom(), and isInBunch().
double Bunch::charge [private] |
Referenced by Bunch(), and computeField().
double Bunch::maxBeta [private] |
Referenced by Bunch(), and isInBunch().
double Bunch::bound_x [private] |
Referenced by Bunch(), computeField(), getBound(), init(), isInBunch(), Bunch::Approx::reset(), and resizeGrid().
double Bunch::bound_y [private] |
Referenced by Bunch(), computeField(), getBound(), init(), isInBunch(), Bunch::Approx::reset(), and resizeGrid().
double Bunch::bound_z [private] |
Referenced by Bunch(), computeField(), getBound(), init(), isInBunch(), Bunch::Approx::reset(), and resizeGrid().
int Bunch::nParticles [private] |
Referenced by addFieldValue(), Bunch(), computeField(), and getNParticles().
double Bunch::percentile [private] |
Referenced by Bunch(), and resizeGrid().
int Bunch::minActive [private] |
Referenced by Bunch(), computeField(), getMinActive(), and init().
PoissonConvolve3D* Bunch::poisson [private] |
Referenced by addFieldValue(), Bunch(), computeField(), and init().
bool Bunch::goodGuess [private] |
Referenced by Bunch(), and computeField().
bool Bunch::fixedGrid [private] |
Referenced by Bunch(), computeField(), and resizeGrid().
Approx Bunch::approx [private] |
Referenced by Bunch(), computeField(), and getNapprox().
std::vector<G4Track*> Bunch::tracks [private] |
Referenced by addTrack(), computeField(), init(), resizeGrid(), and size().
BLRunManager* Bunch::runManager [private] |
Referenced by addFieldValue(), Bunch(), computeField(), init(), and resizeGrid().
int Bunch::verbose = 0 [static, private] |
Referenced by addFieldValue(), computeField(), getReferencePos4Mom(), init(), isInBunch(), resizeGrid(), and setVerbose().
int Bunch::useApproximationOnly = 0 [static, private] |
Referenced by addFieldValue(), computeField(), and setUseApproximationOnly().