SMatrixTimeStepper
SMatrixTimeStepper( pole_residue_matrix: photonforge.PoleResidueMatrix | None = None, pole_residue_reference: Literal['absolute', 'baseband'] = 'baseband', s_matrix_kwargs: dict[str, typing.Any] = {}, carrier_frequency: Annotated[float, minimum=0, units='Hz'] | None = None, initial_poles: collections.abc.Sequence[complex] = (), min_poles: Annotated[int, minimum=0] = 0, max_poles: Annotated[int, minimum=0] = 6, loss_factor: Annotated[float, exclusiveMinimum=0] = 0.001, rms_error_tolerance: Annotated[float, exclusiveMinimum=0] = 0.0001, max_iterations: Annotated[int, exclusiveMinimum=0] = 100, max_stale_iterations: Annotated[int, exclusiveMinimum=0] = 3, passive: bool = True, feedthrough: bool | None = None, delays: Literal['auto'] | Annotated[float, minimum=0, units='s'] | dict[ tuple[str, str], Annotated[float, minimum=0, units='s'] ] = 'auto',) -> NoneTime stepper based on a time-domain model.
The TimeDomainModel can be calculated automatically using
pole_residue_fit and the component’s S matrix or from the
provided PoleResidueMatrix.
Args
- pole_residue_matrix: Pole-residue matrix for the underlying time-domain model. If provided, fitting arguments are not used.
- pole_residue_reference: Frequency reference for an explicitly provided matrix. A
"baseband"matrix is used unchanged, while an"absolute"matrix is shifted to the resolved carrier during setup. - s_matrix_kwargs: Keyword arguments for
Component.s_matrix. - carrier_frequency: Carrier frequency for this stepper. If
None, it is resolved from the circuit: optical references inherit the circuit carrier and electrical references default to0(baseband). - initial_poles: Sequence of poles used as initial guess.
- min_poles: Minimal number of poles to try. It has no effect when initial pole guesses are provided.
- max_poles: Maximal number of poles to try. It has no effect when initial pole guesses are provided.
- loss_factor: For complex initial pole guesses, ratio between their real and imaginary parts.
- rms_error_tolerance: RMS error level to break the fitting loop.
- max_iterations: Maximal number of fitting iterations.
- max_stale_iterations: Maximal number of iterations without error progress.
- passive: Whether to attempt to enforce passivity.
- feedthrough: Whether to include a feedthrough (constant) term in the pole-residue model.
- delays: Time delays (in seconds), one per matrix element. Missing elements have no time delay applied. If a single number is given, this is used as a global delay for all matrix elements. If
"auto", the delays are estimated from the provided data.
Attributes
- pole_residue_matrix: After setup, the stepper’s pole-residue matrix, delays included: the one given, prepared for the carrier, or the fit.
- time_domain_model: After setup, the model stepped:
pole_residue_matrixless the delays thatoutput_delay_stepscarries on the output lines.
Important
Poles, in pole_residue_matrix and initial_poles, follow
the s = -i h f convention of PoleResidueMatrix and
describe the carrier-shifted (envelope) response, except for an
"absolute"-referenced matrix, which is shifted to the carrier
during setup.
Methods
Section titled “Methods”| Method | Description |
|---|---|
bind_native | Bind a compiled step function. |
reset | Reset the state of the internal time domain model and the declared lines. |
setup | Initialize the time stepper. |
setup_state | Initialize internal state, building a time domain model if necessary. |
step | Compute the outputs of this time stepper, given inputs. |
step_single | Take a single time step on the given inputs. |
update | Update this time stepper. |
write_verilog_a | Write this configured time stepper as one Verilog-A module. |
bind_native
Section titled “bind_native”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
addressattribute such as a numbacfunc. - 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) -> NoneReset the state of the internal time domain model and the declared lines.
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
Section titled “setup_state”setup_state( self, *, component: photonforge.Component, time_step: float, carrier_frequency: Annotated[float, minimum=0, units='Hz'] | None = None, frequencies: collections.abc.Sequence[ Annotated[float, minimum=0, units='Hz'] ] | None = None, **kwargs: object,) -> objectInitialize internal state, building a time domain model if necessary.
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.
- frequencies: Frequencies used to build the S matrix for
component, if apole_residue_matrixis not provided. IfNone, one Nyquist band around the carrier, with more points than the default 101 when a model computed in place has a delay the default spacing cannot resolve. Two frequencies near the carrier, within the range of these, are added to the request to measure the delay. - kwargs: Unused.
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
inputsis defined, this value is not used. - time_step (float): The interval between time steps (in seconds). If
inputsis a defined, this value is not used. - show_progress (bool): If
True, show computation progress.
Returns
TimeSeries: Computed outputs.
step_single
Section titled “step_single”step_single( self, inputs: numpy.ndarray, outputs: numpy.ndarray, time_index: int, update_state: bool, shutdown: bool,) -> NoneTake 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
Section titled “update”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
Section titled “write_verilog_a”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
.vafile. - 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
pathwhen omitted. - z0 (float): Travelling-wave optical reference impedance.
- field_impedance (float | None): GF electric-field scaling.
Returns
pathlib.Path: Absolute destination path.
Properties
Section titled “Properties”| Property | Description |
|---|---|
keys | Tuple of input/output keys. |
path_delays | Minimum delay in time steps of each fitted (input, output) path, lines included. |
status |
Tuple of input/output keys.
path_delays
Section titled “path_delays”Minimum delay in time steps of each fitted (input, output) path, lines included.
status
Section titled “status”No description available.
Attributes
Section titled “Attributes”| Attribute | Description |
|---|---|
parametric_function | str: Function used to update the time stepper. |
parametric_kwargs | dict[str, object]: Keyword arguments used to update the time stepper. |
properties | Properties: Object properties. |
random_variables | list[RandomVariable]: Random variables associated to the time stepper’s parameters. |
parametric_function
Section titled “parametric_function”str: Function used to update the time stepper.
parametric_kwargs
Section titled “parametric_kwargs”dict[str, object]: Keyword arguments used to update the time stepper.
properties
Section titled “properties”Properties: Object properties.
random_variables
Section titled “random_variables”list[RandomVariable]: Random variables associated to the time stepper’s parameters.