| 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 |
|
|---|