|
| |
Exporting Electrostatic and Magnetic Field Data from SIMION (and Importing it too)David Manura, Scientific Instrument Services, Inc. 2004-03-24. Updated: $Date: 2004/07/20 05:23:17 $. AbstractA typical usage of SIMION is to create a *.PA or *.PA# potential array file defining an electrode geometry with set voltages potentials on the electrodes, refine the potential array (i.e. solve for the potentials or fields at the non-electrode, space points), and then fly ions through one or more of those refined potential arrays placed in a workbench. Sometimes, however, you may wish to export the electrostatic or magnetic field calculated by SIMION to an external program or import the field from an external program. For example, you might wish to export a 2D or 3D map of the electric or magnetic field to a data analysis program such as Excel, MATLAB, or Mathcad. Alternately, you may have calculated a field in another program and wish to import it into SIMION. There are several ways to export a field from SIMION. First, since the field vectors and other parameters effective on an ion are available as variables to user programs during ion flight, you could write a user program that jumps a neutral particle to every point on the 2D or 3D grid and collect the data you desire at those points. This solution given here. A second solution, discussed later in this article, is to read the data directly from a refined and fast adjusted *.PA0 file using the SL Tools utility or from a general purpose programming language, possibly using the SL Libraries (the SL Tools and SL Libraries are only available in the SIMION SL Toolkit). There are also several ways to import a field into SIMION. One is to write a user program that sets the effective electrostatic or magnetic field variables for each ion at each timestep of the calculation by looking up in a data file the field defined for the ion's current position. This simulates a refined potential array. The second solution, also mentioned here, is to create the refined *.PA0 file directly and then read that *.PA0 file into SIMION as normal. There may also be quite different data import/export needs that can also be satisfied with the techniques described in this article. Conceptual Solution for Exporting with a User ProgramLet's start with a conceptual description of how we're going to use a user program in SIMION to export a 2D electric field map as a text file for importing into another program (e.g. a data plotting program). In this first example, we will extract a 2D map of the electric field from the refined TUNE.PA0 potential array in the "_Tune" example that comes with SIMION:
The below picture gives a conceptual view of how this will be done. We will fly a neutral particle over the entire surface of a plane intersecting our 3D geometry. As shown in the X-Y cross-sectional view (right), the particle will follow a zig-zag pattern. The dots are markers. These dots indicate the locations at which we will sample the data. Obviously, a neutral particle will not naturally follow this zig-zag path, so, as described later in this article, we will need to associate a user program with the potential array, such that the user program will force the ion to follow the zig-zag path.
If, however, you need to collect a 3D map of points, we must instead traverse the neutral particle through an entire 3D rectangular volume as shown below. The trace path here resembles a "space filling curve."
Example StepsTo start setting up this example, copy the "_Tune" subdirectory (in the SIMION program directory) to a new directory named "tunemap". We will use the "tunemap" directory for this example so as not to corrupt the original "_Tune" files. Now, as usual, load the "tunemap\TUNE.PA#" file, refine it, and remove it from memory. Next, we will replace the tune.prg user program with our own user program that traverses a neutral particle over the area or volume we desire to export a map for. We could author this new tune.prg file directly, or we could generate it from high-level SL code using the SL compiler for SIMION. The latter is easier, so we will do that here. First disable the original tune.prg file by renaming it as "tune_backup.prg". If you have the SL compiler for SIMION, create the below file and name it "tune.sl". When you compile this with SL, the SL compiler regenerates the "tune.prg" file from the contents of the "tune.sl" file. The generated "tune.prg" file is shown two figures below. If you don't have the SL compiler, you can simply copy and paste the PRG code directly into your "tune.prg" file. ##### # SL program to record field data at all points on a # 2D or 3D grid. ##### # The extents and granularity of the grid. adjustable ion_x_min = 0.5 adjustable ion_x_max = 98.5 adjustable ion_x_step = 5 adjustable ion_y_min = -38.5 adjustable ion_y_max = 38.5 adjustable ion_y_step = 5 adjustable ion_z_min = 0 adjustable ion_z_max = 0 adjustable ion_z_step = 5 static ion_initialized = 0 static ion_jumped = 0 sub other_actions ion_splat = 0 # prevent ion splats, even on electrodes # initialize trace ion if ion_initialized == 0 ion_px_mm = ion_x_min ion_py_mm = ion_y_min ion_pz_mm = ion_z_min ion_charge = 0 # make unaffected by fields ion_vx_mm = 0 ion_vy_mm = 0 ion_vz_mm = 0 ion_initialized = 1 ion_jumped = 1 exit endif # ion was jumped if ion_jumped == 1 mark() ion_jumped = 0 exit endif # jump ion to next position if ion_px_mm + ion_x_step < ion_x_max ion_px_mm = ion_px_mm + ion_x_step else ion_px_mm = ion_x_min if ion_py_mm + ion_y_step < ion_y_max ion_py_mm = ion_py_mm + ion_y_step else ion_py_mm = ion_y_min if ion_pz_mm + ion_x_step < ion_z_max ion_pz_mm = ion_pz_mm + ion_z_step else ion_splat = 1 exit endif endif endif ion_jumped = 1 endsub Listing 1 - tune.sl - A program for moving a neutral trace particle along
an area- or space-filling curve. Marks are set at grid points.
Let's look at the above SL code to see what this user program is doing. At the top, we define various adjustable variables. The *_min and *_max variables define the x-, y-, and z-extents of a boundary box in which to collect data. These are in mm units and workbench coordinates, but this can be changed in the program. The *_step variables define the width of the grid. Therefore, samples will be taken at the x values of 0.5, 5.5, 10.5, ... up to a value no greater than 98.5. A similar case is for the y and z values. Notice that the boundary box restricts z to the plane z=0, so we are traversing a 2D rectangle, not a 3D rectangular box. We then define an "other_actions" subroutine. This subroutines is called by SIMION at the end of every time-step. We use this subroutine to jump the ion to the next grid location so that the next sample of data may be collected there. At the top of this subroutine is a block of code that initializes the parameters on the neutral trace particle. This code is only executed the first time that other_actions is called. At the bottom, we have the code that jumps the particle to the next position according to a zig-zag pattern. If the particle was jumped, we call the mark() function (in the center section of code) the next time that other_actions is called. mark() is used to trigger data collection and to draw the dots on the ion trace lines. Note that we don't invoke mark() immediately after changing the ion position variables; we must wait until the next call to other_actions so that SIMION has enough time to recalculate its field variables. Below is the compiled tune.prg file generated from the SL compiler. It is not important that you understand its contents.
; This PRG file was automatically generated from SL source code
; using the SIS Simplified SIMION Compiler (SL) 1.0.1-2004-01-12.
; WARNING: This file will be overwritten if you recompile.
; #####
; # SL program to record field data at all points on a
; # 2D or 3D grid.
; #####
;
; # The extents and granularity of the grid.
; adjustable ion_x_min = 0.5
DEFA ion_x_min 0.5
;
; adjustable ion_x_max = 98.5
DEFA ion_x_max 98.5
;
; adjustable ion_x_step = 5
DEFA ion_x_step 5
;
; adjustable ion_y_min = -38.5
DEFA ion_y_min -38.5
;
; adjustable ion_y_max = 38.5
DEFA ion_y_max 38.5
;
; adjustable ion_y_step = 5
DEFA ion_y_step 5
;
; adjustable ion_z_min = 0
DEFA ion_z_min 0
;
; adjustable ion_z_max = 0
DEFA ion_z_max 0
;
; adjustable ion_z_step = 5
DEFA ion_z_step 5
;
; static ion_initialized = 0
DEFS ion_initialized 0
;
; static ion_jumped = 0
DEFS ion_jumped 0
;
; sub other_actions
SEG other_actions
; ion_splat = 0 # prevent ion splats, even on electrodes
0 STO ion_splat
RLUP
;
; # initialize trace ion
; if ion_initialized == 0
0
RCL ion_initialized
X!=Y
GTO label19__
RLUP
RLUP
; ion_px_mm = ion_x_min
RCL ion_x_min
STO ion_px_mm
RLUP
; ion_py_mm = ion_y_min
RCL ion_y_min
STO ion_py_mm
RLUP
; ion_pz_mm = ion_z_min
RCL ion_z_min
STO ion_pz_mm
RLUP
;
; ion_charge = 0 # make unaffected by fields
0 STO ion_charge
RLUP
; ion_vx_mm = 0
0 STO ion_vx_mm
RLUP
; ion_vy_mm = 0
0 STO ion_vy_mm
RLUP
; ion_vz_mm = 0
0 STO ion_vz_mm
RLUP
;
; ion_initialized = 1
1 STO ion_initialized
RLUP
; ion_jumped = 1
1 STO ion_jumped
RLUP
; exit
EXIT
; begin else
GTO label20__
LBL label19__
RLUP
RLUP
LBL label20__
; end if
;
;
; # ion was jumped
; if ion_jumped == 1
1
RCL ion_jumped
X!=Y
GTO label23__
RLUP
RLUP
; mark()
MARK
; ion_jumped = 0
0 STO ion_jumped
RLUP
; exit
EXIT
; begin else
GTO label24__
LBL label23__
RLUP
RLUP
LBL label24__
; end if
;
;
; # jump ion to next position
; if ion_px_mm + ion_x_step < ion_x_max
RCL ion_x_max
RCL ion_px_mm
RCL ion_x_step
+
X>=Y
GTO label35__
RLUP
RLUP
; ion_px_mm = ion_px_mm + ion_x_step
RCL ion_px_mm
RCL ion_x_step
+
STO ion_px_mm
RLUP
; begin else
GTO label36__
LBL label35__
RLUP
RLUP
; ion_px_mm = ion_x_min
RCL ion_x_min
STO ion_px_mm
RLUP
; if ion_py_mm + ion_y_step < ion_y_max
RCL ion_y_max
RCL ion_py_mm
RCL ion_y_step
+
X>=Y
GTO label33__
RLUP
RLUP
; ion_py_mm = ion_py_mm + ion_y_step
RCL ion_py_mm
RCL ion_y_step
+
STO ion_py_mm
RLUP
; begin else
GTO label34__
LBL label33__
RLUP
RLUP
; ion_py_mm = ion_y_min
RCL ion_y_min
STO ion_py_mm
RLUP
; if ion_pz_mm + ion_x_step < ion_z_max
RCL ion_z_max
RCL ion_pz_mm
RCL ion_x_step
+
X>=Y
GTO label31__
RLUP
RLUP
; ion_pz_mm = ion_pz_mm + ion_z_step
RCL ion_pz_mm
RCL ion_z_step
+
STO ion_pz_mm
RLUP
; begin else
GTO label32__
LBL label31__
RLUP
RLUP
; ion_splat = 1
1 STO ion_splat
RLUP
; exit
EXIT
LBL label32__
; end if
;
LBL label34__
; end if
;
LBL label36__
; end if
;
; ion_jumped = 1
1 STO ion_jumped
RLUP
EXIT
; end segment
Listing 2 - tune.prg - PRG program compiled from tune.sl. This
is understood by SIMION.
For the next step, to load the TUNE.IOB file. Then in the PAs tab, select "Fadj" to perform a fast electrode voltage adjust. For this demonstration, let's set the voltages on the electrodes to 100V, 90V, and 0V respectively from left to right:
This generates the following potential energy map in the X-Y potential energy view (PE View tab). Notice that there is 100:90:0 ratio as expected on the heights of the three electrode potentials and that there is a slight potential energy curvature in the center of the middle electrode.
Now let's set up the data recording. First, click the "Def" button under the "Normal" tab to define your ions:
We only need one ion flying to act as the neutral trace particle, so let's not confuse things by flying multiple ions. Ensure that there is only one "Trajectory Group" (the original example has two, so do a "Cut Grp" on the second) and that the number of ions (N) is set to "1 Ions". It is not important what the charge and kinetic energy (KE) are set to here because the user program will reset these both to zero. One thing that is important is for the ion's initial (X, Y, Z) position to to be within your potential array and not touching an electrode. Otherwise, the ion will not be controlled by the user program associated with your potential array, or the ion will "splat" before it even gets the chance to fly. Next we'll set up data recording. In the "To Dev/File" box, enter the file name that data will be saved to (e.g. "data.txt") and enable the "Record" button. To configure data recording, click the "Define" button:
The screen has three parts: the parameters to record, when to record the parameters, and the format in which to record the parameters. Here, we record the X, Y, and Z positions along with the three compontents of the voltage potential gradient (i.e. electric field) denoted by dE/dx, dE/dy, and dE/dz. Ensure that "All Markers" is selected to record data after each mark() call in the user program. "Delimited" rather than "Verbose" should be selected so that the data file outputted is easier to import into Excel or another program. Click "OK" twice to exit. Now we are ready to fly ions. Ensure that the "Vew RD" and "Dots" are not enabled, otherwise the run will be slowed down. Click "Fly'm". You will be afforded the option to adjust any of the adjustable variables in the user program at the time. For now, there is no need to do so, so click "Fly." An ion trace will be drawn.
The simulation will append data to the data.txt file. The contents of the generated data.txt are shown below: ------ Begin Next Fly'm ------ 0.5,-38.5,0,0,0,0 5.5,-38.5,0,-0.278991,-9.13219e-006,0 10.5,-38.5,0,-0.278852,-4.01533e-005,0 15.5,-38.5,0,-0.278547,-7.34804e-005,0 20.5,-38.5,0,-0.278079,-0.000105288,0 25.5,-38.5,0,-0.277488,-0.000123462,0 30.5,-38.5,0,-0.276886,-0.000111344,0 35.5,-38.5,0,-0.27644,-6.18776e-005,0 40.5,-38.5,0,0,0,0 45.5,-38.5,0,0,0,0 50.5,-38.5,0,0,0,0 55.5,-38.5,0,0,0,0 60.5,-38.5,0,-2.31121,-0.00346198,0 65.5,-38.5,0,-2.28817,-0.0052536,0 70.5,-38.5,0,-2.26196,-0.00496627,0 75.5,-38.5,0,-2.23998,-0.00380204,0 80.5,-38.5,0,-2.22422,-0.00257529,0 85.5,-38.5,0,-2.2141,-0.00155748,0 90.5,-38.5,0,-2.20848,-0.000750902,0 95.5,-38.5,0,-2.20649,-6.59663e-005,0 0.5,-33.5,0,0,0,0 5.5,-33.5,0,-0.27911,-6.33095e-005,0 10.5,-33.5,0,-0.278978,-0.00028001,0 15.5,-33.5,0,-0.278676,-0.00050965,0 20.5,-33.5,0,-0.278184,-0.000730146,0 25.5,-33.5,0,-0.27751,-0.00086432,0 30.5,-33.5,0,-0.276761,-0.000781595,0 35.5,-33.5,0,-0.276196,-0.000428521,0 40.5,-33.5,0,0,0,0 45.5,-33.5,0,0,0,0 50.5,-33.5,0,0,0,0 55.5,-33.5,0,0,0,0 60.5,-33.5,0,-2.32302,-0.0263515,0 65.5,-33.5,0,-2.28964,-0.0373788,0 70.5,-33.5,0,-2.25806,-0.0333549,0 75.5,-33.5,0,-2.23508,-0.0246132,0 80.5,-33.5,0,-2.22001,-0.0163149,0 85.5,-33.5,0,-2.21082,-0.00974569,0 90.5,-33.5,0,-2.20585,-0.00466664,0 95.5,-33.5,0,-2.20412,-0.000409193,0 0.5,-28.5,0,0,0,0 5.5,-28.5,0,-0.27942,-0.000122759,0 10.5,-28.5,0,-0.279312,-0.000550141,0 15.5,-28.5,0,-0.279041,-0.00103212,0 20.5,-28.5,0,-0.278523,-0.00155814,0 25.5,-28.5,0,-0.277642,-0.00198206,0 30.5,-28.5,0,-0.27641,-0.00192053,0 35.5,-28.5,0,-0.275413,-0.000982163,0 40.5,-28.5,0,0,0,0 45.5,-28.5,0,0,0,0 50.5,-28.5,0,0,0,0 55.5,-28.5,0,0,0,0 60.5,-28.5,0,-2.35783,-0.0808194,0 65.5,-28.5,0,-2.28606,-0.0923306,0 70.5,-28.5,0,-2.24316,-0.0711283,0 75.5,-28.5,0,-2.22071,-0.0483006,0 80.5,-28.5,0,-2.20886,-0.0305946,0 85.5,-28.5,0,-2.20256,-0.0178336,0 90.5,-28.5,0,-2.19941,-0.00843505,0 95.5,-28.5,0,-2.19836,-0.000736579,0 0.5,-23.5,0,0,0,0 5.5,-23.5,0,-0.279931,-0.000181043,0 10.5,-23.5,0,-0.279888,-0.000826939,0 15.5,-23.5,0,-0.279742,-0.00162472,0 20.5,-23.5,0,-0.279327,-0.00265697,0 25.5,-23.5,0,-0.278276,-0.00386608,0 30.5,-23.5,0,-0.27593,-0.00455823,0 35.5,-23.5,0,-0.272602,-0.00190491,0 40.5,-23.5,0,0,0,0 45.5,-23.5,0,0,0,0 50.5,-23.5,0,0,0,0 55.5,-23.5,0,0,0,0 60.5,-23.5,0,-2.39008,-0.2708,0 65.5,-23.5,0,-2.24277,-0.187416,0 70.5,-23.5,0,-2.20392,-0.116819,0 75.5,-23.5,0,-2.19281,-0.0717227,0 80.5,-23.5,0,-2.1899,-0.0430923,0 85.5,-23.5,0,-2.18944,-0.0244072,0 90.5,-23.5,0,-2.18955,-0.0113757,0 95.5,-23.5,0,-2.18965,-0.000988397,0 0.5,-18.5,0,0,0,0 5.5,-18.5,0,-0.280617,-0.000224068,0 10.5,-18.5,0,-0.280708,-0.00104426,0 15.5,-18.5,0,-0.280871,-0.00215438,0 20.5,-18.5,0,-0.280963,-0.00386668,0 25.5,-18.5,0,-0.2805,-0.00664765,0 30.5,-18.5,0,-0.277762,-0.0110268,0 35.5,-18.5,0,-0.265168,-0.0162149,0 40.5,-18.5,0,-0.174422,-0.0474932,0 45.5,-18.5,0,-0.147528,-0.286583,0 50.5,-18.5,0,-0.298707,-0.677306,0 55.5,-18.5,0,-1.17031,-1.30726,0 60.5,-18.5,0,-2.05017,-0.581398,0 65.5,-18.5,0,-2.10426,-0.275132,0 70.5,-18.5,0,-2.13131,-0.150602,0 75.5,-18.5,0,-2.15082,-0.0865227,0 80.5,-18.5,0,-2.1642,-0.0499965,0 85.5,-18.5,0,-2.17269,-0.0276633,0 90.5,-18.5,0,-2.1774,-0.0127294,0 95.5,-18.5,0,-2.17907,-0.001101,0 0.5,-13.5,0,0,0,0 5.5,-13.5,0,-0.281394,-0.000230872,0 10.5,-13.5,0,-0.281684,-0.00109313,0 15.5,-13.5,0,-0.282377,-0.00235655,0 20.5,-13.5,0,-0.283586,-0.00457495,0 25.5,-13.5,0,-0.285418,-0.0089318,0 30.5,-13.5,0,-0.287716,-0.0183902,0 35.5,-13.5,0,-0.289839,-0.0420459,0 40.5,-13.5,0,-0.300982,-0.109608,0 45.5,-13.5,0,-0.38922,-0.258448,0 50.5,-13.5,0,-0.657992,-0.468081,0 55.5,-13.5,0,-1.18682,-0.596075,0 60.5,-13.5,0,-1.69251,-0.447586,0 65.5,-13.5,0,-1.93302,-0.260687,0 70.5,-13.5,0,-2.04401,-0.147289,0 75.5,-13.5,0,-2.10272,-0.0839641,0 80.5,-13.5,0,-2.13603,-0.0478064,0 85.5,-13.5,0,-2.15498,-0.0261138,0 90.5,-13.5,0,-2.16487,-0.011916,0 95.5,-13.5,0,-2.16827,-0.00102739,0 0.5,-8.5,0,0,0,0 5.5,-8.5,0,-0.282108,-0.000184012,0 10.5,-8.5,0,-0.282616,-0.000882569,0 15.5,-8.5,0,-0.28394,-0.0019637,0 20.5,-8.5,0,-0.286615,-0.0040057,0 25.5,-8.5,0,-0.29189,-0.00832703,0 30.5,-8.5,0,-0.30277,-0.0181475,0 35.5,-8.5,0,-0.327307,-0.0410087,0 40.5,-8.5,0,-0.387568,-0.0901095,0 45.5,-8.5,0,-0.528175,-0.17294,0 50.5,-8.5,0,-0.795584,-0.267461,0 55.5,-8.5,0,-1.17882,-0.31153,0 60.5,-8.5,0,-1.55574,-0.263591,0 65.5,-8.5,0,-1.81796,-0.177358,0 70.5,-8.5,0,-1.97292,-0.107394,0 75.5,-8.5,0,-2.06129,-0.0625832,0 80.5,-8.5,0,-2.1116,-0.0357115,0 85.5,-8.5,0,-2.13978,-0.0194317,0 90.5,-8.5,0,-2.15426,-0.00883244,0 95.5,-8.5,0,-2.15918,-0.000760016,0 0.5,-3.5,0,0,0,0 5.5,-3.5,0,-0.282574,-8.59383e-005,0 10.5,-3.5,0,-0.283243,-0.000415615,0 15.5,-3.5,0,-0.28504,-0.00094064,0 20.5,-3.5,0,-0.288855,-0.00196479,0 25.5,-3.5,0,-0.29684,-0.00417787,0 30.5,-3.5,0,-0.314089,-0.00915266,0 35.5,-3.5,0,-0.35218,-0.0199979,0 40.5,-3.5,0,-0.433901,-0.0407835,0 45.5,-3.5,0,-0.59163,-0.072089,0 50.5,-3.5,0,-0.847145,-0.104281,0 55.5,-3.5,0,-1.17713,-0.118244,0 60.5,-3.5,0,-1.50563,-0.103912,0 65.5,-3.5,0,-1.76257,-0.0743883,0 70.5,-3.5,0,-1.93284,-0.0470257,0 75.5,-3.5,0,-2.03624,-0.0279528,0 80.5,-3.5,0,-2.09648,-0.0160462,0 85.5,-3.5,0,-2.13035,-0.00873328,0 90.5,-3.5,0,-2.1477,-0.00396367,0 95.5,-3.5,0,-2.15358,-0.000340933,0 0.5,1.5,0,0,0,0 5.5,1.5,0,-0.282657,3.75428e-005,0 10.5,1.5,0,-0.283356,0.000181588,0 15.5,1.5,0,-0.285243,0.000412104,0 20.5,1.5,0,-0.289275,0.000864917,0 25.5,1.5,0,-0.297773,0.00184626,0 30.5,1.5,0,-0.316181,0.00404465,0 35.5,1.5,0,-0.356543,0.00878299,0 40.5,1.5,0,-0.441485,0.0177099,0 45.5,1.5,0,-0.601378,0.0309219,0 50.5,1.5,0,-0.854583,0.0442923,0 55.5,1.5,0,-1.17698,0.0500417,0 60.5,1.5,0,-1.49848,0.044205,0 65.5,1.5,0,-1.75393,0.0319375,0 70.5,1.5,0,-1.92616,0.0203356,0 75.5,1.5,0,-2.03192,0.012133,0 80.5,1.5,0,-2.09384,0.00697427,0 85.5,1.5,0,-2.12869,0.00379701,0 90.5,1.5,0,-2.14655,0.00172301,0 95.5,1.5,0,-2.1526,0.000148167,0 0.5,6.5,0,0,0,0 5.5,6.5,0,-0.282333,0.000149931,0 10.5,6.5,0,-0.282918,0.000722035,0 15.5,6.5,0,-0.284465,0.00162048,0 20.5,6.5,0,-0.287676,0.00334571,0 25.5,6.5,0,-0.294229,0.00704111,0 30.5,6.5,0,-0.308161,0.0154128,0 35.5,6.5,0,-0.339441,0.0342874,0 40.5,6.5,0,-0.410892,0.0724863,0 45.5,6.5,0,-0.560982,0.133262,0 50.5,6.5,0,-0.822958,0.198995,0 55.5,6.5,0,-1.17779,0.22841,0 60.5,6.5,0,-1.52902,0.197273,0 65.5,6.5,0,-1.78951,0.137115,0 70.5,6.5,0,-1.9529,0.0848222,0 75.5,6.5,0,-2.04896,0.0498929,0 80.5,6.5,0,-2.1042,0.0285434,0 85.5,6.5,0,-2.13517,0.0155294,0 90.5,6.5,0,-2.15105,0.00705352,0 95.5,6.5,0,-2.15644,0.000606807,0 0.5,11.5,0,0,0,0 5.5,11.5,0,-0.281698,0.000218852,0 10.5,11.5,0,-0.282076,0.00104266,0 15.5,11.5,0,-0.283023,0.00228029,0 20.5,11.5,0,-0.284809,0.0045314,0 25.5,11.5,0,-0.287977,0.00913303,0 30.5,11.5,0,-0.293639,0.0194668,0 35.5,11.5,0,-0.305295,0.0448289,0 40.5,11.5,0,-0.340376,0.107439,0 45.5,11.5,0,-0.455956,0.227968,0 50.5,11.5,0,-0.728956,0.382124,0 55.5,11.5,0,-1.18227,0.463138,0 60.5,11.5,0,-1.62157,0.371183,0 65.5,11.5,0,-1.87896,0.231929,0 70.5,11.5,0,-2.01237,0.134877,0 75.5,11.5,0,-2.08468,0.0774609,0 80.5,11.5,0,-2.12545,0.0440864,0 85.5,11.5,0,-2.1484,0.0240248,0 90.5,11.5,0,-2.16027,0.0109405,0 95.5,11.5,0,-2.16432,0.00094251,0 0.5,16.5,0,0,0,0 5.5,16.5,0,-0.280925,0.000232475,0 10.5,16.5,0,-0.281088,0.00109015,0 15.5,16.5,0,-0.28144,0.00229193,0 20.5,16.5,0,-0.281907,0.0042579,0 25.5,16.5,0,-0.28214,0.00776362,0 30.5,16.5,0,-0.280641,0.0144126,0 35.5,16.5,0,-0.270748,0.0289706,0 40.5,16.5,0,-0.230968,0.0893611,0 45.5,16.5,0,-0.256623,0.286003,0 50.5,16.5,0,-0.482854,0.604512,0 55.5,16.5,0,-1.19687,0.903941,0 60.5,16.5,0,-1.86891,0.553408,0 65.5,16.5,0,-2.03231,0.28211,0 70.5,16.5,0,-2.09624,0.154371,0 75.5,16.5,0,-2.1316,0.0878715,0 80.5,16.5,0,-2.15289,0.0503347,0 85.5,16.5,0,-2.16554,0.0276713,0 90.5,16.5,0,-2.17231,0.0126831,0 95.5,16.5,0,-2.17467,0.00109539,0 0.5,21.5,0,0,0,0 5.5,21.5,0,-0.280187,0.000200938,0 10.5,21.5,0,-0.280189,0.000926703,0 15.5,21.5,0,-0.28014,0.00185643,0 20.5,21.5,0,-0.279862,0.00315107,0 25.5,21.5,0,-0.27889,0.00490158,0 30.5,21.5,0,-0.276048,0.00658494,0 35.5,21.5,0,-0.269265,0.00352703,0 40.5,21.5,0,0,0,0 45.5,21.5,0,0,0,0 50.5,21.5,0,0,0,0 55.5,21.5,0,0,0,0 60.5,21.5,0,-2.32751,0.429983,0 65.5,21.5,0,-2.19934,0.230423,0 70.5,21.5,0,-2.17857,0.133487,0 75.5,21.5,0,-2.17746,0.0792581,0 80.5,21.5,0,-2.18026,0.0467579,0 85.5,21.5,0,-2.18305,0.0262084,0 90.5,21.5,0,-2.18487,0.0121476,0 95.5,21.5,0,-2.18556,0.00105343,0 0.5,26.5,0,0,0,0 5.5,26.5,0,-0.279601,0.000146858,0 10.5,26.5,0,-0.279512,0.000662556,0 15.5,26.5,0,-0.279275,0.00126503,0 20.5,26.5,0,-0.27877,0.00196594,0 25.5,26.5,0,-0.277794,0.00261967,0 30.5,26.5,0,-0.276201,0.00268742,0 35.5,26.5,0,-0.274762,0.00127187,0 40.5,26.5,0,0,0,0 45.5,26.5,0,0,0,0 50.5,26.5,0,0,0,0 55.5,26.5,0,0,0,0 60.5,26.5,0,-2.37817,0.128762,0 65.5,26.5,0,-2.27704,0.125471,0 70.5,26.5,0,-2.23127,0.0890701,0 75.5,26.5,0,-2.21136,0.058064,0 80.5,26.5,0,-2.20222,0.0359978,0 85.5,26.5,0,-2.19785,0.0207422,0 90.5,26.5,0,-2.19583,0.00975352,0 95.5,26.5,0,-2.19518,0.000850022,0 0.5,31.5,0,0,0,0 5.5,31.5,0,-0.27921,8.65756e-005,0 10.5,31.5,0,-0.279084,0.000384959,0 15.5,31.5,0,-0.278789,0.000707476,0 20.5,31.5,0,-0.278283,0.001031,0 25.5,31.5,0,-0.277539,0.00124742,0 30.5,31.5,0,-0.276651,0.00114913,0 35.5,31.5,0,-0.275972,0.00062115,0 40.5,31.5,0,0,0,0 45.5,31.5,0,0,0,0 50.5,31.5,0,0,0,0 55.5,31.5,0,0,0,0 60.5,31.5,0,-2.33368,0.0415904,0 65.5,31.5,0,-2.28981,0.0554188,0 70.5,31.5,0,-2.25402,0.0471428,0 75.5,31.5,0,-2.2307,0.0338053,0 80.5,31.5,0,-2.21645,0.0220522,0 85.5,31.5,0,-2.20812,0.0130593,0 90.5,31.5,0,-2.20373,0.00622616,0 95.5,31.5,0,-2.20221,0.000545148,0 0.5,36.5,0,0,0,0 5.5,36.5,0,-0.279017,3.01866e-005,0 10.5,36.5,0,-0.27888,0.000132425,0 15.5,36.5,0,-0.278575,0.000239169,0 20.5,36.5,0,-0.278102,0.000338183,0 25.5,36.5,0,-0.277493,0.000393187,0 30.5,36.5,0,-0.276859,0.000351519,0 35.5,36.5,0,-0.276388,0.000194264,0 40.5,36.5,0,0,0,0 45.5,36.5,0,0,0,0 50.5,36.5,0,0,0,0 55.5,36.5,0,0,0,0 60.5,36.5,0,-2.31374,0.011099,0 65.5,36.5,0,-2.2886,0.0166011,0 70.5,36.5,0,-2.26118,0.0154935,0 75.5,36.5,0,-2.23893,0.0117628,0 80.5,36.5,0,-2.22329,0.00792593,0 85.5,36.5,0,-2.21336,0.0047775,0 90.5,36.5,0,-2.20788,0.00229828,0 95.5,36.5,0,-2.20596,0.000201823,0 Listing 3 - data.txt - Generated data file containing a field map: x, y, z, E_x, E_y, E_z.
So what can we do with this data? For demonstration, below is an example of importing the data into the gnuplot plotting program (after replacing the commas with spaces as expected by the program). This graph displays the X and Y vector field lines on the X-Y plane. Each vector corresponds to a row in the above data.txt file, where the (X, Y, Delta-X, Delta-Y) values for the vectors are taken from columns numbered (1, 2, 4, 5) in data.txt.
Notice that the above field is the mathematical gradient of the potential map given in SIMION:
Reading a Field Directly from the *.PA0 FileAs mentioned in the introduction, there is another way to extract the field information other than to fly a neutral particle though the entire field: from the PA0 file directly. One way, that does not require any programming, is to use the "PA --> Text" function in the SL Tools program in the SL Toolkit. Another way, described below, is to write a C++, Python, or Perl program that will read the field values directly from the refined and fast-adjusted *.PA0 file. This can be accomplished with the SL Libraries that come with the SL Toolkit. A SIMION potential array file is stored as a bitmap of the voltage potentials at all electrode and non-electrode points. These potential values can be queried directly with the SL Libraries. However, what we really want here is the electric field at all points, which is the gradient of the potential. Starting with SL v. 1.2, the SL Libraries has a functions built-in for computing the gradient according to the calculation methods described starting on p. E-9 of the printed manual. Here is a preview of some Perl code to accomplish the generation of the data.txt file:
use strict;
use SIMION::PA;
my $pa = new SIMION::PA(file => 'c:/sim7/_tune/tune.pa0');
open(my $fh, ">pdata.txt") or die $!;
my $z = 0;
for(my $y = -38.5; $y < 38.5 - 1; $y += 5) {
for(my $x = 0.5; $x < 98.5 - 1; $x += 5) {
print $fh "$x, $y, $z, ",
join(', ', $pa->field_real($x, $y, $z)), "\n";
}
}
Listing 4 - field.pl - Perl program using the SL Libraries
for Perl to generate a data file containing the
electrostatic field map directly from a potential array file.
This code requires the SL Toolkit 1.2 or above.
Below is a snippet of the results. Compare this to the previous data.txt file. 0.5, -38.5, 0, 0, 0, 0 5.5, -38.5, 0, -0.278990594992763, -9.13218690357098e-06, -0 10.5, -38.5, 0, -0.278852413169545, -4.01533280296462e-05, -0 15.5, -38.5, 0, -0.278547491586551, -7.34803709292464e-05, -0 ... Listing 5 - Electrostatic field data file generated from
field.pl.
Note that coordinates here are in grid units with respect to the potential array, not workbench coordinates as before. In this example, both coordinate systems overlap, so no difference is evident. Importing a Field into SIMIONNow that we have discussed exporting a field from SIMION, how do we import a field into SIMION? As before, there are several ways. One way is to associate a user program with your potential array and have the user program adjust the observed electrostatic or magnetic field variables on each ion at each timestep of the calculation by looking up in a (ASCII) data file the field defined for the current ion position. Field values for points not defined in the data file are interpolated from surrounding points. This solution uses the efield_adjust and mfield_adjust program segments and the ion_bfield_* and ion_dvolts_* variables as described on page I-21 and I-28 of the printed SIMION manual. See the "Measured Magnetic Fields" section of the "Advanced SIMION Ion Opics: An ASMS Course" (also distributed on the SIMION CD) for a full explanation of this method. The bfield.prg program in the "Measured Magnetic Fields" lab is written in PRG code. For elucidation, the below listing shows the bfield.prg converted to a high-level SL program. Here, the field for a given ion position is computed from a data file ("bfield.dat"), which is read into the bfield array in memory. If the ion is not located on a point defined in the bfield array, linear interpolation is used with respect to the four surrounding points defined in the bfield array. Notice that we use some array index computations since the bfield array is one-dimensional, but it is storing two-dimensional data. # Define a field from a data file. # (instance scaling 1 mm/gu) static x_size = 21 static y_size = 40 static grid_size = 5 # Field data file. # bx, by; 21x by 40y array; first point is 0,0; # scan lines in x then y every grid_size. adjustable[1680] bfield # 1680 = 21 * 40 * 2 adjustable field_loaded = 0 sub mfield_adjust # load field from file if field_loaded == 0 array_load(bfield, "bfield.dat") field_loaded = 1 endif # use pa B values if first ion if ion_number == 1 exit endif # assume initially that fields are zero ion_bfieldx_gu = 0 ion_bfieldy_gu = 0 ion_bfieldz_gu = 0 # exit if ion beyond data array limits if ion_px_abs_gu > (x_size - 2) * grid_size exit endif if ion_py_abs_gu > (y_size - 2) * grid_size exit endif x = ion_px_abs_gu / grid_size # convert to data array spacings xint = int(x) # convert to integer and fraction components xfrac = frac(x) xlfrac = 1 - xfrac y = ion_py_abs_gu / grid_size # convert to data array spacings yint = int(y) # convert to integer and fraction components yfrac = frac(y) ylfrac = 1 - yfrac idx = yint * 21 + xint # offset to lower-left (LL) corner point llnbx = idx*2 + 1 # index of LL corner of bx llnby = idx*2 + 2 # index of LL corner of by # calculate ion's B_x field by linear interpolation ion_bfieldx_gu = bfield[llnbx] * xlfrac * ylfrac + bfield[llnbx + 2] * xfrac * ylfrac + bfield[llnbx + x_size*2] * xlfrac * yfrac + bfield[llnbx + x_size*2 + 2] * xfrac * yfrac # calculate ion's B_r field by linear interpolation bfieldr = bfield[llnby] * xlfrac * ylfrac + bfield[llnby + 2] * xfrac * ylfrac + bfield[llnby + x_size*2] * xlfrac * yfrac + bfield[llnby + x_size*2 + 2] * xfrac * yfrac # set field (radius, theta) = rect_to_polar(ion_py_gu, ion_pz_gu) radius = bfieldr (ion_bfieldy_gu, ion_bfieldz_gu) = polar_to_rect(radius, theta) endsub
Listing 6 - bfield.sl - SL program to generate a magnetic field in SIMION
simulation. This is a drop-in replacement for to the bfield.prg program.
Things can be much simpler if the field can be defined exactly by an equation as shown below. In such case, no data interpolation is needed.
sub mfield_adjust
ion_bfieldx_gu = ion_px_gu * 2 + ion_py_gu
ion_bfieldy_gu = ion_px_gu + ion_py_gu * ion_py_gu
ion_bfieldz_gu = 0
endsub
Listing 7 - example SL program for generating a magnetic field
during a SIMION simulation and according to a closed-form equation.
Writing a Field Directly to a *.PA0 FileThe alternate to importing a field using user programs is to create the refined *.PA0 file directly yourself and then read that *.PA0 file into SIMION as normal. This would be the more natural and SIMION-ish solution because you can then fully visualize the potential array even when no ions are flying. However, since a PA file is stored as a bitmap of scalar electrostatic or magnetic potentials--not vector fields--you will have to first compute the scalar potential map corresponding to your field by computing a line integral over vector field. The resultant potential map can then be stored in the *.PA0 file using the PA Tools. This integration step is performed automatically by the "Text --> PA" function in SL Tools. (See p. 2-10 of the printed SIMION manual for further discussion on potentials v.s. fields.)A related solution is to use the "field" method in the SL Libraries to write the field from a general purpose programming language. Here is an example:
use strict;
use SIMION::PA;
#-- create a magnetic field from scratch
my $pa3 = new SIMION::PA(nx => 50, ny => 50, field_type => 'magnetic');
my $z = 0;
for my $x (0..$pa3->nx-1) {
for my $y (0..$pa3->ny-1) {
my $ex = $x;
my $ey = $y**2;
my $ez = 0;
$pa3->field($x, $y, $z, $ex, $ey, $ez);
}}
$pa3->save('mag1.pa');
See the SL Libraries documentation for details since there are some requirements on on how the field is set (the points must be traversed in "lexographic" order). The last two solutions may or may not be more accurate than the first because it relies on SIMION to do the field interpolation near electrode boundaries. The previous bfield.sl program does not (although it could) handle electrode boundaries specially when it implements its own linear interpolation. SIMION's method provides some special handling of electrode boundaries as described on page E-7 of the printed SIMION manual. (If anyone can explain to me what the somewhat ambiguous "If one of the four points..." paragraph on p. E-7 is talking about, I'd be interested in knowing.) ConclusionWe have demonstrated how to export/import the electrostatic/magnetic fields calculated by SIMION to/from an ASCII text file for use in an external program.
(c) 2004 Scientific Instrument
Services, Inc. |
|