|
|
|
|
![]() |
![]() |
![]() | ||
|
About McStas Download Documentation |
A.3 Magnetic fields: the precession algorithm and field frameworkAll magnetic-field-related polarisation components in McStas share a common run-time library, pol-lib (mccode/nlib/share/pol-lib.c/.h), which provides the spin-precession integrator and a small set of built-in field functions. A separate library, ref-lib, provides the standard supermirror reflectivity function (StdReflecFunc, section A.2.2) used by the polarising mirrors and guides.
A.3.1 The magnetic field stackRather than each field-producing component computing precession locally and independently, pol-lib maintains a small per-particle stack of active magnetic fields, _particle->mcMagnet. A component that defines a field region (e.g. Pol_Bfield) pushes a description of its field onto this stack when a particle enters the region, using
where field_type selects one of the built-in field functions (section A.3.3), rotation/position record the field region’s placement in the lab frame (so the field can later be evaluated in the region’s own local coordinates regardless of where in the instrument it sits), and params holds up to 8 doubles of field-specific parameters (amplitude, extent, …). A companion Pol_Bfield_stop component calls mcmagnet_pop() to remove the field from the stack once the particle leaves the region. Because this is a stack rather than a single active field, field regions may be nested or overlap: any component placed between a Pol_Bfield/Pol_Bfield_stop pair – including another, independent field region – experiences the vector sum of every field currently on the stack (evaluated by mcmagnet_get_field(), which walks the whole stack, transforms each field into the lab frame, and adds the contributions). A field region may also be declared closed (concentric=0), in which case it pushes and pops its own field internally and no other components may be placed inside it – this is the simpler, non-nestable mode used when a single self-contained field region is all that is needed. Whenever a particle is propagated through a region with an active field (technically: whenever PROP_DT is called while _particle->mcMagnet is non-NULL), the propagation macro transparently invokes the precession integrator described next, so that ordinary component code (slits, monitors, samples placed inside a field region) does not need to know anything about polarisation – the spin precesses correctly regardless of what else is happening to the particle during that propagation step.
A.3.2 Numerical spin precession: SimpleNumMagnetPrecessionThe general-purpose precession routine, SimpleNumMagnetPrecession(), integrates Eq. A.11 numerically along the particle’s straight-line trajectory (gravity is not accounted for inside the field itself) for a total propagation time \(dt\), using an adaptive-step scheme:
Positions/velocities/spin are tracked internally in the lab frame (fields are pushed to the stack together with the rotation/position needed to transform into and out of each field region’s local frame) and the final spin is transformed back into the calling component’s local frame before being returned. Pol_tabled_field (section A.4) re-implements this identical algorithm internally (rather than going through the shared field stack), so that it can query its own tabulated/ interpolated field directly. Two component-specific accuracy parameters, exposed via mc_pol_set_timestep() and mc_pol_set_angular_accuracy(), allow the initial sub-step size and the angular-accuracy threshold to be tuned instrument-wide if the defaults are not adequate for a particular field geometry.
A.3.3 Available field functionsThe field pushed onto the stack by Pol_Bfield is one of the following built-in functions, selected by the integer field_type parameter (Pol_FieldBox and Pol_constBfield always use the constant-field case, evaluated in closed form rather than via the stack):
New field functions can be added by writing a function with the signature of e.g. const_magnetic_field() in pol-lib.c and adding a case to magnetic_field_dispatcher(); per the file header, this requires modifying the shared library rather than being an end-user-facing extension point. |
|||||||
| ||||||||