Ejemplo n.º 1
0
def test_unit_Q_conversion(auxiliary_function):
    results = auxiliary_function(
        E=Q_(1, "lbf/in**2"),
        G_s=Q_(1, "lbf/in**2"),
        rho=Q_(1, "lb/foot**3"),
        L=Q_(1, "inches"),
        idl=Q_(1, "inches"),
        idr=Q_(1, "inches"),
        odl=Q_(1, "inches"),
        odr=Q_(1, "inches"),
        speed=Q_(1, "RPM"),
        frequency=Q_(1, "RPM"),
    )

    # check if all available units are tested
    assert len(results) == len(units)

    E, G_s, rho, L, idl, idr, odl, odr, speed, frequency = results

    assert E == 6894.7572931683635
    assert G_s == 6894.7572931683635
    assert_allclose(rho, 16.01846337396014)
    assert L == 0.0254
    assert idl == 0.0254
    assert idr == 0.0254
    assert odl == 0.0254
    assert odr == 0.0254
    assert speed == 0.10471975511965977
    assert frequency == 0.10471975511965977
Ejemplo n.º 2
0
def test_unit_Q_(auxiliary_function):
    results = auxiliary_function(
        E=Q_(1, "N/m**2"),
        G_s=Q_(1, "N/m**2"),
        rho=Q_(1, "kg/m**3"),
        L=Q_(1, "meter"),
        idl=Q_(1, "meter"),
        idr=Q_(1, "meter"),
        odl=Q_(1, "meter"),
        odr=Q_(1, "meter"),
        speed=Q_(1, "radian/second"),
        frequency=Q_(1, "radian/second"),
    )

    # check if all available units are tested
    assert len(results) == len(units)

    E, G_s, rho, L, idl, idr, odl, odr, speed, frequency = results

    assert E == 1
    assert G_s == 1
    assert rho == 1
    assert L == 1
    assert idl == 1
    assert idr == 1
    assert odl == 1
    assert odr == 1
    assert speed == 1
    assert frequency == 1
Ejemplo n.º 3
0
def cylindrical_units():

    speed = Q_(900, "RPM")
    L = Q_(10.3600055944, "in")

    bearing = THDCylindrical(
        L=L,
        R=0.2,
        c_r=1.95e-4,
        n_theta=11,
        n_z=3,
        n_y=None,
        betha_s=176,
        mu_ref=0.02,
        speed=speed,
        Wx=0,
        Wy=-112814.91,
        k_t=0.15327,
        Cp=1915.24,
        rho=854.952,
        T_reserv=50,
        fat_mixt=[0.52, 0.48],
        T_muI=50,
        T_muF=80,
        mu_I=0.02,
        mu_F=0.01,
        sommerfeld_type=2,
    )

    return bearing
Ejemplo n.º 4
0
def test_unit_Q__pint(auxiliary_function):
    results = auxiliary_function(
        E=Q_(1, "N/m**2"),
        G_s=Q_(1, "N/m**2"),
        rho=Q_(1, "kg/m**3"),
        L=Q_(1, "meter"),
        idl=Q_(1, "meter"),
        idr=Q_(1, "meter"),
        odl=Q_(1, "meter"),
        odr=Q_(1, "meter"),
        speed=Q_(1, "radian/second"),
        frequency=Q_(1, "radian/second"),
    )

    # check if all available units are tested
    assert len(results) == len(units)

    E, G_s, rho, L, idl, idr, odl, odr, speed, frequency = results

    assert E.magnitude == 1
    assert E.units == "newton/meter**2"

    assert G_s.magnitude == 1
    assert G_s.units == "newton/meter**2"

    assert rho.magnitude == 1
    assert rho.units == "kilogram/meter**3"

    assert L.magnitude == 1
    assert L.units == "meter"

    assert idl.magnitude == 1
    assert idl.units == "meter"

    assert idr.magnitude == 1
    assert idr.units == "meter"

    assert odl.magnitude == 1
    assert odl.units == "meter"

    assert odr.magnitude == 1
    assert odr.units == "meter"

    assert speed.magnitude == 1
    assert speed.units == "radian/second"

    assert frequency.magnitude == 1
    assert frequency.units == "radian/second"
Ejemplo n.º 5
0
def test_unit_Q_conversion_pint(auxiliary_function):
    results = auxiliary_function(
        E=Q_(1, "lbf/in**2"),
        G_s=Q_(1, "lbf/in**2"),
        rho=Q_(1, "lb/foot**3"),
        L=Q_(1, "inches"),
        idl=Q_(1, "inches"),
        idr=Q_(1, "inches"),
        odl=Q_(1, "inches"),
        odr=Q_(1, "inches"),
        speed=Q_(1, "RPM"),
        frequency=Q_(1, "RPM"),
    )

    # check if all available units are tested
    assert len(results) == len(units)

    E, G_s, rho, L, idl, idr, odl, odr, speed, frequency = results

    assert E.magnitude == 6894.7572931683635
    assert E.units == "newton/meter**2"

    assert G_s.magnitude == 6894.7572931683635
    assert G_s.units == "newton/meter**2"

    assert_allclose(rho.magnitude, 16.01846337396014)
    assert rho.units == "kilogram/meter**3"

    assert L.magnitude == 0.0254
    assert L.units == "meter"

    assert idl.magnitude == 0.0254
    assert idl.units == "meter"

    assert idr.magnitude == 0.0254
    assert idr.units == "meter"

    assert odl.magnitude == 0.0254
    assert odl.units == "meter"

    assert odr.magnitude == 0.0254
    assert odr.units == "meter"

    assert speed.magnitude == 0.10471975511965977
    assert speed.units == "radian/second"

    assert frequency.magnitude == 0.10471975511965977
    assert frequency.units == "radian/second"
Ejemplo n.º 6
0
def crack_example():
    """Create an example to evaluate the influence of transverse cracks in a rotating shaft.

    This function returns an instance of a transversal crack
    defect. The purpose is to make available a simple model so that a
    doctest can be written using it.

    Returns
    -------
    crack : ross.Crack Object
        An instance of a crack model object.

    Examples
    --------
    >>> crack = crack_example()
    >>> crack.speed
    125.66370614359172
    """

    rotor = base_rotor_example()

    crack = rotor.run_crack(
        dt=0.0001,
        tI=0,
        tF=0.5,
        depth_ratio=0.2,
        n_crack=18,
        speed=Q_(1200, "RPM"),
        unbalance_magnitude=np.array([5e-4, 0]),
        unbalance_phase=np.array([-np.pi / 2, 0]),
        crack_type="Mayes",
        print_progress=False,
    )

    return crack
Ejemplo n.º 7
0
def crack_mayes_units():

    unbalance_magnitudet = Q_(np.array([0.043398083107259365, 0]), "lb*in")
    unbalance_phaset = Q_(np.array([-90.0, 0.0]), "degrees")

    crack = rotor.run_crack(
        dt=0.01,
        tI=0,
        tF=0.5,
        depth_ratio=0.2,
        n_crack=18,
        speed=Q_(1200, "RPM"),
        unbalance_magnitude=unbalance_magnitudet,
        unbalance_phase=unbalance_phaset,
        crack_type="Mayes",
        print_progress=False,
    )

    return crack
Ejemplo n.º 8
0
def rub_units():

    unbalance_magnitudet = Q_(np.array([0.043398083107259365, 0]), "lb*in")
    unbalance_phaset = Q_(np.array([-90.0, 0.0]), "degrees")

    rubbing = rotor.run_rubbing(
        dt=0.001,
        tI=0,
        tF=0.5,
        deltaRUB=7.95e-5,
        kRUB=1.1e6,
        cRUB=40,
        miRUB=0.3,
        posRUB=12,
        speed=Q_(1200, "RPM"),
        unbalance_magnitude=unbalance_magnitudet,
        unbalance_phase=unbalance_phaset,
        print_progress=True,
    )

    return rubbing
Ejemplo n.º 9
0
    def plot_dfft(self,
                  probe,
                  probe_units="rad",
                  range_freq=None,
                  fig=None,
                  **kwargs):
        """"""
        if fig is None:
            fig = go.Figure()

        for i, p in enumerate(probe):
            dofx = p[0] * self.rotor.number_dof
            dofy = p[0] * self.rotor.number_dof + 1
            angle = Q_(p[1], probe_units).to("rad").m

            # fmt: off
            operator = np.array([[np.cos(angle), -np.sin(angle)],
                                 [np.cos(angle), +np.sin(angle)]])
            row, cols = self.response.shape
            _probe_resp = operator @ np.vstack(
                (self.response[dofx, int(2 * cols / 3):],
                 self.response[dofy, int(2 * cols / 3):]))
            probe_resp = (_probe_resp[0] * np.cos(angle)**2 +
                          _probe_resp[1] * np.sin(angle)**2)
            # fmt: on

            amp, freq = self._dfft(probe_resp, self.dt)

            if range_freq is not None:
                amp = amp[(freq >= range_freq[0]) & (freq <= range_freq[1])]

                freq = freq[(freq >= range_freq[0]) & (freq <= range_freq[1])]

            fig.add_trace(
                go.Scatter(
                    x=freq,
                    y=amp,
                    mode="lines",
                    name=f"Probe {i + 1}",
                    legendgroup=f"Probe {i + 1}",
                    showlegend=True,
                    hovertemplate=
                    f"Frequency (Hz): %{{x:.2f}}<br>Amplitude (m): %{{y:.2e}}",
                ))

        fig.update_xaxes(title_text=f"Frequency (Hz)")
        fig.update_yaxes(title_text=f"Amplitude (m)")
        fig.update_layout(**kwargs)

        return fig
Ejemplo n.º 10
0
def misalignment_flex_combined_example():
    """Create an example of a flexible combined misalignment defect.

    This function returns an instance of a flexible combined misalignment
    defect. The purpose is to make available a simple model so that a
    doctest can be written using it.

    Returns
    -------
    misalignment : ross.MisalignmentFlex Object
        An instance of a flexible combined misalignment model object.

    Examples
    --------
    >>> misalignment = misalignment_flex_combined_example()
    >>> misalignment.speed
    125.66370614359172
    """

    rotor = base_rotor_example()

    misalignment = rotor.run_misalignment(
        coupling="flex",
        dt=0.0001,
        tI=0,
        tF=0.5,
        kd=40 * 10**(3),
        ks=38 * 10**(3),
        eCOUPx=2 * 10**(-4),
        eCOUPy=2 * 10**(-4),
        misalignment_angle=5 * np.pi / 180,
        TD=0,
        TL=0,
        n1=0,
        speed=Q_(1200, "RPM"),
        unbalance_magnitude=np.array([5e-4, 0]),
        unbalance_phase=np.array([-np.pi / 2, 0]),
        mis_type="combined",
        print_progress=False,
    )

    return misalignment
Ejemplo n.º 11
0
def cylindrical_bearing_example():
    """Create an example of a cylindrical bearing with termo hydrodynamic effects. This function returns pressure and temperature field and dynamic coefficient. The purpose is to make available a simple model so that a doctest can be written using it.
    Returns
    -------
    THDCylindrical : ross.THDCylindrical Object
        An instance of a termo-hydrodynamic cylendrical bearing model object.
    Examples
    --------
    >>> bearing = cylindrical_bearing_example()
    >>> bearing.L
    0.263144
    """

    bearing = THDCylindrical(
        L=0.263144,
        R=0.2,
        c_r=1.95e-4,
        n_theta=11,
        n_z=3,
        n_y=None,
        betha_s=176,
        mu_ref=0.02,
        speed=Q_(900, "RPM"),
        Wx=0,
        Wy=-112814.91,
        k_t=0.15327,
        Cp=1915.24,
        rho=854.952,
        T_reserv=50,
        fat_mixt=[0.52, 0.48],
        T_muI=50,
        T_muF=80,
        mu_I=0.02,
        mu_F=0.01,
        sommerfeld_type=2,
    )

    return bearing
Ejemplo n.º 12
0
def rubbing_example():
    """Create an example of a rubbing defect.

    This function returns an instance of a rubbing defect. The purpose is to make
    available a simple model so that a doctest can be written using it.

    Returns
    -------
    rubbing : ross.Rubbing Object
        An instance of a rubbing model object.

    Examples
    --------
    >>> rubbing = rubbing_example()
    >>> rubbing.speed
    125.66370614359172
    """

    rotor = base_rotor_example()

    rubbing = rotor.run_rubbing(
        dt=0.0001,
        tI=0,
        tF=0.5,
        deltaRUB=7.95e-5,
        kRUB=1.1e6,
        cRUB=40,
        miRUB=0.3,
        posRUB=12,
        speed=Q_(1200, "RPM"),
        unbalance_magnitude=np.array([5e-4, 0]),
        unbalance_phase=np.array([-np.pi / 2, 0]),
        torque=False,
        print_progress=False,
    )

    return rubbing
Ejemplo n.º 13
0
def misalignment_rigid_example():
    """Create an example of a rigid misalignment defect.

    This function returns an instance of a rigid misalignment
    defect. The purpose is to make available a simple model so that a
    doctest can be written using it.

    Returns
    -------
    misalignment : ross.MisalignmentRigid Object
        An instance of a rigid misalignment model object.

    Examples
    --------
    >>> misalignment = misalignment_rigid_example()
    >>> misalignment.speed
    125.66370614359172
    """

    rotor = base_rotor_example()

    misalignment = rotor.run_misalignment(
        coupling="rigid",
        dt=0.0001,
        tI=0,
        tF=0.5,
        eCOUP=2e-4,
        TD=0,
        TL=0,
        n1=0,
        speed=Q_(1200, "RPM"),
        unbalance_magnitude=np.array([5e-4, 0]),
        unbalance_phase=np.array([-np.pi / 2, 0]),
        print_progress=False,
    )

    return misalignment
Ejemplo n.º 14
0
def test_cylindrical_hydrodynamic():
    cylindrical = CylindricalBearing(
        n=0,
        speed=Q_([1500, 2000], "RPM"),
        weight=525,
        bearing_length=Q_(30, "mm"),
        journal_diameter=Q_(100, "mm"),
        radial_clearance=Q_(0.1, "mm"),
        oil_viscosity=0.1,
    )
    expected_modified_sommerfeld = np.array([1.009798, 1.346397])
    expected_sommerfeld = np.array([3.571429, 4.761905])
    expected_eccentricity = np.array([0.266298, 0.212571])
    expected_attitude_angle = np.array([0.198931, 0.161713])
    expected_k = np.array([[12.80796, 16.393593], [-25.060393, 8.815303]])
    expected_c = np.array([[232.89693, -81.924371], [-81.924371, 294.911619]])
    assert_allclose(
        cylindrical.modified_sommerfeld, expected_modified_sommerfeld, rtol=1e-6
    )
    assert_allclose(cylindrical.sommerfeld, expected_sommerfeld, rtol=1e-6)
    assert_allclose(cylindrical.eccentricity, expected_eccentricity, rtol=1e-5)
    assert_allclose(cylindrical.attitude_angle, expected_attitude_angle, rtol=1e-5)
    assert_allclose(cylindrical.K(Q_(1500, "RPM")) / 1e6, expected_k, rtol=1e-6)
    assert_allclose(cylindrical.C(Q_(1500, "RPM")) / 1e3, expected_c, rtol=1e-6)
Ejemplo n.º 15
0
def test_unit_Q_(auxiliary_function):
    results = auxiliary_function(
        E=Q_(1, "N/m**2"),
        G_s=Q_(1, "N/m**2"),
        rho=Q_(1, "kg/m**3"),
        L=Q_(1, "meter"),
        idl=Q_(1, "meter"),
        idr=Q_(1, "meter"),
        odl=Q_(1, "meter"),
        odr=Q_(1, "meter"),
        speed=Q_(1, "radian/second"),
        frequency=Q_(1, "radian/second"),
        m=Q_(1, "kg"),
        mx=Q_(1, "kg"),
        my=Q_(1, "kg"),
        Ip=Q_(1, "kg*m**2"),
        Id=Q_(1, "kg*m**2"),
        width=Q_(1, "meter"),
        depth=Q_(1, "meter"),
        i_d=Q_(1, "meter"),
        o_d=Q_(1, "meter"),
        kxx=Q_(1, "N/m"),
        kxy=Q_(1, "N/m"),
        kxz=Q_(1, "N/m"),
        kyx=Q_(1, "N/m"),
        kyy=Q_(1, "N/m"),
        kyz=Q_(1, "N/m"),
        kzx=Q_(1, "N/m"),
        kzy=Q_(1, "N/m"),
        kzz=Q_(1, "N/m"),
        cxx=Q_(1, "N*s/m"),
        cxy=Q_(1, "N*s/m"),
        cxz=Q_(1, "N*s/m"),
        cyx=Q_(1, "N*s/m"),
        cyy=Q_(1, "N*s/m"),
        cyz=Q_(1, "N*s/m"),
        czx=Q_(1, "N*s/m"),
        czy=Q_(1, "N*s/m"),
        czz=Q_(1, "N*s/m"),
        unbalance_magnitude=Q_(1, "kg*m"),
        unbalance_phase=Q_(1, "rad"),
    )

    # check if all available units are tested
    assert len(results) == len(units)
    # fmt: off
    (E, G_s, rho, L, idl, idr, odl, odr, speed, frequency, m, mx, my, Ip, Id,
     width, depth, i_d, o_d, kxx, kxy, kxz, kyx, kyy, kyz, kzx, kzy, kzz, cxx, cxy,
     cxz, cyx, cyy, cyz, czx, czy, czz, unbalance_magnitude, unbalance_phase) = results
    # fmt: on

    assert E == 1
    assert G_s == 1
    assert rho == 1
    assert L == 1
    assert idl == 1
    assert idr == 1
    assert odl == 1
    assert odr == 1
    assert speed == 1
    assert frequency == 1
    assert m == 1
    assert mx == 1
    assert my == 1
    assert Ip == 1
    assert Id == 1
    assert width == 1
    assert depth == 1
    assert i_d == 1
    assert o_d == 1
    assert kxx == 1
    assert kxy == 1
    assert kxz == 1
    assert kyx == 1
    assert kyy == 1
    assert kyz == 1
    assert kzx == 1
    assert kzy == 1
    assert kzz == 1
    assert cxx == 1
    assert cxy == 1
    assert cxz == 1
    assert cyx == 1
    assert cyy == 1
    assert cyz == 1
    assert czx == 1
    assert czy == 1
    assert czz == 1
    unbalance_magnitude == 1
    unbalance_phase == 1
Ejemplo n.º 16
0
def test_new_units_loaded():
    speed = Q_(1, "RPM")
    assert speed.magnitude == 1
Ejemplo n.º 17
0
def test_units_pickle():
    speed = Q_(1, "RPM")
    speed_pickled = pickle.loads(pickle.dumps(speed))
    assert speed == speed_pickled
Ejemplo n.º 18
0
def test_unit_Q_conversion(auxiliary_function):
    results = auxiliary_function(
        E=Q_(1, "lbf/in**2"),
        G_s=Q_(1, "lbf/in**2"),
        rho=Q_(1, "lb/foot**3"),
        L=Q_(1, "inches"),
        idl=Q_(1, "inches"),
        idr=Q_(1, "inches"),
        odl=Q_(1, "inches"),
        odr=Q_(1, "inches"),
        speed=Q_(1, "RPM"),
        frequency=Q_(1, "RPM"),
        m=Q_(1, "lb"),
        mx=Q_(1, "lb"),
        my=Q_(1, "lb"),
        Ip=Q_(1, "lb*in**2"),
        Id=Q_(1, "lb*in**2"),
        width=Q_(1, "inches"),
        depth=Q_(1, "inches"),
        i_d=Q_(1, "inches"),
        o_d=Q_(1, "inches"),
        kxx=Q_(1, "lbf/in"),
        kxy=Q_(1, "lbf/in"),
        kxz=Q_(1, "lbf/in"),
        kyx=Q_(1, "lbf/in"),
        kyy=Q_(1, "lbf/in"),
        kyz=Q_(1, "lbf/in"),
        kzx=Q_(1, "lbf/in"),
        kzy=Q_(1, "lbf/in"),
        kzz=Q_(1, "lbf/in"),
        cxx=Q_(1, "lbf*s/in"),
        cxy=Q_(1, "lbf*s/in"),
        cxz=Q_(1, "lbf*s/in"),
        cyx=Q_(1, "lbf*s/in"),
        cyy=Q_(1, "lbf*s/in"),
        cyz=Q_(1, "lbf*s/in"),
        czx=Q_(1, "lbf*s/in"),
        czy=Q_(1, "lbf*s/in"),
        czz=Q_(1, "lbf*s/in"),
        unbalance_magnitude=Q_(1, "lb*in"),
        unbalance_phase=Q_(1, "deg"),
    )

    # check if all available units are tested
    assert len(results) == len(units)

    # fmt: off
    (E, G_s, rho, L, idl, idr, odl, odr, speed, frequency, m, mx, my, Ip, Id,
     width, depth, i_d, o_d, kxx, kxy, kxz, kyx, kyy, kyz, kzx, kzy, kzz, cxx, cxy,
     cxz, cyx, cyy, cyz, czx, czy, czz, unbalance_magnitude, unbalance_phase) = results
    # fmt: on

    assert E == 6894.7572931683635
    assert G_s == 6894.7572931683635
    assert_allclose(rho, 16.01846337396014)
    assert L == 0.0254
    assert idl == 0.0254
    assert idr == 0.0254
    assert odl == 0.0254
    assert odr == 0.0254
    assert speed == 0.10471975511965977
    assert frequency == 0.10471975511965977
    assert m == 0.4535923700000001
    assert mx == 0.4535923700000001
    assert my == 0.4535923700000001
    assert Ip == 0.0002926396534292
    assert Id == 0.0002926396534292
    assert width == 0.0254
    assert depth == 0.0254
    assert i_d == 0.0254
    assert o_d == 0.0254
    assert kxx == 175.12683524647645
    assert kxy == 175.12683524647645
    assert kxz == 175.12683524647645
    assert kyx == 175.12683524647645
    assert kyy == 175.12683524647645
    assert kyz == 175.12683524647645
    assert kzx == 175.12683524647645
    assert kzy == 175.12683524647645
    assert kzz == 175.12683524647645
    assert cxx == 175.12683524647645
    assert cxy == 175.12683524647645
    assert cxz == 175.12683524647645
    assert cyx == 175.12683524647645
    assert cyy == 175.12683524647645
    assert cyz == 175.12683524647645
    assert czx == 175.12683524647645
    assert czy == 175.12683524647645
    assert czz == 175.12683524647645
    assert unbalance_magnitude == 0.011521246198000002
    assert unbalance_phase == 0.017453292519943295
Ejemplo n.º 19
0
def test_unit_Q_conversion(auxiliary_function):
    kwargs = {k: Q_(v.single_value, v.other_unit) for k, v in arguments.items()}
    results = auxiliary_function(**kwargs)
    results_dict = {k: v for k, v in zip(arguments.keys(), results)}
    for arg, actual in results_dict.items():
        assert_allclose(actual, arguments[arg].expected_converted_value)
Ejemplo n.º 20
0
def test_new_units_loaded():
    speed = Q_(1, "RPM")
    assert speed.m == 1
    # check if h is hour instead of planck constant
    v = Q_(3600, "m/h")
    assert v.to("m/s").m == 1
Ejemplo n.º 21
0
    def plot_dfft(self,
                  probe,
                  probe_units="rad",
                  range_freq=None,
                  fig=None,
                  **kwargs):
        """Plot response in frequency domain (dFFT - discrete Fourier Transform) using Plotly.

        Parameters
        ----------
        probe : list of tuples
            List with tuples (node, orientation angle, tag).
            node : int
                indicate the node where the probe is located.
            orientation : float
                probe orientation angle about the shaft. The 0 refers to +X direction.
            tag : str, optional
                probe tag to be displayed at the legend.
        probe_units : str, option
            Units for probe orientation.
            Default is "rad".
        range_freq : list, optional
            Units for the x axis.
            Default is "Hz"
        fig : Plotly graph_objects.Figure()
            The figure object with the plot.
        kwargs : optional
            Additional key word arguments can be passed to change the plot layout only
            (e.g. width=1000, height=800, ...).
            *See Plotly Python Figure Reference for more information.

        Returns
        -------
        fig : Plotly graph_objects.Figure()
            The figure object with the plot.
        """
        if fig is None:
            fig = go.Figure()

        for i, p in enumerate(probe):
            dofx = p[0] * self.rotor.number_dof
            dofy = p[0] * self.rotor.number_dof + 1
            angle = Q_(p[1], probe_units).to("rad").m

            # fmt: off
            operator = np.array([[np.cos(angle), -np.sin(angle)],
                                 [np.cos(angle), +np.sin(angle)]])
            row, cols = self.response.shape
            _probe_resp = operator @ np.vstack(
                (self.response[dofx, int(2 * cols / 3):],
                 self.response[dofy, int(2 * cols / 3):]))
            probe_resp = (_probe_resp[0] * np.cos(angle)**2 +
                          _probe_resp[1] * np.sin(angle)**2)
            # fmt: on

            amp, freq = self._dfft(probe_resp, self.dt)

            if range_freq is not None:
                amp = amp[(freq >= range_freq[0]) & (freq <= range_freq[1])]

                freq = freq[(freq >= range_freq[0]) & (freq <= range_freq[1])]

            fig.add_trace(
                go.Scatter(
                    x=freq,
                    y=amp,
                    mode="lines",
                    name=f"Probe {i + 1} - Node {p[0]}",
                    legendgroup=f"Probe {i + 1} - Node {p[0]}",
                    showlegend=True,
                    hovertemplate=
                    f"Frequency (Hz): %{{x:.2f}}<br>Amplitude (m): %{{y:.2e}}",
                ))

        fig.update_xaxes(title_text=f"Frequency (Hz)")
        fig.update_yaxes(title_text=f"Amplitude (m)")
        fig.update_layout(**kwargs)

        return fig