Module traceon.solver

The solver module uses the Boundary Element Method (BEM) to compute the surface charge distribution of a given geometry and excitation. Once the surface charge distribution is known, the field at any arbitrary position in space can be calculated by integration over the charged boundary. However, doing a field evaluation in this manner is very slow as for every field evaluation an iteration needs to be done over all elements in the mesh. Especially for particle tracing it is crucial that the field evaluation can be done faster. To achieve this, interpolation techniques can be used, see FieldRadialAxial, and Field3DAxial.

Functions

def solve_direct(excitation)
Expand source code
def solve_direct(excitation):
    """
    Solve for the charges on the surface of the geometry by using a direct method and taking
    into account the specified `excitation`. 

    Parameters
    ----------
    excitation : traceon.excitation.Excitation
        The excitation that produces the resulting field.
     
    Returns
    -------
    `FieldRadialBEM`
    """
    if excitation.mesh.is_2d() and not excitation.mesh.is_higher_order():
        excitation = _excitation_to_higher_order(excitation)
    
    mag, elec = excitation.is_magnetostatic(), excitation.is_electrostatic()

    assert mag or elec, "Solving for an empty excitation"

    if mag and elec:
        elec_field = ElectrostaticSolverRadial(excitation).solve_matrix()[0]
        mag_field = MagnetostaticSolverRadial(excitation).solve_matrix()[0]
        return elec_field + mag_field # type: ignore
    elif elec and not mag:
        return ElectrostaticSolverRadial(excitation).solve_matrix()[0]
    elif mag and not elec:
        return MagnetostaticSolverRadial(excitation).solve_matrix()[0]

Solve for the charges on the surface of the geometry by using a direct method and taking into account the specified excitation.

Parameters

excitation : Excitation
The excitation that produces the resulting field.

Returns

FieldRadialBEM

def solve_direct_superposition(excitation)
Expand source code
def solve_direct_superposition(excitation):
    """
    When using superposition multiple fields are computed at once. Each field corresponds with a unity excitation (1V)
    of an electrode that was assigned a non-zero fixed voltage value. This is useful when a geometry needs
    to be analyzed for many different voltage settings. In this case taking a linear superposition of the returned fields
    allows to select a different voltage 'setting' without inducing any computational cost. There is no computational cost
    involved in using `superposition=True` since a direct solver is used which easily allows for multiple right hand sides (the
    matrix does not have to be inverted multiple times). However, voltage functions are invalid in the superposition process (position dependent voltages).

    Parameters
    ---------------------
    excitation: `traceon.excitation.Excitation`
        The excitation that produces the resulting field.
    
    Returns
    ---------------------------
    Dictionary from str to `traceon.field.Field`. Each key is the name of an electrode on which a voltage (or current) was applied, the corresponding values are the fields.
    """
    if excitation.mesh.is_2d() and not excitation.mesh.is_higher_order():
        excitation = _excitation_to_higher_order(excitation)
    
    # Speedup: invert matrix only once, when using superposition
    electrostatic_excitations, magnetostatic_excitations = excitation._split_for_superposition()
    
    # Solve for elec fields
    elec_names = electrostatic_excitations.keys()
    right_hand_sides = np.array([ElectrostaticSolverRadial(electrostatic_excitations[n]).get_right_hand_side() for n in elec_names])
    solutions = ElectrostaticSolverRadial(excitation).solve_matrix(right_hand_sides)
    elec_dict = {n:s for n, s in zip(elec_names, solutions)}
    
    # Solve for mag fields 
    mag_names = magnetostatic_excitations.keys()
    right_hand_sides = np.array([MagnetostaticSolverRadial(magnetostatic_excitations[n]).get_right_hand_side() for n in mag_names])
    solutions = MagnetostaticSolverRadial(excitation).solve_matrix(right_hand_sides)
    mag_dict = {n:s for n, s in zip(mag_names, solutions)}
        
    return {**elec_dict, **mag_dict}

When using superposition multiple fields are computed at once. Each field corresponds with a unity excitation (1V) of an electrode that was assigned a non-zero fixed voltage value. This is useful when a geometry needs to be analyzed for many different voltage settings. In this case taking a linear superposition of the returned fields allows to select a different voltage 'setting' without inducing any computational cost. There is no computational cost involved in using superposition=True since a direct solver is used which easily allows for multiple right hand sides (the matrix does not have to be inverted multiple times). However, voltage functions are invalid in the superposition process (position dependent voltages).

Parameters

excitation : Excitation
The excitation that produces the resulting field.

Returns

Dictionary from str to Field. Each key is the name of an electrode on which a voltage (or current) was applied, the corresponding values are the fields.