Skip to content

CircuitTimeStepper

CircuitTimeStepper(
mesh_refinement: 'PositiveFloat | None' = None,
max_iterations: 'PositiveInt' = 100,
abs_tolerance: 'PositiveFloat' = 1e-08,
rel_tolerance: 'PositiveFloat' = 1e-05,
max_threads: 'PositiveInt' = 8,
verbose: 'bool' = True,
require_native: 'bool' = False,
) -> 'None'

Circuit-level time stepper.

Constructs time steppers for individual circuit elements and handles connections between them. Each time stepper initialization is preceded by an update to the component’s technology, the component itself, and its active model by calling Reference.update. They are reset to their original state afterwards. Reference updates must preserve the parent-visible interface, connectivity, and port-model or terminal-model representation, as described by CircuitModel.

More information on the handling of references and connections can be found CircuitModel.

Args

  • mesh_refinement: Minimum number of mesh elements per wavelength used for mode solving.
  • max_iterations: Maximum number of Newton updates per time step of a zero-delay loop, a group of instances whose declared signal paths (see TimeStepper.path_delays) close within the step. Loops closed through built-in affine steppers are solved exactly with one update; everything outside loops is stepped once, in flow order. 1 steps every instance exactly once and lets loop signals carry the previous time step’s value instead of converging.
  • abs_tolerance: The absolute tolerance for the convergence check.
  • rel_tolerance: The relative tolerance for the convergence check.
  • max_threads: Unused.
  • verbose: Flag setting the verbosity of mode solver runs.
  • require_native: If set, setup fails when any instance steps through Python (see python_instances), and without a PhotonForge Photonic Canvas license.

Setup compiles the circuit into one numba function per circuit structure when config.compile_circuit_time_steppers is set, numba is installed (pip install photonforge[numba]) and native time stepping is licensed (PhotonForge Photonic Canvas); otherwise, or when the circuit is not supported, it is stepped by the built-in C++ kernel with the same results (see compilation). Without the license, the kernel calls every instance through TimeStepper.step_single.

MethodDescription
bind_nativeBind a compiled step function.
resetReset the state of the circuit variables.
setupInitialize the time stepper.
setup_stateInitialize internal circuit variables.
stepCompute the outputs of this time stepper, given inputs.
step_singleTake a single time step on the given inputs.
updateUpdate this time stepper.
write_verilog_aWrite this configured time stepper as one Verilog-A module.

bind_native(self, step, keys, state=None, cstate=None, context=None)

Bind a compiled step function.

Instead of implementing step_single, a time stepper can hand the simulator the address of a C function with the signature:

int64 step(inputs, outputs, time_index, update_state, shutdown,
context, state, cstate)

inputs and outputs are complex128 arrays with one entry per key, state and cstate are the float64 and complex128 arrays, and a nonzero return signals failure. The function must overwrite every element of outputs and only modify the state arrays when update_state is true. The arrays must not be reallocated after binding; reset restores them to the values given here, so a subclass overriding reset must call super().reset().

Calls with update_state false must give the same outputs: circuits may call the function several times in a time step, and setup checks this for steppers that declare path_delays. Random numbers must therefore come from a generator whose state lives in the arrays (e.g., a seed and a counter): output a draw kept there and draw the next one only when update_state is true, which also makes reset replay the stream. Do not use numpy.random in the function: numba draws it from a global stream that differs on every call and survives a reset.

The function can be compiled with numba (when available).

Args

  • step (int | object): Address of the step function, or an object with an address attribute such as a numba cfunc.
  • keys (Sequence[str]): Input/output keys.
  • state (ndarray | None): Contiguous float64 array the function may use.
  • cstate (ndarray | None): Contiguous complex128 array the function may use.
  • context (int | None): Opaque pointer passed to the function.

Example

A two-port element that leaks the field entering its first port out of its second one:

>>> from numba import cfunc
>>> from photonforge.time_steppers import STEP_SIGNATURE
>>>
>>> @cfunc(STEP_SIGNATURE, cache=True) # doctest: +SKIP
... def leaky_step(inputs, outputs, time_index, update_state,
... shutdown, context, state, cstate):
... # state[0]: decay per step
... # cstate[0]: field leaving the second port
... outputs[0] = 0j
... outputs[1] = cstate[0] * state[0] + inputs[0]
... if update_state:
... cstate[0] = outputs[1]
... return 0
...
>>> class LeakyTimeStepper(pf.TimeStepper):
... def __init__(self, *, k=0.5):
... super().__init__(k=k)
...
... def setup_state(self, *, component, time_step, **kwargs):
... keys = tuple(f"{p}@0" for p in sorted(component.ports))
... state = numpy.array([
... self.parametric_kwargs["k"] ** time_step
... ])
... self.bind_native(
... leaky_step, keys, state, numpy.zeros(1, complex)
... )
...
>>> pf.register_time_stepper_class(LeakyTimeStepper)

reset(self) -> 'None'

Reset the state of the circuit variables.

setup(
self,
component,
time_step,
*,
carrier_frequency=0,
show_progress=True,
**kwargs,
)

Initialize the time stepper.

Args

  • component (Component): Component for the time stepper.
  • time_step (float): The interval between time steps (in seconds).
  • carrier_frequency (float): The carrier frequency used to construct the time stepper. The carrier should be omitted from the input signals, as it is handled automatically by the time stepper.
  • show_progress (bool): If True, show setup progress.
  • **kwargs (object): Keyword args forwarded to setup_state.

Returns

TimeStepper: This time stepper.

setup_state(
self,
*,
component: 'Component',
time_step: 'float',
carrier_frequency: 'float',
monitors: 'dict[str, Port | FiberPort | GaussianPort] | None' = None,
updates: 'dict[str | tuple[str | re.Pattern | int | None, ...], dict[str, dict[str, Any]]] | None' = None,
chain_technology_updates: 'bool' = True,
verbose: 'bool | None' = None,
**kwargs: 'object',
) -> 'CircuitTimeStepper'

Initialize internal circuit variables.

Args

  • component: Component for the time stepper.
  • time_step: The interval between time steps (in seconds).
  • carrier_frequency: The carrier frequency used to construct the time stepper. The carrier should be omitted from the input signals, as it is handled automatically by the time stepper.
  • monitors: Additional ports to include in the outputs as a dictionary with monitor names as keys. Subcomponent ports can be obtained with Reference.get_ports for the 1st level of references or with Component.query for more deeply-nested ports.
  • updates: Dictionary of parameter updates to be applied to components, technologies, and models for references within the main component. See CircuitModel.start for examples.
  • chain_technology_updates: if set, a technology update will trigger an update for all components using that technology.
  • verbose: If set, overrides the model’s verbose attribute and is passed to reference models.
  • kwargs: Keyword arguments passed to reference models.

Returns

Object with a status dictionary.

step(self, inputs=None, steps=0, time_step=0, show_progress=True)

Compute the outputs of this time stepper, given inputs.

Args

  • inputs (TimeSeries): Inputs to the time stepper.
  • steps (int): The number of time steps to execute. If inputs is defined, this value is not used.
  • time_step (float): The interval between time steps (in seconds). If inputs is a defined, this value is not used.
  • show_progress (bool): If True, show computation progress.

Returns

TimeSeries: Computed outputs.

step_single(
self,
inputs: 'numpy.ndarray',
outputs: 'numpy.ndarray',
time_index: 'int',
update_state: 'bool',
shutdown: 'bool',
) -> 'None'

Take a single time step on the given inputs.

Args

  • inputs: Input values at the current time step. Must be a 1D array of complex values ordered according to keys.
  • outputs: Pre-allocated output array where results will be stored. Same size and type as inputs.
  • time_index: Time series index for the current input.
  • update_state: Whether to update the internal stepper state.
  • shutdown: Whether this is the last call to the single stepping function for the provided TimeSeries.

update(self, *args, **kwargs)

Update this time stepper.

All contents of the time stepper are updated with the contents from the updated version. Object contents or modifications introduced after the time stepper creation (outside of the original parametric function) are not propagated.

Args

  • *args (object): Positional arguments to the parametric time stepper function.
  • **kwargs (object): Keyword arguments to the parametric time stepper function.

Returns

TimeStepper: This time stepper.

Note

The original keyword arguments used to generate the time stepper are stored and updated with the passed kwargs. This updated version is used in the function call and will be stored for future updates. Positional arguments are not stored.

write_verilog_a(
self,
path,
*,
backend='openvaf',
port_convention='travelling_wave',
module_name=None,
z0=50.0,
field_impedance=None,
)

Write this configured time stepper as one Verilog-A module.

The time stepper must first be configured with setup or Component.setup_time_stepper. The writer creates source only; it does not compile the model or create a simulator deck. Requires a PhotonForge Photonic Canvas license.

Args

  • path (str | os.PathLike): Destination .va file.
  • backend (Literal[“openvaf”, “spectre”]): Compiler capability target recorded in the source.
  • port_convention (Literal[“travelling_wave”, “gf_45spclo_npe”]): External optical port convention. GF packed ports require the Spectre backend.
  • module_name (str | None): Module identifier derived from path when omitted.
  • z0 (float): Travelling-wave optical reference impedance.
  • field_impedance (float | None): GF electric-field scaling.

Returns

pathlib.Path: Absolute destination path.

PropertyDescription
compilationWhether setup compiled the circuit and, if not, why.
evaluationsNumber of instance calls since the last reset.
keysTuple of input/output keys.
path_delaysMinimum delay in time steps from each external input to the outputs it reaches.
python_instancesInstances stepped through Python, as name[index] (class).
silent_outputsExternal outputs that are always zero.
status

Whether setup compiled the circuit and, if not, why.

reason is None when compiled, else "disabled" (config.compile_circuit_time_steppers is off), "license" (no PhotonForge Photonic Canvas license), "numba" (not installed: pip install photonforge[numba]), "python" (an instance steps through Python), "solver" (a Newton loop or a linear loop of more than 16 edges), "factor" (a zero or non-finite mode factor), "budget" (too much generated code) or "codegen" (a compile error, in detail). A compiled circuit also reports compile_seconds, lines and the inlined instances.

Number of instance calls since the last reset.

Tuple of input/output keys.

Minimum delay in time steps from each external input to the outputs it reaches.

Instances stepped through Python, as name[index] (class).

Instances of nested circuits are listed by path. Empty when every instance is native, in which case the circuit steps without the interpreter. Without a PhotonForge Photonic Canvas license, every instance is listed.

External outputs that are always zero.

No description available.

AttributeDescription
parametric_functionstr: Function used to update the time stepper.
parametric_kwargsdict[str, object]: Keyword arguments used to update the time stepper.
propertiesProperties: Object properties.
random_variableslist[RandomVariable]: Random variables associated to the time stepper’s parameters.

str: Function used to update the time stepper.

dict[str, object]: Keyword arguments used to update the time stepper.

Properties: Object properties.

list[RandomVariable]: Random variables associated to the time stepper’s parameters.