00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 
00013 
00014 
00015 
00016 
00017 
00018 
00019 
00020 
00021 
00022 
00023 
00024 
00025 
00026 
00027 
00028 
00029 #include <time.h>
00030 
00031 #include "Randomize.hh"
00032 #include "G4TransportationManager.hh"
00033 
00034 #include "G4ExplicitEuler.hh"
00035 #include "G4ImplicitEuler.hh"
00036 #include "G4SimpleRunge.hh"
00037 #include "G4SimpleHeum.hh"
00038 #include "G4ClassicalRK4.hh"
00039 #include "G4CashKarpRKF45.hh"
00040 
00041 #include "MyGlobalField.hh"
00042 
00043 MyGlobalField* MyGlobalField::object = 0;
00044 
00045 MyGlobalField::MyGlobalField() : G4ElectroMagneticField(),
00046 minStep(0.01*mm), deltaChord(3.0*mm),
00047 deltaOneStep(0.01*mm), deltaIntersection(0.1*mm),
00048 epsMin(2.5e-7*mm), epsMax(0.05*mm),
00049 fEquation(0), fFieldManager(0),
00050 fFieldPropagator(0), fStepper(0), fChordFinder(0) {
00051     
00052     
00053     
00054     
00055     
00056     
00057     fGlobalFieldMessenger = new MyGlobalFieldMessenger(this);
00058 
00059     fields = new FieldList();
00060 
00061     fStepperType = 4 ;                                
00062 
00063     
00064 
00065     object = this;
00066 
00067     updateField();
00068 }
00069 
00070 
00071 MyGlobalField::~MyGlobalField() {
00072     clear();
00073 
00074     delete fGlobalFieldMessenger;
00075 
00076     if (fEquation)        delete fEquation;
00077     if (fFieldManager)    delete fFieldManager;
00078     if (fFieldPropagator) delete fFieldPropagator;
00079     if (fStepper)         delete fStepper;
00080     if (fChordFinder)     delete fChordFinder;
00081 }
00082 
00083 
00084 void MyGlobalField::updateField() {
00085     first = true;
00086 
00087     nfp = 0;
00088     fp = 0;
00089 
00090     clear();
00091 
00092     
00093     
00094     
00095     
00096     
00097     
00098     
00099     fEquation = new G4EqEMFieldWithSpin(this);
00100 
00101     
00102     G4TransportationManager* fTransportManager =
00103         G4TransportationManager::GetTransportationManager();
00104 
00105     fFieldManager = GetGlobalFieldManager();
00106 
00107     fFieldPropagator = fTransportManager->GetPropagatorInField();
00108 
00109     
00110     
00111     fFieldManager->SetFieldChangesEnergy(true);
00112 
00113     
00114     fFieldManager->SetDetectorField(this);
00115 
00116     
00117     SetStepper();
00118 
00119     
00120     
00121     fChordFinder = new G4ChordFinder((G4MagneticField*)this,minStep,fStepper);
00122 
00123     
00124     fChordFinder->SetDeltaChord( deltaChord );
00125 
00126     fFieldManager->SetAccuraciesWithDeltaOneStep(deltaOneStep);
00127 
00128     fFieldManager->SetDeltaIntersection(deltaIntersection);
00129 
00130     fFieldPropagator->SetMinimumEpsilonStep(epsMin);
00131     fFieldPropagator->SetMaximumEpsilonStep(epsMax);
00132 
00133     G4cout << "Accuracy Parameters:" <<
00134         " MinStep=" << minStep <<
00135         " DeltaChord=" << deltaChord <<
00136         " DeltaOneStep=" << deltaOneStep << G4endl;
00137     G4cout << "                    " <<
00138         " DeltaIntersection=" << deltaIntersection <<
00139         " EpsMin=" << epsMin <<
00140         " EpsMax=" << epsMax <<  G4endl;
00141 
00142     fFieldManager->SetChordFinder(fChordFinder);
00143 
00144 }
00145 
00146 
00147 MyGlobalField* MyGlobalField::getObject() {
00148     if (!object) new MyGlobalField();
00149     return object;
00150 }
00151 
00152 
00153 void MyGlobalField::SetStepper() {
00154     if(fStepper) delete fStepper;
00155 
00156     switch ( fStepperType ) {
00157         case 0:
00158             
00159                                                       
00160             fStepper = new G4ExplicitEuler( fEquation, 12 );
00161             G4cout << "G4ExplicitEuler is called" << G4endl;
00162             break;
00163         case 1:
00164             
00165                                                       
00166             fStepper = new G4ImplicitEuler( fEquation, 12 );
00167             G4cout << "G4ImplicitEuler is called" << G4endl;
00168             break;
00169         case 2:
00170             
00171                                                       
00172             fStepper = new G4SimpleRunge( fEquation, 12 );
00173             G4cout << "G4SimpleRunge is called" << G4endl;
00174             break;
00175         case 3:
00176             
00177                                                       
00178             fStepper = new G4SimpleHeum( fEquation, 12 );
00179             G4cout << "G4SimpleHeum is called" << G4endl;
00180             break;
00181         case 4:
00182             
00183                                                       
00184             fStepper = new G4ClassicalRK4( fEquation, 12 );
00185             G4cout << "G4ClassicalRK4 (default) is called" << G4endl;
00186             break;
00187         case 5:
00188             
00189                                                       
00190             fStepper = new G4CashKarpRKF45( fEquation, 12 );
00191             G4cout << "G4CashKarpRKF45 is called" << G4endl;
00192             break;
00193         default: fStepper = 0;
00194     }
00195 }
00196 
00197 
00198 G4FieldManager* MyGlobalField::GetGlobalFieldManager() {
00199     return G4TransportationManager::GetTransportationManager()
00200         ->GetFieldManager();
00201 }
00202 
00203 
00204 void MyGlobalField::GetFieldValue(const G4double* point, G4double* field) const {
00205     
00206     
00207     
00208 
00209     field[0] = field[1] = field[2] = field[3] = field[4] = field[5] = 0.0;
00210 
00211     
00212     if(point[0] != point[0]) return;
00213 
00214     
00215     if (first) ((MyGlobalField*)this)->setupArray();  
00216 
00217     for (int i=0; i<nfp; ++i) {
00218         const MyElementField* p = fp[i];
00219         if (p->isInBoundingBox(point)) {
00220             p->addFieldValue(point,field);
00221         }
00222     }
00223 
00224     if(0) {
00225         G4cout << "Point = [" << point[0]/cm << ", "
00226             << point[1]/cm << ", " << point[2]/cm << "] cm" << G4endl;
00227         G4cout << " Field = [" << field[0]/tesla << ", " << field[1]/tesla << ", "
00228             << field[2]/tesla << "]" << G4endl
00229             << "         [" << field[3] << ", " << field[4]
00230             << ", " << field[5]<< "] " << G4endl;
00231     }
00232 }
00233 
00234 
00235 void MyGlobalField::clear() {
00236     if (fields) {
00237         if (fields->size()>0) {
00238             FieldList::iterator i;
00239             for (i=fields->begin(); i!=fields->end(); ++i) delete *i;
00240             fields->clear();
00241         }
00242     }
00243 
00244     if (fp) delete[] fp;
00245 
00246     first = true;
00247 
00248     nfp = 0;
00249     fp = NULL;
00250 }
00251 
00252 
00253 void MyGlobalField::setupArray() {
00254     first = false;
00255     nfp = fields->size();
00256     fp = new const MyElementField* [nfp+1];           
00257     for (int i=0; i<nfp; ++i) fp[i] = (*fields)[i];
00258 
00259     
00260 }