SIMION® Industry standard charged particle optics simulation software.
About | Documentation | Community/Support | Downloads | Ordering

Info: User Programming

From SIMION

Table of contents

Cookbook of SIMION user programming (PRG) examples

This is a collection of common SIMION user programming techniques. See also Lua Cookbook.

Ensure time steps terminate on multiples of "step"

This code ensures that time step boundaries fall on multiples of time "step_size". For example, 0.001, 0.002, 0.0003, etc. microseconds. SIMION may still insert additional time-steps. Another way to do this is to enable "time markers" every 0.001 microseconds (ion definition screen of SIMION 7.0).

; PRG example
DEFA step_size 0.001  ; microseconds

SEG tstep_adjust
  ; max_step = (1 - frac(ion_time_of_flight / step_size)) * step_size 
  RCL ion_time_of_flight RCL step / FRAC CHS 1 + RCL step * STO max_step
 
  ; if ion_time_step > max_step
  RCL ion_time_step RCL max_step X>=Y GTO skip1
    ; max_step = ion_time_step
    RCL max_step STO ion_time_step
  LBL skip1
 # SL example
 adjustable step_size = 0.001  # microseconds
 
 sub tstep_adjust
   max_step = (1 - frac(ion_time_of_flight / step_size)) * step_size
   if ion_time_step > max_step
     max_step = ion_time_step
   endif
 endsub

Kill particle if time of flight reaches some maximum

The following code will cause particles to terminate precisely upon time of flight (TOF) reaching some maximum value specified. You may find this code useful to limit the duration in which particles fly, especially if particles would normally fly on essentially forever such as in an ion-trap/ICR.

We use a tstep_adjust segment here to ensure that a time-step ends exactly at time max_time given (this may alternately be done by enabling a time marker to occur at max_time), which is not essential but does improve the preciseness of the termination time. Then we have an other_actions segment to cause the particle to terminate if the time of flight is reached in the current time step. Some care is taken to ensure we terminate precisely on the correct time step. Use data recording to record TOF on ion splat to verify this works.

The following is a Lua version of the program (requires SIMION 8):

 simion.workbench_program()
 
 adjustable max_time = 2      -- maximum time of flight in microseconds
 
 -- Overrides time-step size.  
 function segment.tstep_adjust()
   -- Ensure that a time-step boundary exactly coincids
   --   with max_time (for increased precision).
   if ion_time_of_flight < max_time then
     ion_time_step = min(ion_time_step, max_time - ion_time_of_flight)
   end
 end
 
 -- This segment is called on each time-step.  
 local is_splat_next = false  -- flag indicating splat scheduled on next time-step
 function segment.other_actions()
   -- Splat particle if previously scheduled.
   if is_splat_next then ion_splat = -1 end
 
   -- If the end of current time-step exceeds max_time,
   --   then finish current time-step but schedule a splat
   --   on start of next time-step.
   if ion_time_of_flight >= max_time then
     is_splat_next = true
   end
 
   -- Reset for next particle.
   if ion_splat ~= 0 then is_splat_next = false end
 end

The following is an equivalent PRG version of the program (compatible with SIMION 7):

 defa max_time 2       ; maximum time of flight in microseconds
 defs is_splat_next 0  ; flag indicating splat scheduled
                       ;   on next time-step (1=YES)
 
 -- Overrides time-step size.  
 SEG tstep_adjust
     ; Ensure that a time-step boundary exactly coincides
     ;   with max_time (for increased precision).
     RCL max_time RCL ion_time_of_flight
     X>=Y GOTO skip1
     RCL ion_time_step +
     X<=Y GOTO skip1
         RCL max_time RCL ion_time_of_flight - STO ion_time_step      
     LBL skip1
 
 ; This segment is called on each time-step.
 SEG other_actions
     ; Splat particle if previously scheduled.
     RCL is_splat_next X=0 GOTO skip2
         -1 STO ion_splat
     LBL skip2
 
     ; If the end of current time-step exceeds max_time,
     ;   then finish current time-step but schedule a splat
     ;   on start of next time-step.
     RCL max_time RCL ion_time_of_flight X<Y GOTO skip1
         1 sto is_splat_next
     LBL skip1

Periodically update potential energy display

This code causes the potential energy (PE) view to update every "update_pe_period" microseconds. This is useful in conjunction with a fast_adjust segment that changes electrode potentials during the fly'm.

; PRG example
DEFA update_pe_period 0.010  ; microseconds
DEFS next_pe_update_time 0

SEG other_actions
  ; if ion_time_of_flight >= next_pe_update_time
  RCL ion_time_of_flight RCL next_pe_update_time X>Y GTO skip1
    ; next_pe_update_time = ion_time_of_flight + update_pe_period
    RCL ion_time_of_flight RCL update_pe_period + STO next_pe_update_time
    ; update_pe_surface = 1
    1 STO update_pe_surface
  LBL skip1
# SL example
adjustable update_pe_period = 0.010  # microseconds
static next_pe_update_time = 0

sub other_actions
  if ion_time_of_flight >= next_pe_update_time
    next_pe_update_time = ion_time_of_flight + update_pe_period
    update_pe_surface = 1
  endif
endsub

Applying a non-repeating segmented waveform potential

These user programs apply a non-repeating wave-form voltage to an electrode such that the waveform consists of a series of line segments. Both SIMION 8 (Lua) and SIMION 8 (PRG) versions of the program are included.

 -- SIMION 8.0 user program (Lua) to create non-repeating
 -- waveform of line segments.
 --
 -- Note: for better accuracy, also ensure that your time-steps are
 -- sufficiently small relative to the waveform.  For example, impose a
 -- sufficiently large negative (or positive) trajectory quality control
 -- value, enable time step markers, or add a tstep_adjust segment here.
 --
 -- D.Manura-2006-11--Rev.2
 simion.workbench_program()
 
 -- Here's where the waveform is defined as a list
 -- of ordered pairs (t, v) of times (t) and voltages (v).
 local wave = {
   {0, 20},       -- initial
   {10, 20},
   {20, 60},
   {30, 60},
   {30, 30},
   {math.huge, 30} -- infinity
 }
 
 function segment.fast_adjust()
   -- For improved accuracy, define time t at the mid-point of the
   -- time-step.  The computed potential at this time will then
   -- be the accumulated average potential over the entire time-step.
   local t = ion_time_of_flight + ion_time_step * 0.5
 
   -- Locate current line segment [n-1, n] of the waveform.
   local n
   for m = 1, #wave do
     n = m; if wave[m][1] > t then break end
   end
 
   -- Obtain points (t1,v1) and (t2,v2) of that line segment.
   local t1, t2, v1, v2 = wave[n-1][1], wave[n][1], wave[n-1][2], wave[n][2]
 
   -- Linearly interpolate potential over the line segment.
   local v = v1 + (t - t1) * ((v2-v1)/(t2-t1))
 
   -- Store voltage.
   adj_elect01 = v
 end
 ; SIMION 7.0 user program (PRG) to create non-repeating
 ; waveform of line segments.
 ;
 ; Note: for better accuracy, also ensure that your time-steps are
 ; sufficiently small relative to the waveform.  For example, impose a
 ; sufficiently large negative (or positive) trajectory quality control
 ; value, enable time step markers, or add a tstep_adjust segment here.
 ;
 ; D.Manura-2006-09--Rev.1
 
 DEFS  wave_num_points 6  ; size of array
 ADEFS wave_times      6  ;   note: array values in microseconds
 ADEFS wave_voltages   6  ;   note: array values in volts
 DEFS  is_initialized  0
 
 SEG fast_adjust
   ; Here's where the waveform is defined as a list
   ; of ordered pairs (t, v) of times (t) and voltages (v).
   ; if not is_initialized then
   RCL is_initialized X!=0 GTO skip1
     1      STO  is_initialized
     0    1 ASTO wave_times 20  1 ASTO wave_voltages
     10   2 ASTO wave_times 20  2 ASTO wave_voltages
     20   3 ASTO wave_times 60  3 ASTO wave_voltages
     30   4 ASTO wave_times 60  4 ASTO wave_voltages
     30   5 ASTO wave_times 30  5 ASTO wave_voltages
     1E99 6 ASTO wave_times 30  6 ASTO wave_voltages ; infinity
   LBL skip1
   ; end
 
   ; For improved accuracy, define time t at the mid-point of the
   ; time-step.  The computed potential at this time will then
   ; be the accumulated average potential over the entire time-step.
   ; t = ion_time_of_flight + ion_time_step * 0.5
   RCL ion_time_of_flight RCL ion_time_step 0.5 * + STO t
 
   ; Locate current line segment [n-1, n] of the waveform.
   ; for n = 1, wave_num_points do
   1 STO n LBL loop1
   RCL wave_num_points RCL n X>Y GTO skip2
     ; if wave_times[n] > t then break
     RCL t RCL n ARCL wave_times
     X>Y GTO skip2
     ; n = n + 1
     RCL n 1 + STO n
     GTO loop1
   LBL skip2
   ; end
 
   ; Obtain points (t1,v1) and (t2,v2) of that line segment.
   RCL n 1 - ARCL wave_times    STO t1  ; t1 = wave_times[n-1]
   RCL n ARCL wave_times        STO t2  ; t2 = wave_times[n]
   RCL n 1 - ARCL wave_voltages STO v1  ; v1 = wave_times[n-1]
   RCL n ARCL wave_voltages     STO v2  ; v2 = wave_times[n]
 
   ; Linearly interpolate potential over the line segment.
   ; v = v1 + (t - t1) * ((v2-v1)/(t2-t1))
   RCL v1
   RCL t RCL t1 -
   RCL v2 RCL v1 - RCL t2 RCL t1 - /
   * +
   STO v
 
   ; Store voltage.
   RCL v STO adj_elect01  ; v = adj_elect01
Any comments on this web page? (will be sent to SIS)
[Optional] Your name: email: phone/fax:
(c) 2003-2006 Scientific Instrument Services, Inc. (SIS). Contact SIS.