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 }