1 | <!-- ******************************************************** --> |
---|
2 | <!-- Docbook Version: For Toolkit Developers Guide --> |
---|
3 | <!-- ******************************************************** --> |
---|
4 | |
---|
5 | <!-- ******************* Section (Level#1) ****************** --> |
---|
6 | <sect1 id="sect.ExtdFuncEMFld"> |
---|
7 | <title> |
---|
8 | Electromagnetic Fields |
---|
9 | </title> |
---|
10 | |
---|
11 | <!-- ******************* Section (Level#2) ****************** --> |
---|
12 | <sect2 id="sect.ExtdFuncEMFld.CrtNwFld"> |
---|
13 | <title> |
---|
14 | Creating a New Type of Field |
---|
15 | </title> |
---|
16 | |
---|
17 | <para> |
---|
18 | Geant4 currently handles magnetic and electric fields and, |
---|
19 | in future releases, will handle combined electromagnetic |
---|
20 | fields. Fields due to other forces, not yet included in |
---|
21 | Geant4, can be provided by describing the new field and the |
---|
22 | force it exerts on a particle passing through it. For the |
---|
23 | time being, all fields must be time-independent. This |
---|
24 | restriction may be lifted in the future. |
---|
25 | </para> |
---|
26 | |
---|
27 | <para> |
---|
28 | In order to accommodate a new type of field, two classes must |
---|
29 | be created: a field type and a class that determines the force. |
---|
30 | The Geant4 system must then be informed of the new field. |
---|
31 | </para> |
---|
32 | |
---|
33 | <!-- ******* Bridgehead ******* --> |
---|
34 | <bridgehead renderas='sect4'> |
---|
35 | A new Field class |
---|
36 | </bridgehead> |
---|
37 | |
---|
38 | <para> |
---|
39 | A new type of Field class may be created by inheriting from |
---|
40 | G4Field |
---|
41 | |
---|
42 | <informalexample><programlisting> |
---|
43 | class NewField : public G4Field |
---|
44 | { |
---|
45 | public: |
---|
46 | void GetFieldValue( const double Point[3], |
---|
47 | double *pField )=0; |
---|
48 | } |
---|
49 | </programlisting></informalexample> |
---|
50 | |
---|
51 | and deciding how many components your field will have, and what |
---|
52 | each component represents. For example, three components are |
---|
53 | required to describe a vector field while only one component is |
---|
54 | required to describe a scalar field. |
---|
55 | </para> |
---|
56 | |
---|
57 | <para> |
---|
58 | If you want your field to be a combination of different fields, |
---|
59 | you must choose your convention for which field goes first, |
---|
60 | which second etc. For example, to define an electromagnetic field we |
---|
61 | follow the convention that components 0,1 and 2 refer to the magnetic |
---|
62 | field and components 3, 4 and 5 refer to the electric field. |
---|
63 | </para> |
---|
64 | |
---|
65 | <para> |
---|
66 | By leaving the GetFieldValue method pure virtual, you force |
---|
67 | those users who want to describe their field to create a |
---|
68 | class that implements it for their detector's instance of |
---|
69 | this field. So documenting what each component means is required, |
---|
70 | to give them the necessary information. |
---|
71 | </para> |
---|
72 | |
---|
73 | <para> |
---|
74 | For example someone can describe DetectorAbc's field by creating |
---|
75 | a class DetectorAbcField, that derives from your NewField |
---|
76 | |
---|
77 | <informalexample><programlisting> |
---|
78 | class DetectorAbcField : public NewField |
---|
79 | { |
---|
80 | public: |
---|
81 | void MyFieldGradient::GetFieldValue( const double Point[3], |
---|
82 | double *pField ); |
---|
83 | } |
---|
84 | </programlisting></informalexample> |
---|
85 | |
---|
86 | They then implement the function GetFieldValue |
---|
87 | |
---|
88 | <informalexample><programlisting> |
---|
89 | void MyFieldGradient::GetFieldValue( const double Point[3], |
---|
90 | double *pField ) |
---|
91 | { |
---|
92 | // We expect pField to point to pField[9]; |
---|
93 | // This & the order of the components of pField is your own |
---|
94 | // convention |
---|
95 | |
---|
96 | // We calculate the value of pField at Point ... |
---|
97 | } |
---|
98 | </programlisting></informalexample> |
---|
99 | </para> |
---|
100 | |
---|
101 | <!-- ******* Bridgehead ******* --> |
---|
102 | <bridgehead renderas='sect4'> |
---|
103 | A new Equation of Motion for the new Field |
---|
104 | </bridgehead> |
---|
105 | |
---|
106 | <para> |
---|
107 | Once you have created a new type of field, you must create an |
---|
108 | Equation of Motion for this Field. This is required in order to |
---|
109 | obtain the force that a particle feels. |
---|
110 | </para> |
---|
111 | |
---|
112 | <para> |
---|
113 | To do this you must inherit from G4Mag_EqRhs and create your own |
---|
114 | equation of motion that understands your field. In it |
---|
115 | you must implement the virtual function EvaluateRhsGivenB. Given |
---|
116 | the value of the field, this function calculates the |
---|
117 | value of the generalised force. This is the only function that |
---|
118 | a subclass must define. |
---|
119 | |
---|
120 | <informalexample><programlisting> |
---|
121 | virtual void EvaluateRhsGivenB( const G4double y[], |
---|
122 | const G4double B[3], |
---|
123 | G4double dydx[] ) const = 0; |
---|
124 | </programlisting></informalexample> |
---|
125 | </para> |
---|
126 | |
---|
127 | <para> |
---|
128 | In particular, the derivative vector dydx is a vector with six |
---|
129 | components. The first three are the derivative of the position |
---|
130 | with respect to the curve length. Thus they should set equal to |
---|
131 | the normalised velocity, which is components 3, 4 and 5 of y. |
---|
132 | |
---|
133 | <informalexample><programlisting> |
---|
134 | (dydx[0], dydx[1], dydx[2]) = (y[3], y[4], y[5]) |
---|
135 | </programlisting></informalexample> |
---|
136 | </para> |
---|
137 | |
---|
138 | <para> |
---|
139 | The next three components are the derivatives of the velocity |
---|
140 | vector with respect to the path length. So you should write the |
---|
141 | "force" components for |
---|
142 | |
---|
143 | <informalexample><programlisting> |
---|
144 | dydx[3], dydx[4] and dydx[5] |
---|
145 | </programlisting></informalexample> |
---|
146 | |
---|
147 | for your field. |
---|
148 | </para> |
---|
149 | |
---|
150 | <!-- ******* Bridgehead ******* --> |
---|
151 | <bridgehead renderas='sect4'> |
---|
152 | Get a G4FieldManager to use your field |
---|
153 | </bridgehead> |
---|
154 | |
---|
155 | <para> |
---|
156 | In order to inform the Geant4 system that you want it to use |
---|
157 | your field as the global field, you must do the following steps: |
---|
158 | |
---|
159 | <orderedlist spacing="compact"> |
---|
160 | <listitem><para> |
---|
161 | Create a Stepper of your choice: |
---|
162 | <informalexample><programlisting> |
---|
163 | |
---|
164 | yourStepper = new G4ClassicalRK( yourEquationOfMotion ); |
---|
165 | // or if your field is not smooth eg |
---|
166 | // new G4ImplicitEuler( yourEquationOfMotion ); |
---|
167 | </programlisting></informalexample> |
---|
168 | </para></listitem> |
---|
169 | <listitem><para> |
---|
170 | Create a chord finder that uses your Field and Stepper. You |
---|
171 | must also give it a minimum step size, below which it |
---|
172 | does not make sense to attempt to integrate: |
---|
173 | <informalexample><programlisting> |
---|
174 | yourChordFinder= new G4ChordFinder( yourField, |
---|
175 | yourMininumStep, // say 0.01*mm |
---|
176 | yourStepper ); |
---|
177 | </programlisting></informalexample> |
---|
178 | </para></listitem> |
---|
179 | <listitem><para> |
---|
180 | Next create a G4FieldManager and give it that chord finder, |
---|
181 | <informalexample><programlisting> |
---|
182 | yourFieldManager= new G4FieldManager(); |
---|
183 | yourFieldManager.SetChordFinder(yourChordFinder); |
---|
184 | </programlisting></informalexample> |
---|
185 | </para></listitem> |
---|
186 | <listitem><para> |
---|
187 | Finally we tell the Geometry that this FieldManager is |
---|
188 | responsible for creating a field for the detector. |
---|
189 | <informalexample><programlisting> |
---|
190 | G4TransportationManager::GetTransportationManager() |
---|
191 | -> SetFieldManager( yourFieldManager ); |
---|
192 | </programlisting></informalexample> |
---|
193 | </para></listitem> |
---|
194 | </orderedlist> |
---|
195 | </para> |
---|
196 | |
---|
197 | <!-- ******* Bridgehead ******* --> |
---|
198 | <bridgehead renderas='sect4'> |
---|
199 | Changes for non-electromagnetic fields |
---|
200 | </bridgehead> |
---|
201 | |
---|
202 | <para> |
---|
203 | If the field you are interested in simulating is not electromagnetic, |
---|
204 | another minor modification may be required. The |
---|
205 | transportation currently chooses whether to propagate a particle |
---|
206 | in a field or rectilinearly based on whether the particle is |
---|
207 | charged or not. If your field affects non-charged particles, you |
---|
208 | must inherit from the G4Transportation and re-implement the |
---|
209 | part of GetAlongStepPhysicalInteractionLength that decides whether |
---|
210 | the particles is affected by your force. |
---|
211 | </para> |
---|
212 | |
---|
213 | <para> |
---|
214 | In particular the relevant section of code does the following: |
---|
215 | |
---|
216 | <informalexample><programlisting> |
---|
217 | // Does the particle have an (EM) field force exerting upon it? |
---|
218 | // |
---|
219 | if( (particleCharge!=0.0) ){ |
---|
220 | |
---|
221 | fieldExertsForce= this->DoesGlobalFieldExist(); |
---|
222 | // Future: will/can also check whether current volume's field is Zero or |
---|
223 | // set by the user (in the logical volume) to be zero. |
---|
224 | } |
---|
225 | </programlisting></informalexample> |
---|
226 | |
---|
227 | and you want it to ask whether it feels your force. If, for the sake |
---|
228 | of an example, you wanted to see the effects of gravity on a |
---|
229 | heavy hypothetical particle, you could say |
---|
230 | |
---|
231 | <informalexample><programlisting> |
---|
232 | |
---|
233 | // Does the particle have my field's force exerted on it? |
---|
234 | // |
---|
235 | if (particle->GetName() == "VeryHeavyWIMP") { |
---|
236 | fieldExertsForce= this->DoesGlobalFieldExist(); // For gravity |
---|
237 | } |
---|
238 | </programlisting></informalexample> |
---|
239 | |
---|
240 | After doing all these steps, you will be able to see the effects of |
---|
241 | your force on a particle's motion. |
---|
242 | </para> |
---|
243 | |
---|
244 | <!-- ******* Bridgehead ******* --> |
---|
245 | <bridgehead role="revisionHistory" renderas="sect4"> |
---|
246 | [Status of this chapter] |
---|
247 | </bridgehead> |
---|
248 | <para> |
---|
249 | <simplelist type="var"> |
---|
250 | <member> |
---|
251 | 10.06.02 partially re-written by D.H. Wright |
---|
252 | </member> |
---|
253 | <member> |
---|
254 | 14.11.02 spell check by P. Arce |
---|
255 | </member> |
---|
256 | Dec. 2006 Conversion from latex to Docbook verson by K. Amako |
---|
257 | <member> |
---|
258 | </member> |
---|
259 | </simplelist> |
---|
260 | </para> |
---|
261 | |
---|
262 | |
---|
263 | </sect2> |
---|
264 | </sect1> |
---|
265 | |
---|
266 | |
---|
267 | |
---|
268 | |
---|