Particle Tracking in an Accelerator’s Vacuum Chamber

Cross-section of the APS’s Storage Ring

Introduction

The Advanced Photon Source (APS) is a scientific facility at Argonne National Laboratory, used by over 5,500 scientists annually. It generates ultrabright X-rays, which can be used in the development of robust materials, the advancement of efficient battery technologies, and the research contributing to vaccines and treatments for infectious diseases. The comprehensive upgrade to the facility's electron storage ring, scheduled to begin in April 2024, promises a substantial enhancement in X-ray brightness, reaching up to 500 times its current intensity. This upgrade is poised to unlock novel opportunities for scientific exploration and discoveries.

In a particle accelerator like the APS, the vacuum chamber serves a crucial purpose in maintaining a low-pressure environment by removing air, minimizing collisions between the accelerated particles and gas molecules. This is essential for preserving the beam's stability and preventing energy loss due to interactions with the surrounding medium. The vacuum also helps to minimize scattering, allowing the particles to travel along their intended paths with minimal disruption.

One of my duties as an intern at Argonne National Laboratory was to model the APS’s vacuum chamber and slice that model into layers, generating contour plots. These plots would then be used to simulate particle beam strikes and verify the containment of harmful X-rays. I worked on this project with my mentor at Argonne, John Quintana, Manager of Accelerator and Beamline Engineering.

Problem Statement

Stereolithography (STL) files of the storage ring were provided. These files, however, were not slicable using a 3D printer software such as Meshmixer or Cura. In the model, there were extraneous triangles and surfaces, stemming from water lines and miscellaneous components, meaning that existing slicing programs would not be able to trace out the contour of the vacuum chamber. For an unknown reason, a model of the vacuum chamber by itself does not exist.

An alternative approach was proposed by Dr. Quintana. First, we would generate the contours of the vacuum chamber. Then, the idea was to create vertical slices of the model to generate 2D cross-sections that included other miscellaneous components. By identifying and extruding the outline of the vacuum chamber in each cross-section using OpenSCAD, we aimed to construct a fully connected volume of the vacuum system. This OpenSCAD representation will be subtracted from a large solid, creating a casting with the vacuum volume as a hole. The reason we use OpenSCAD as our modelling software is because it’s scripted-based, meaning that programmers are able to create solid objects by specifying precise points through written code.

This alternative method is designed to create a cleaned-up representation of the vacuum system. The final OpenSCAD result will then be processed through our slicer to obtain closed contours with no irregularities.


Implementation

We adapted a Python library, which computes the planar cross-section of a 3D mesh, represented by a multitude of triangles, to our needs. This open-source implementation of a “mesh cutter” was too time-inefficient, as we needed to slice a very fine model (with roughly half a million triangles). For that reason, we rewrote parts of the cutting algorithm to speed up this process. A simple, interactive graphical user interface was made to choose the slicing plane and display the resulting plot.

 

Cross-section of Original Model

 

As seen in the cross-section above, there are a ton of features that are irrelevant to us, since we only wish to extract the contour of the vacuum chamber. I added a functionality to the UI that gives the user the ability to select points on the contour that are closest to the location they clicked on. These selected points are recorded and can be written as a sequence of lines forming a closed polygon.

def onclick(event):
    global SELECT_POINT_LIST
    global LAST_X_VALUES
    global LAST_Y_VALUES
    with OUTWIDGET:
        print('%s click: button=%d, x=%d, y=%d, xdata=%f, ydata=%f' %
              ('double' if event.dblclick else 'single', event.button,
               event.x, event.y, event.xdata, event.ydata))
        closest_distance_squared = 1e20
        for i in range(len(LAST_X_VALUES)):
            if LAST_X_VALUES[i] != None and LAST_Y_VALUES[i] != None:
                distance_squared = (event.ydata - LAST_Y_VALUES[i])**2 + (event.xdata - LAST_X_VALUES[i])**2
                if distance_squared < closest_distance_squared:
                    closest_distance_squared = distance_squared
                    xdata = LAST_X_VALUES[i]
                    ydata = LAST_Y_VALUES[i]
        SELECT_POINT_LIST.append([xdata,ydata])

def write_point_list_as_polygon(b):
    global SELECT_POINT_LIST    
    with open("polygons.scad","a") as f:
        f.write("// Polygon Created \n")
        f.write("polygon ( points = [\n")
        for point in SELECT_POINT_LIST:
            f.write(f"[ {point[0]} , {point[1]} ],\n")
        f.write(");\n")

The polygon, or sequence of lines, can be copied into the OpenSCAD script to extrude along a path to form a section of the vacuum chamber.

module chamber_segment(y, z, h, dy1, dy2, zoffset) {
    extrude_height = 1.1*h;
    translate([0,y,z-zoffset]) translate([0,0,extrude_height/2])
    rotate([(180/PI)*(dy1-dy2)/h,0,0]) translate([0,0,-extrude_height/2])
    linear_extrude(extrude_height) dlma_bend_chamber_crosssection();
};

module dlma_bend_chamber_crosssection() {
    polygon(points = [
    [ -0.8228347, -4.5668187 ],
    [ -0.8228347, -4.5701227 ],
    [ -0.8228347, -4.5707564 ],
    [ -0.8178569, -4.6085663 ],
    [ -0.8156289, -4.625487 ],
    [ -0.79479724, -4.783718 ],
    ...
    [ -0.9409449, -4.5668187 ],
    [ -0.8418357, -4.5668187 ]]);
}

Extrusion of Polygon Extracted From Cross-section

Simpler sections of the vacuum chamber were constructed from primitive objects such as cylinders and rectangular prisms. The dimensions, positions, and orientations of these geometric shapes were determined by a similar process of visually selecting points on the models’ cross-sections.

module chamber_upper() {
    Z_box_1_end = 4935;
    Z_box_1_start = 4138;
    Z_box_1_length = Z_box_1_end-Z_box_1_start;
    translate([0,0,Z_box_1_start+Z_box_1_length/2]) 
    cube([36.4,12,Z_box_1_length],center=true);

    Z_box_2_end = 5736;
    Z_box_2_start = 4138.9;
    Z_box_2_length = Z_box_2_end-Z_box_2_start;
    translate([0,0,Z_box_2_start+Z_box_2_length/2]) 
    cube([44,12.5,Z_box_2_length],center=true);
};

This work culminated into a complete, isolated model of the vacuum chamber shown below.

Vacuum Chamber CAD


Results

The OpenSCAD model was then exported as an STL file and, once again, run through our mesh cutter program. Clean contours of the vacuum chamber were generated. An example of such a contour, when the model is sliced along the Y=0 plane, is shown below. The red polygons originate from the OpenSCAD model and the blue lines originate from the model of the entire storage ring.

Side-by-side Comparison of Storage Ring and Vacuum Chamber Cross-section

The contours are used to determine if any part of the electron beam could deviate into undesired areas. The method for assessing whether an electron has hit metal is to compute the winding number for the particle coordinates for a series of 2D closed contours. These particle simulations and computations were performed by a colleague and not documented in this article.

Previous
Previous

Formula SAE Suspension

Next
Next

Fruit Ninja Game