Tracing the beam

In general the Gaussian beam parameter of a \(\M{00}\) mode is changed at every optical surface (see Transformation of the beam parameter). In other words, for each location inside the interferometer where field amplitudes are to be computed a certain beam parameter has to be set for the simulation.

A possible method to find reasonable beam parameters for every location in the interferometer (every node in Finesse) is to first set only some specific beam parameters and then derive the remaining beam parameters from these initial ones: usually it is sensible to assume that the beam at the input can be properly described by the (hopefully known) beam parameter of the laser’s output mode. In addition, in most cavities the light fields can be described safely by using cavity eigenmodes.

Algorithm details

Finesse 3 provides two methods for setting beam parameters at nodes: accessing the OpticalNode.q attribute and adding an instance of a Cavity to a Model instance. These are equivalent to the gauss and cav commands, respectively, in Finesse 2 syntax. When a cavity instance is added to a model the eigenmode of the cavity is computed (if it is stable) and all the respective beam parameters are set on all nodes that are part of the cavity when the tracing step is performed. The behaviour of setting node beam parameter attributes directly is covered in more detail in beam_param_node_usage.

After the model has been informed of any beam parameters to set at nodes, these are then given new/updated entries in the Model.last_trace dictionary upon a call to the beam tracing algorithm of Finesse 3 - Model.beam_trace(). The order in which these are set are as follows:

  • Each entry within the Model.gauss_commands dictionary is used to set the last_trace entries. If the set_symmetric argument of Model.beam_trace() is left as true then another entry for the OpticalNode.opposite instance is created in last_trace where the beam parameter is set to \(-q^*\) where \(q\) is the beam parameter set at the current node (i.e. flipping the sign of the distance to waist part of the beam parameter). Once these parameters are set they will not be overwritten - this means that beam parameters set directly at optical nodes take priority over cavity set nodes.

  • Next the Cavity.source nodes of all cavities in the model are set to the eigenmode of the cavity. Note that if the Cavity.source was set from Model.gauss_commands then this parameter entry will not be overwritten - the gauss command takes precedence.

Once these parameters have been set the core of the beam tracing algorithm is then called to set the beam parameters for the remaining nodes. Tracing in this context means that a beam starting at a node with an already know beam parameter is propagated through the optical system and the beam parameter is transformed according to the optical elements encountered.

The tracing algorithm for Finesse 3 works as follows:

  • the starting point of the tracing can be set explicitly by the user by specifying the startnode parameter of Model.beam_trace() (the beam parameter of the respective node must have been previously set). If no startnode is specified then the starting point of the trace is automatically set:

    • to the Cavity.source node of the first cavity in the order parameter of Model.beam_trace(), or if order has not been specified then to the source node of the first cavity added to the model (if the model contains at least one stable cavity),

    • or to the node corresponding to the first entry of Model.gauss_commands if no cavities have been added to the model.

  • from the starting node the beam is traced through the full optical configuration simply by following all possible paths successively. This is done by moving from the start node to a connecting component then to the next node, to the next component and so on. At every optical element along the path the beam parameter is transformed according to the ABCD matrix of the element. If more than one possibility exists (for example at a beam splitter) the various paths are followed one after the other. Each path ends, i.e. is considered to be traced completely, when any of these conditions are satisfied:

    • all the successor nodes of the current node have already been traced,

    • the next node is connected to a node which was set directly by the user - the tracing is then picked up from that node in order to ensure that no beam parameter change occurs inside Space components,

    • if the current tracing path was started from a user defined beam parameter node and the path has encountered a cavity or the current tracing path was started from a cavity and the path has encounted a different cavity. In this case the tracing algorithm will let that cavity take care of tracing its own nodes from the source of that cavity.

  • if a new node is found that already has a beam parameter, the beam parameter for the current trace path is dropped and the parameter of that node is kept and used for further tracing instead.

  • when all paths have been traced completely, the number of nodes found is compared to the size of the Model.optical_nodes container and a RuntimeError is thrown if these numbers do no match (the error message will display all the nodes for which no beam parameter was set).

As implied previously, all the beam parameters set initially and computed during the trace are stored in the Model.last_trace dictionary. This container is then used in the simulation to compute the field amplitudes for each node.


The animation below demonstrates an example execution of the beam tracing algorithm used by Finesse 3 for the case of a Fabry-Perot optical resonator where a Cavity has been added to the model. A beam parameter is also specified manually at the laser L0. This then shows, visually, how the branch nodes at a beam splitter are handled and also what occurs when a node is encountered which has an associated attached space with a user set node beam parameter at the other end.