isolator.py 2.5 KB
Newer Older
1 2 3 4
"""
Optical components performing directional suppression of beams.
"""

5 6
import logging

7
import numpy as np
8

9
from finesse.components.modal.isolator import (
10
    IsolatorWorkspace
11
)
12 13
from finesse.components.general import Connector, InteractionType
from finesse.components.node import NodeDirection, NodeType
14
from finesse.parameter import model_parameter, Rebuild
15
from finesse.utilities import refractive_index
16 17 18

LOGGER = logging.getLogger(__name__)

Samuel Rowlinson's avatar
Samuel Rowlinson committed
19

20
@model_parameter("S", "Power suppression", 0.0, Rebuild.PlaneWave)
21
class Isolator(Connector):
22
    """Represents an isolator optical component with a suppression factor.
Samuel Rowlinson's avatar
Samuel Rowlinson committed
23

24 25 26 27
    Parameters
    ----------
    name : str
        Name of newly created isolator.
28

29 30 31
    S : float
        Power suppression in dB.
    """
32

33
    def __init__(self, name, S=0.0):
34
        super().__init__(name)
35 36 37

        self.S = S

38
        self._add_port("p1", NodeType.OPTICAL)
Samuel Rowlinson's avatar
Samuel Rowlinson committed
39 40
        self.p1._add_node("i", NodeDirection.INPUT)
        self.p1._add_node("o", NodeDirection.OUTPUT)
41

42
        self._add_port("p2", NodeType.OPTICAL)
Samuel Rowlinson's avatar
Samuel Rowlinson committed
43 44
        self.p2._add_node("i", NodeDirection.INPUT)
        self.p2._add_node("o", NodeDirection.OUTPUT)
45 46

        # optic to optic couplings
Samuel Rowlinson's avatar
Samuel Rowlinson committed
47
        self._register_node_coupling(
48 49 50 51
            "P1i_P2o",
            self.p1.i,
            self.p2.o,
            interaction_type=InteractionType.TRANSMISSION,
Samuel Rowlinson's avatar
Samuel Rowlinson committed
52 53
        )
        self._register_node_coupling(
54 55 56 57
            "P2i_P1o",
            self.p2.i,
            self.p1.o,
            interaction_type=InteractionType.TRANSMISSION,
Samuel Rowlinson's avatar
Samuel Rowlinson committed
58
        )
59

60 61
    def _get_workspace(self, sim):
        _, is_changing = self._eval_parameters()
62
        refill = self in sim.trace_forest.changing_components or len(is_changing)
63 64

        ws = IsolatorWorkspace(self, sim, refill)
65 66 67 68
        # This assumes that nr1/nr2 cannot change during a simulation
        ws.nr1 = refractive_index(self.p1) or 1
        ws.nr2 = refractive_index(self.p2) or 1

Daniel Brown's avatar
Daniel Brown committed
69
        ws.set_fill_function(self._fill_matrix)
70
        return ws
71

72
    def _fill_matrix(self, ws):
73
        values, _ = self._eval_parameters()
Samuel Rowlinson's avatar
Samuel Rowlinson committed
74
        suppression = 10 ** (-values["S"] / 20)
75

76 77
        for freq in ws.sim.frequencies:
            with ws.sim.component_edge_fill3(
78
                ws.owner_id, ws.connections.P1i_P2o_idx, freq.index, freq.index
79
            ) as mat:
80
                mat[:] = ws.K12.data
81 82

            with ws.sim.component_edge_fill3(
83
                ws.owner_id, ws.connections.P2i_P1o_idx, freq.index, freq.index,
84
            ) as mat:
85
                np.multiply(suppression, ws.K21.data, out=mat[:])