Stopping powers are critical for the simulation and analysis of RBS spectra since the depth scale is determined solely by the energy loss into the substrate. Unfortunately, stopping powers are difficult to measure and semi-empirical analytical expressions have become the norm for analytical work. The complexity of the semi-empirical algorithms prohibit their primary use in simulators like RUMP. Instead, polynomial fits (normally sixth order) are typically used to provide both the stopping power and the low order derivatives with respect to energy. Coefficients for the stopping power polynomials are normally obtained by fitting to the semi-empirical models.
RUMP internally uses a sixth order polynomial either in the energy
or in the square root of the energy. Fitting as a function of the
square root of the energy generally results in a better match to the
Bragg peak, especially at low energies. Historically though,
polynomials linear in energy have been used and this is the default
for RUMP. Switching between fitting modes is accomplished using
the command
config stop_type [sqrt | linear]
Stopping power polynomial coefficients are generated on an as-needed
basis during simulation and analysis. Separate tables are maintained for
each incident particle, with different incident isotopes potentially handled
by energy scaling. For each target element, stopping powers are calculated
via some semi-empirical method over a relevent energy range. This range
is set nominally from 0.12 Emax to 1.15 Emax
for fits linear in energy and from 0.06 Emax for fit in square of
energy. Below 0.03 Emax, the table
Several algorithms exist for the semi-empirical calculation of the
stopping powers. The default algorithm to handle all elements in all
targets is the
The semi-empirical stopping power calculation proceeds as follows:
The casual RBS user can likely all of the alternate algorithms and just use the defaults. Simple modifications to the tables, such as increasing the stopping power of a given target by a constant, can be handled using the exception mechanism. Only if working with high Z ion beams should it be necessary to consider the more powerful user DLL mechanism.
An exception table entry is essentially a mathematical expression modifying or setting the stopping power of a particular (Z1,M1,Z2) triplet. Any arbitrary number of exception entries may be defined, although only the last one defined for any given triplet will be used (ie. they are not cummulative). For standard RBS, these exceptions are only ocassionally used and then only to provide a multiplicative scaling to the Ziegler algorithm values. However, the mechanism is sufficiently general to be used extensively in high Z scattering.
To load an exception file, use:
config stop_load exception.stp
where exception.stp is the name of the exception data file. RUMP
will assume an extension of .stp if none is given. Loading a new
exception file automatically deletes all existing tables so that the table
takes effect immediately.
An exception file consists of simple ASCII text. Any line beginning with
a # sign is considered a comment. The first non-comment line must be the
text
EXCEPTION TABLE.
Each subsequent non-comment line defines an exception
z1 m1 z2 expression(zgl,kev)
where z1 is the incident particle Z, m1 is the mass
in AMU, z2 is the target Z and expression is an
arbitrary mathematical expression involving potentially the
semi-empirically determined stopping power (as the variable
zgl) or the incident ion energy kev. The expression
must be a single line calculation, but may be arbitrarily long. Use an
isolated backslash character (\) at the end of the line as a logical
continuation character.
To scale the stopping power for He in Si by 20%, the appropriate line is
2 4 14 1.2*zgl.
To add 10% modulation on top of the stopping power of Ni, use
2 4 28 zgl*(1+0.10*sin(kev/100)).
To slowly increase the stopping power above 5 MeV:
2 4 14 (kev.lt.5000)?zgl:zgl*(1+.01*(kev-5000))
More usefully, the exceptions for Mylar (which are now hardcoded in RUMP)
would have been
1 1 93 13.37-1.969E-2*kev+1.551E-5*kev^2-...
1 2 93 10.37-4.430E-4*kev-6.729E-6*kev^2+...
2 4 93 12.71+5.538E-2*kev-5.557E-5*kev^2+...
The cgs/Rump/Data directory contains an example exception stopping power file except.stp. This file can be easily modified using any programming text editor, including notepad.
Because of the difficulty matching high energy stopping powers, it is possible (actually easy) to write your own routine to calculate the stopping powers. If possible, CGS would like to obtain a copy of user written stopping power routines, especially ones for high Z incident particles that may be released to other users. At this time, user stopping power routines are possible only in the Windows NT version of RUMP -- UNIX does not generally support the dynamic loading of modules and I haven't had any requests for this capability from OS/2 users.
A user written stopping power routine is a simple DLL containing a single entry point (routine) that returns the stopping power of a given triplet at a given energy. Because it is a DLL, any algorithm that can be programmed in C can be used. The most major limitation is that the routine must be compiled with a compatible version of the Microsoft C compiler -- how long any given compiler is compatible is up to the whims and wishes of the evil Gates empire. A very simple example user routine is provided in the cgs/Rump/MyStop directory of the distribution. This code is also reproduced below.
To load a user stopping power routine,
config stop_user mystop.dll
where mystop.dll is the name of user written DLL. RUMP will assume
an extension of .dll if none is given, and will search for the file
along the normal RUMP search directories. Loading a new user stopping power
routine automatically deletes all existing tables so that the changes will
take effect immediately.
/* ===========================================================================
-- Example file of user defined stopping power calculations.
--
-- This program traps the Z=93 element (defined as Mylar) and calculates
-- the stopping power values for H, D and He from a simple polynomial
--
-- Requirements:
-- (1) ZStop must be an exported entry point to this DLL
-- (see the .def file)
-- (2) ZStop must be prototyped as in this file
-- (3) Zstop returns an integer
-- 0 => This incident/target combination is handled
-- !0 => Don't use this routine for that pair
-- (4) Must return stopping power in ev/1E15 at/cm^2 units ONLY
--
-- Under NT, this must be compiled with at least /LD option. Typical is
-- cl /nologo /LD /G5 /W3 /O2 mystop.c mystop.def
-- where mystop.def includes at least
-- LIBRARY mystop
-- EXPORTS
-- ZStop
--
-- To verify that the code is being used, check the reports after first sim:
-- Fitting particle 2H for Z = 93 ... usf ... maximum deviation: 0.00%
-- The "u" in "usf" indicates user routine. z is ziegler, e is exception
-- and "m" is mylar kludge.
--
-- Stopping powers are only generated once unless conditions are changed
-- dramatically. Unloading this routine, or loading a new one, will
-- automatically release all of the modules and recalculate stopping powers.
=========================================================================== */
/* ------------------------------ */
/* Feature test macros */
/* ------------------------------ */
#define _POSIX_SOURCE /* Always require POSIX standard */
#define TRUE 1
#define FALSE 0
/* ------------------------------ */
/* Standard include files */
/* ------------------------------ */
#include <stdlib.h>
/* ===========================================================================
-- Usage: int ZStop(int z1, double m1, int z2, double kev, double *stop);
--
-- Description: Calculates the stopping power in eV/1E15 for pair
--
-- Inputs: z1 - incident particle Z
-- m1 - incident particle mass
-- z2 - target Z
-- keV - particle energy in KeV
--
-- Outputs: stop - returned stopping power in eV/1E15 at/cm^2
--
-- Returns: 0 ==> routine handles this pair
-- !0 ==> routine does not handle this pair
--
-- Notes: (1) The "handles this pair" is only checked once, with keV set
-- to the maximum it will ever be. If the routine handles the
-- incident/target pair, it must do so for all energies below
-- the given keV.
-- (2) No distinction is made between nuclear and electronic stopping.
-- (3) If this routine chooses not to handle the pair, the default
-- calculation will be automatically used, possible modified by
-- the exception tables.
-- (4) This routine will be called many (currently 201) times for each
-- particle pair. The values are fit to the internal RUMP
-- polynomial before use.
=========================================================================== */
int ZStop(int z1, double m1, int z2, double kev, double *stop) {
double *p;
static double h_in_my[6] =
{13.37, -1.969E-2, +1.551E-5, -6.592E-9, +1.426E-12, -1.229E-16};
static double d_in_my[6] =
{10.37, -4.430E-4, -6.729E-6, +4.674E-9, -1.239E-12, +1.172E-16};
static double he_in_my[6] =
{12.71, +5.538E-2, -5.557E-5, +2.440E-8, -5.175E-12, +4.274E-16};
/* Check for everything we don't handle */
if (z2 != 93 || z1 > 2) return(-1); /* We don't handle */
if (z1 == 1 && m1 > 2.1) return(-1); /* really bad anyway */
if (z1 == 2 && m1 != 4) return(-1);
/* Select one of the polynomial sets */
if (z1 == 1 && m1 < 1.1) { /* Hydrogen table */
p = d_in_my;
} else if (z1 == 1) { /* Deuterium table */
p = d_in_my;
} else { /* Helium table */
p = he_in_my;
}
/* Calculate the value */
*stop = ((((p[5]*kev + p[4])*kev + p[3])*kev + p[2])*kev + p[1])*kev + p[0];
/* Return that we did indeed calculate */
return 0;
}