Repository: ross-rotordynamics/ross
Pull request #625 (2020-07-10 19:51:32)

Replace interp1d by line_shape from Plotly
It removes the need of creating sub arrays from interpolation to smooth some results in StaticResults.


Patch:
diff --git a/.travis.yml b/.travis.yml
index 19007d1f..8ef5671a 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -11,7 +11,7 @@ install:
 - pip install -e .[dev]
 before_script:
 - black --check ross
-- isort ross --check-only
+- isort --recursive ross --check-only
 script:
 - pytest ross --cov=ross
 after_success:
diff --git a/ross/__init__.py b/ross/__init__.py
index cb5f67bf..bed038f3 100644
--- a/ross/__init__.py
+++ b/ross/__init__.py
@@ -1,5 +1,6 @@
 __version__ = "0.3.3"
-from plotly import io as _pio
+
+import plotly.io as _pio
 
 import ross.plotly_theme
 
diff --git a/ross/api_report.py b/ross/api_report.py
index 883ffc38..dc63f8f1 100644
--- a/ross/api_report.py
+++ b/ross/api_report.py
@@ -3,8 +3,8 @@ from copy import copy, deepcopy
 
 import numpy as np
 import pandas as pd
-from plotly import express as px
-from plotly import graph_objects as go
+import plotly.express as px
+import plotly.graph_objects as go
 from plotly.subplots import make_subplots
 from scipy.interpolate import interp1d
 from scipy.signal import argrelextrema
diff --git a/ross/bearing_seal_element.py b/ross/bearing_seal_element.py
index 072f355c..c53715aa 100644
--- a/ross/bearing_seal_element.py
+++ b/ross/bearing_seal_element.py
@@ -10,9 +10,9 @@ import warnings
 from pathlib import Path
 
 import numpy as np
+import plotly.graph_objects as go
+import scipy.interpolate as interpolate
 import toml
-from plotly import graph_objects as go
-from scipy import interpolate as interpolate
 
 from ross.element import Element
 from ross.fluid_flow import fluid_flow as flow
diff --git a/ross/config.py b/ross/config.py
deleted file mode 100644
index f0024716..00000000
--- a/ross/config.py
+++ /dev/null
@@ -1,471 +0,0 @@
-"""Rotordynamic Report Configuration File."""
-import black
-
-__all__ = ["Config"]
-
-
-class _Dict:
-    """Set keys and values as attribute for the Config object.
-
-    Subclass to organize nested dictionaries and set each key / value as attribute for
-    the config object.
-
-    Return
-    ------
-    A dictionary as attribute for the Config() object.
-
-    Examples
-    --------
-    >>> param = _Dict({
-    ...     "stiffness_range": None,
-    ...     "num": 30,
-    ...     "num_modes": 16,
-    ...     "synchronous": False,
-    ... })
-    >>> param.num
-    30
-    """
-
-    def __init__(self, dictionary):
-        for k, v in dictionary.items():
-            if isinstance(v, dict):
-                setattr(self, k, self.__class__(v))
-            else:
-                setattr(self, k, v)
-
-    def __repr__(self):
-        """Return a string representation for the dict attribute.
-
-        This method uses Black code formatting for better visualization.
-
-        Returns
-        -------
-        A string representation for the dictionary options.
-
-        Examples
-        --------
-        >>> param = _Dict({
-        ...     "oper_clearance": None,
-        ...     "min_clearance": None,
-        ...     "max_clearance": None,
-        ... })
-        >>> param # doctest: +ELLIPSIS
-        {"oper_clearance": None, "min_clearance": None, "max_clearance": None}...
-        """
-        return black.format_file_contents(
-            repr(self.__dict__), fast=True, mode=black.FileMode()
-        )
-
-    def __getitem__(self, option):
-        """Return the value for a given option from the dictionary.
-
-        Parameters
-        ----------
-        option : str
-            A dictionary key corresponding to config options as string.
-
-        Raises
-        ------
-        KeyError
-            Raises an error if the parameter doesn't belong to the dictionary.
-
-        Returns
-        -------
-        Return the value for the given key.
-
-        Examples
-        --------
-        >>> param = _Dict({
-        ...     "stiffness_range": None,
-        ...     "num": 30,
-        ...     "num_modes": 16,
-        ...     "synchronous": False,
-        ... })
-        >>> param["num"]
-        30
-        """
-        if option not in self.__dict__.keys():
-            raise KeyError("Option '{}' not found.".format(option))
-
-        return self.__dict__[option]
-
-    def _update(self, **kwargs):
-        """Update the dict values.
-
-        This is an axuliar method for Config.update_config() to set new values for the
-        config dictionary according to kwargs input.
-        The kwargs must respect Config attributes. It's only possible to update
-        existing values from Config dictionary.
-        **See Config attributes reference for infos about the dict options.
-
-        Parameters
-        ----------
-        **kwargs : dict
-            Dictionary with new values for corresponding keys.
-
-        Raises
-        ------
-        KeyError
-            Raises an error if the parameter doesn't belong to the dictionary.
-
-        Examples
-        --------
-        >>> param = _Dict({
-        ...     "stiffness_range": None,
-        ...     "num": 30,
-        ...     "num_modes": 16,
-        ...     "synchronous": False,
-        ... })
-        >>> param._update(num=20, num_modes=10)
-        >>> param # doctest: +ELLIPSIS
-        {"stiffness_range": None, "num": 20, "num_modes": 10, "synchronous": False}...
-        """
-        for k, v in kwargs.items():
-            if k not in self.__dict__.keys():
-                raise KeyError("Option '{}' not found.".format(k))
-
-            if isinstance(v, dict):
-                getattr(self, k)._update(**v)
-            else:
-                self.__dict__[k] = v
-
-
-class Config:
-    """Configurate parameters for rotordynamic report.
-
-    This class generates an object with several preset parameters to run the
-    rotordynamics analyses. It's a must to check all the options for a correct
-    functioning.
-
-    The attributes are automatically generated and it's not possible to remove then or
-    add new ones.
-
-    Attributes
-    ----------
-    rotor_properties : dict
-        Dictionary of rotor properties.
-
-        rotor_speeds : dict
-            Dictionary indicating the operational speeds which will be used in the
-            analyses.
-
-            min_speed : float
-                The machine minimum operational speed.
-            max_speed : float
-                The machine  maximum operational speed.
-            oper_speed : float
-                The machine  nominal operational speed.
-            trip_speed : float
-                The machine overspeed trip.
-            speed_factor : float
-                Multiplicative factor of the speed range - according to API 684.
-                Default is 1.50.
-            unit : str
-                Unit system to speed values. Options: "rad/s", "rpm".
-                Default is "rpm".
-
-        rotor_id : dict
-            Dictionary with rotor identifications.
-
-            type : str
-                Machine type: Options are: "compressor", "turbine", "axial_flow". Each
-                options has it's own considerations (according to API 684). If a different
-                option is input, it will be the software will treat as a "compressor".
-            tag : str
-                Tag for the rotor. If None, it'll copy the tag from rotor object.
-
-    bearings : dict
-        The analyses consider different configurations for the bearings. It should be done
-        for minimum, maximum and the nominal clearance.
-
-        oper_clearance : list
-            List of bearing elements. The coefficients should be calculated for the nominal
-            clearance.
-        min_clearance : list
-            List of bearing elements. The coefficients should be calculated for the minimum
-            clearance.
-        max_clearance : list
-            List of bearing elements. The coefficients should be calculated for the maximum
-            clearance.
-
-    run_campbell : dict
-        Dictionary configurating run_campbell parameters.
-
-        speed_range : list, array
-            Array with the speed range.
-        num_modes : float
-            Number of frequencies that will be calculated.
-            Default is 6.
-
-    plot_ucs : dict
-        Dictionary configurating plot_ucs parameters.
-
-        stiffness_range : tuple, optional
-            Tuple with (start, end) for stiffness range.
-        num : int
-            Number of steps in the range.
-            Default is 30.
-        num_modes : int, optional
-            Number of modes to be calculated.
-            Default is 16.
-        synchronous : bool
-            If True a synchronous analysis is carried out and the frequency of
-            the first forward model will be equal to the speed.
-            Default is False.
-
-    run_unbalance_response : dict
-        Dictionary configurating run_unbalance_response parameters.
-
-        probes : dict
-            Dictionary with the node where the probe is set and its respective
-            orientation angle.
-
-            node : list
-                List with the nodes where probes are located.
-            orientation : list
-                List with the respective orientation angle for the probes.
-                0 or π (rad) corresponds to the X orientation and
-                π / 2 or 3 * π / 2 (rad) corresponds to the Y orientation.
-            unit : str
-                Unit system for the orientation angle. Can be "rad" or "degree".
-                Default is "rad".
-
-        frequency_range : list, array
-            Array with the desired range of frequencies. If None and cluster_points is
-            False, it creates an array from 0 to the max continuos speed times the
-            speed_factor.
-            If None and cluster_points is True, it creates and automatic array based on
-            the number of modes selected.
-            Default is None with cluster_points False.
-        modes : list, optional
-            Modes that will be used to calculate the frequency response
-            (all modes will be used if a list is not given).
-        cluster_points : bool, optional
-            Boolean to activate the automatic frequency spacing method. If True, the
-            method uses _clustering_points() to create an speed_range.
-            Default is False
-        num_points : int, optional
-            The number of points generated per critical speed.
-            The method set the same number of points for slightly less and slightly
-            higher than the natural circular frequency. It means there'll be num_points
-            greater and num_points smaller than a given critical speed.
-            num_points may be between 2 and 12. Anything above this range defaults
-            to 10 and anything below this range defaults to 4.
-            The default is 10.
-        num_modes
-            The number of eigenvalues and eigenvectors to be calculated using ARPACK.
-            It also defines the range for the output array, since the method generates
-            points only for the critical speed calculated by Rotor.run_critical_speed().
-            Default is 12.
-        rtol : float, optional
-            Tolerance (relative) for termination. Applied to scipy.optimize.newton to
-            calculate the approximated critical speeds.
-            Default is 0.005 (0.5%).
-
-    stability_level1 : dict
-        Dictionary configurating stability_level_1 parameters.
-
-        D : list, array
-            Impeller diameter, m (in.) or Blade pitch diameter, m (in.).
-            The disk elements order must be observed to input this list.
-        H : list, array
-            Minimum diffuser width per impeller, m (in.) or Effective blade height, m (in.).
-            The disk elements order must be observed to input this list.
-        rated_power : list
-            Rated power per stage/impeller, W (HP),
-            The disk elements order must be observed to input this list.
-        rho_ratio : list
-            Density ratio between the discharge gas density and the suction
-            gas density per impeller, kg/m3 (lbm/in.3),
-            The disk elements order must be observed to input this list.
-        rho_suction : float
-            Suction gas density in the first stage, kg/m3 (lbm/in.3).
-        rho_discharge : float
-            Discharge gas density in the last stage, kg/m3 (lbm/in.3),
-        unit: str, optional
-            Unit system. Options are "m" (meter) and "in" (inch).
-            Default is "m".
-
-    Returns
-    -------
-    A config object to rotordynamic report.
-
-    Examples
-    --------
-    There are two possible syntax to return the options setup. One is using the
-    object.attribute syntax and the other is the dicionary syntax
-
-    First syntax opion:
-    >>> configs = Config()
-    >>> configs.rotor_properties.rotor_id # doctest: +ELLIPSIS
-    {"type": "compressor", "tag": None}...
-
-    Second syntax opion:
-    >>> configs = Config()
-    >>> configs["rotor_properties"]["rotor_id"] # doctest: +ELLIPSIS
-    {"type": "compressor", "tag": None}...
-    """
-
-    def __init__(self):
-        # fmt: off
-        # Configurating rotor properties
-        self.rotor_properties = _Dict({
-            "rotor_speeds": {
-                "min_speed": None,
-                "max_speed": None,
-                "oper_speed": None,
-                "trip_speed": None,
-                "speed_factor": 1.50,
-                "unit": "rpm",
-            },
-            "rotor_id": {
-                "type": "compressor",
-                "tag": None
-            },
-        })
-
-        # Configurating bearing elements for diferent clearances
-        self.bearings = _Dict({
-            "oper_clearance": None,
-            "min_clearance": None,
-            "max_clearance": None,
-        })
-
-        # Configurating campbell options
-        self.run_campbell = _Dict({
-            "speed_range": None,
-            "num_modes": 6,
-        })
-
-        # Configurating UCS options
-        self.plot_ucs = _Dict({
-            "stiffness_range": None,
-            "num": 30,
-            "num_modes": 16,
-            "synchronous": False,
-        })
-
-        # Configurating unbalance response options
-        self.run_unbalance_response = _Dict({
-            "probes": {
-                "node": None,
-                "orientation": None,
-                "unit": "rad",
-            },
-            "frequency_range": None,
-            "modes": None,
-            "cluster_points": False,
-            "num_modes": 12,
-            "num_points": 10,
-            "rtol": 0.005,
-        })
-
-        # Configurating stability level 1 analysis
-        self.stability_level1 = _Dict({
-            "D": None,
-            "H": None,
-            "rated_power": None,
-            "rho_ratio": None,
-            "rho_suction": None,
-            "rho_discharge": None,
-            "unit": "m",
-        })
-        # fmt: on
-
-    def __repr__(self):
-        """Return a string representation for the config options.
-
-        This method uses Black code formatting for better visualization.
-
-        Returns
-        -------
-        A string representation for the config dictionary.
-
-        Examples
-        --------
-        >>> configs = Config()
-        >>> configs # doctest: +ELLIPSIS
-        {
-            "rotor_properties": {
-                "rotor_speeds": {
-                    "min_speed": None,
-                    "max_speed": None,
-                    "oper_speed": None...
-        """
-        return black.format_file_contents(
-            repr(self.__dict__), fast=True, mode=black.FileMode()
-        )
-
-    def __getitem__(self, option):
-        """Return the value for a given option from config dictionary.
-
-        Parameters
-        ----------
-        option : str
-            A dictionary key corresponding to config options as string.
-
-        Raises
-        ------
-        KeyError
-            Raises an error if the parameter doesn't belong to the dictionary.
-
-        Returns
-        -------
-        Return the value for the given key.
-
-        Examples
-        --------
-        >>> configs = Config()
-        >>> configs["bearings"] # doctest: +ELLIPSIS
-        {"oper_clearance": None, "min_clearance": None, "max_clearance": None}...
-        """
-        if option not in self.__dict__.keys():
-            raise KeyError("Option '{}' not found.".format(option))
-
-        return self.__dict__[option]
-
-    def update_config(self, **kwargs):
-        """Update the config options.
-
-        This method set new values for the config dictionary according to kwargs input.
-        The kwargs must respect Config attributes. It's only possible to update
-        existing values from Config dictionary.
-        **See Config attributes reference for infos about the dict options.
-
-        Parameters
-        ----------
-        **kwargs : dict
-            Dictionary with new values for corresponding keys.
-
-        Raises
-        ------
-        KeyError
-            Raises an error if the parameter doesn't belong to the dictionary.
-
-        Examples
-        --------
-        >>> configs = Config()
-        >>> configs.update_config(
-        ...     rotor_properties=dict(
-        ...         rotor_speeds=dict(min_speed=1000.0, max_speed=10000.0),
-        ...         rotor_id=dict(type="turbine", tag="Model"),
-        ...     )
-        ... )
-        >>> configs.rotor_properties # doctest: +ELLIPSIS
-        {
-            "rotor_speeds": {
-                "min_speed": 1000.0,
-                "max_speed": 10000.0,
-                "oper_speed": None,
-                "trip_speed": None,
-                "speed_factor": 1.5,
-                "unit": "rpm",
-            },
-            "rotor_id": {"type": "turbine", "tag": "Model"},
-        }...
-        """
-        for k, v in kwargs.items():
-            if k not in self.__dict__.keys():
-                raise KeyError("Option '{}' not found.".format(k))
-            else:
-                getattr(self, k)._update(**v)
diff --git a/ross/disk_element.py b/ross/disk_element.py
index bb5eb025..235c56ee 100644
--- a/ross/disk_element.py
+++ b/ross/disk_element.py
@@ -8,8 +8,8 @@ import os
 from pathlib import Path
 
 import numpy as np
+import plotly.graph_objects as go
 import toml
-from plotly import graph_objects as go
 
 from ross.element import Element
 from ross.units import check_units
diff --git a/ross/fluid_flow/fluid_flow.py b/ross/fluid_flow/fluid_flow.py
index 8371e3cc..e3bb5265 100644
--- a/ross/fluid_flow/fluid_flow.py
+++ b/ross/fluid_flow/fluid_flow.py
@@ -32,6 +32,8 @@ class FluidFlow:
         Number of points along the Z direction (direction of flow).
     ntheta: int
         Number of points along the direction theta. NOTE: ntheta must be odd.
+    nradius: int
+        Number of points along the direction r.
     length: float
         Length in the Z direction (m).
 
@@ -89,11 +91,13 @@ class FluidFlow:
     dtheta: float
         Range size in the theta direction.
     ntotal: int
-        Number of nodes in the grid., ntheta, n_interv_z, n_interv_theta,
+        Number of nodes in the grid., ntheta, nradius, n_interv_z, n_interv_theta,
     n_interv_z: int
         Number of intervals on Z.
     n_interv_theta: int
       Number of intervals on theta.
+    n_interv_radius: int
+        Number of intervals on r.
     p_mat_analytical : array of shape (nz, ntheta)
         The analytical pressure matrix.
     p_mat_numerical : array of shape (nz, ntheta)
@@ -110,6 +114,8 @@ class FluidFlow:
         The external radius in each position of the grid.
     ri : array of shape (nz, ntheta)
         The internal radius in each position of the grid.
+    z_list : array of shape (1, nz)
+        z along the object. It goes from 0 to lb.
     xre : array of shape (nz, ntheta)
         x value of the external radius.
     xri : array of shape (nz, ntheta)
@@ -118,11 +124,6 @@ class FluidFlow:
         y value of the external radius.
     yri : array of shape (nz, ntheta)
         y value of the internal radius.
-    z_list : array of shape (1, nz)
-        z along the object. It goes from 0 to lb.
-    gama : array of shape (nz, ntheta)
-        Points along the object in the tangential direction.
-        It ranges from 0 to 2 pi, starting at the largest spacing between rotor and stator.
     t : float
         Time.
     xp : float
@@ -155,6 +156,7 @@ class FluidFlow:
     >>> import numpy as np
     >>> nz = 8
     >>> ntheta = 64
+    >>> nradius = 8
     >>> length = 0.01
     >>> omega = 100.*2*np.pi/60
     >>> p_in = 0.
@@ -165,7 +167,7 @@ class FluidFlow:
     >>> density = 860.
     >>> eccentricity = 0.001
     >>> attitude_angle = np.pi
-    >>> my_fluid_flow = flow.FluidFlow(nz, ntheta, length,
+    >>> my_fluid_flow = flow.FluidFlow(nz, ntheta, nradius, length,
     ...                                omega, p_in, p_out, radius_rotor,
     ...                                radius_stator, viscosity, density,
     ...                                attitude_angle=attitude_angle, eccentricity=eccentricity,
@@ -185,6 +187,7 @@ class FluidFlow:
         self,
         nz,
         ntheta,
+        nradius,
         length,
         omega,
         p_in,
@@ -203,8 +206,10 @@ class FluidFlow:
             sys.exit("Either load or eccentricity must be given.")
         self.nz = nz
         self.ntheta = ntheta
+        self.nradius = nradius
         self.n_interv_z = nz - 1
         self.n_interv_theta = ntheta - 1
+        self.n_interv_radius = nradius - 1
         self.length = length
         self.ltheta = 2.0 * np.pi
         self.dz = length / self.n_interv_z
@@ -264,18 +269,21 @@ class FluidFlow:
         self.yi = self.eccentricity * np.sin(3 * np.pi / 2 + self.attitude_angle)
         self.re = np.zeros([self.nz, self.ntheta])
         self.ri = np.zeros([self.nz, self.ntheta])
+        self.z_list = np.zeros(self.nz)
         self.xre = np.zeros([self.nz, self.ntheta])
         self.xri = np.zeros([self.nz, self.ntheta])
         self.yre = np.zeros([self.nz, self.ntheta])
         self.yri = np.zeros([self.nz, self.ntheta])
-        self.z_list = np.zeros(self.nz)
-        self.gama = np.zeros([self.nz, self.ntheta])
-        self.t = 0
-        self.xp = 0
-        self.yp = 0
         self.p_mat_analytical = np.zeros([self.nz, self.ntheta])
+        self.c1 = np.zeros([self.nz, self.ntheta])
+        self.c2 = np.zeros([self.nz, self.ntheta])
+        self.c0w = np.zeros([self.nz, self.ntheta])
+        self.M = np.zeros([self.ntotal, self.ntotal])
+        self.f = np.zeros([self.ntotal, 1])
+        self.P = np.zeros([self.ntotal, 1])
         self.p_mat_numerical = np.zeros([self.nz, self.ntheta])
-        self.geometry_description()
+        self.gama = np.zeros([self.nz, self.ntheta])
+        self.calculate_coefficients()
         self.analytical_pressure_matrix_available = False
         self.numerical_pressure_matrix_available = False
         self.calculate_pressure_matrix_numerical()
@@ -311,19 +319,19 @@ class FluidFlow:
                 for i in range(0, self.nz):
                     for j in range(0, self.ntheta):
                         # fmt: off
-                        self.p_mat_analytical[i, j] = (
+                        self.p_mat_analytical[i][j] = (
                                 ((-3 * self.viscosity * self.omega) / self.radial_clearance ** 2) *
                                 ((i * self.dz - (self.length / 2)) ** 2 - (self.length ** 2) / 4) *
                                 (self.eccentricity_ratio * np.sin(j * self.dtheta)) /
                                 (1 + self.eccentricity_ratio * np.cos(j * self.dtheta)) ** 3)
                         # fmt: on
-                        if self.p_mat_analytical[i, j] < 0:
-                            self.p_mat_analytical[i, j] = 0
+                        if self.p_mat_analytical[i][j] < 0:
+                            self.p_mat_analytical[i][j] = 0
             elif method == 1:
                 for i in range(0, self.nz):
                     for j in range(0, self.ntheta):
                         # fmt: off
-                        self.p_mat_analytical[i, j] = (3 * self.viscosity / ((self.radial_clearance ** 2) *
+                        self.p_mat_analytical[i][j] = (3 * self.viscosity / ((self.radial_clearance ** 2) *
                                                                              (1. + self.eccentricity_ratio * np.cos(
                                                                                  j * self.dtheta)) ** 3)) * \
                                                       (-self.eccentricity_ratio * self.omega * np.sin(
@@ -331,18 +339,18 @@ class FluidFlow:
                                                       (((i * self.dz - (self.length / 2)) ** 2) - (
                                                               self.length ** 2) / 4)
                         # fmt: on
-                        if self.p_mat_analytical[i, j] < 0:
-                            self.p_mat_analytical[i, j] = 0
+                        if self.p_mat_analytical[i][j] < 0:
+                            self.p_mat_analytical[i][j] = 0
         elif self.bearing_type == "long_bearing" or force_type == "long":
             if method == 0:
                 for i in range(0, self.nz):
                     for j in range(0, self.ntheta):
-                        self.p_mat_analytical[i, j] = (
+                        self.p_mat_analytical[i][j] = (
                             (
                                 6
                                 * self.viscosity
                                 * self.omega
-                                * (self.radius_rotor / self.radial_clearance) ** 2
+                                * (self.ri[i][j] / self.radial_clearance) ** 2
                                 * self.eccentricity_ratio
                                 * np.sin(self.dtheta * j)
                                 * (
@@ -360,8 +368,8 @@ class FluidFlow:
                             )
                             + self.p_in
                         )
-                        if self.p_mat_analytical[i, j] < 0:
-                            self.p_mat_analytical[i, j] = 0
+                        if self.p_mat_analytical[i][j] < 0:
+                            self.p_mat_analytical[i][j] = 0
         elif self.bearing_type == "medium_size":
             raise ValueError(
                 "The pressure matrix for a bearing that is neither short or long can only be calculated "
@@ -371,209 +379,158 @@ class FluidFlow:
         self.analytical_pressure_matrix_available = True
         return self.p_mat_analytical
 
-    def geometry_description(self):
-        """This function calculates the geometry description.
-        It is executed when the class is instantiated.
-        Examples
-        --------
-        >>> my_fluid_flow = fluid_flow_example()
-        >>> my_fluid_flow.geometry_description()
-        """
-        for i in range(0, self.nz):
-            zno = i * self.dz
-            self.z_list[i] = zno
-            for j in range(0, self.ntheta):
-                # fmt: off
-                self.gama[i, j] = j * self.dtheta + np.pi / 2 + self.attitude_angle
-                [radius_external, self.xre[i, j], self.yre[i, j]] = \
-                    external_radius_function(self.gama[i, j], self.radius_stator)
-                [radius_internal, self.xri[i, j], self.yri[i, j]] = \
-                    internal_radius_function(self.gama[i, j], self.attitude_angle, self.radius_rotor,
-                                             self.eccentricity)
-                self.re[i, j] = radius_external
-                self.ri[i, j] = radius_internal
-                # fmt: on
-
     def calculate_coefficients(self, direction=None):
         """This function calculates the constants that form the Poisson equation
         of the discrete pressure (central differences in the second
-        derivatives).
-        Parameters
-        ----------
-        direction: str
-            If defined, it calculates the model based on the disturbance in the chosen direction: 'x' or 'y'.
-        Returns
+        derivatives). It is executed when the class is instantiated.
+        Examples
         --------
-        c1, c2, c0w: matrix of float
-            Constants that form the Poisson equation.
         >>> my_fluid_flow = fluid_flow_example()
-        >>> my_fluid_flow.calculate_coefficients()# doctest: +ELLIPSIS
-        (array([[...
+        >>> my_fluid_flow.calculate_coefficients()
+        >>> my_fluid_flow.c0w # doctest: +ELLIPSIS
+        array([[...
         """
-        c1 = np.zeros([self.nz, self.ntheta])
-        c2 = np.zeros([self.nz, self.ntheta])
-        c0w = np.zeros([self.nz, self.ntheta])
-
         for i in range(0, self.nz):
+            zno = i * self.dz
+            self.z_list[i] = zno
             eccentricity_error = False
             for j in range(0, self.ntheta):
                 # fmt: off
+                self.gama[i][j] = j * self.dtheta + np.pi / 2 + self.attitude_angle
+                [radius_external, self.xre[i][j], self.yre[i][j]] = \
+                    external_radius_function(self.gama[i][j], self.radius_stator)
+                [radius_internal, self.xri[i][j], self.yri[i][j]] = \
+                    internal_radius_function(self.gama[i][j], self.attitude_angle, self.radius_rotor,
+                                             self.eccentricity)
+                self.re[i][j] = radius_external
+                self.ri[i][j] = radius_internal
 
                 w = self.omega * self.radius_rotor
 
-                k = (self.re[i, j] ** 2 * (np.log(self.re[i, j]) - 1 / 2) - self.ri[i, j] ** 2 *
-                     (np.log(self.ri[i, j]) - 1 / 2)) / (self.ri[i, j] ** 2 - self.re[i, j] ** 2)
-
-                c1[i, j] = (1 / (4 * self.viscosity)) * ((self.re[i, j] ** 2 * np.log(self.re[i, j]) -
-                                                               self.ri[i, j] ** 2 * np.log(self.ri[i, j]) +
-                                                               (self.re[i, j] ** 2 - self.ri[i, j] ** 2) *
-                                                               (k - 1)) - 2 * self.re[i, j] ** 2 * (
-                                                                      (np.log(self.re[i, j]) + k - 1 / 2) * np.log(
-                                                                       self.re[i, j] / self.ri[i, j])))
-
-                c2[i, j] = (- self.ri[i, j] ** 2) / (8 * self.viscosity) * \
-                                ((self.re[i, j] ** 2 - self.ri[i, j] ** 2 -
-                                  (self.re[i, j] ** 4 - self.ri[i, j] ** 4) /
-                                  (2 * self.ri[i, j] ** 2)) +
-                                 ((self.re[i, j] ** 2 - self.ri[i, j] ** 2) /
-                                  (self.ri[i, j] ** 2 *
-                                   np.log(self.re[i, j] / self.ri[i, j]))) *
-                                 (self.re[i, j] ** 2 * np.log(self.re[i, j] / self.ri[i, j]) -
-                                  (self.re[i, j] ** 2 - self.ri[i, j] ** 2) / 2))
-
-                c0w[i, j] = (- w * self.ri[i, j] *
-                                  (np.log(self.re[i, j] / self.ri[i, j]) *
-                                   (1 + (self.ri[i, j] ** 2) / (self.re[i, j] ** 2 - self.ri[i, j] ** 2)) - 1 / 2))
+                k = (self.re[i][j] ** 2 * (np.log(self.re[i][j]) - 1 / 2) - self.ri[i][j] ** 2 *
+                     (np.log(self.ri[i][j]) - 1 / 2)) / (self.ri[i][j] ** 2 - self.re[i][j] ** 2)
+
+                self.c1[i][j] = (1 / (4 * self.viscosity)) * ((self.re[i][j] ** 2 * np.log(self.re[i][j]) -
+                                                               self.ri[i][j] ** 2 * np.log(self.ri[i][j]) +
+                                                               (self.re[i][j] ** 2 - self.ri[i][j] ** 2) *
+                                                               (k - 1)) - 2 * self.re[i][j] ** 2 * (
+                                                                      (np.log(self.re[i][j]) + k - 1 / 2) * np.log(
+                                                                       self.re[i][j] / self.ri[i][j])))
+
+                self.c2[i][j] = (- self.ri[i][j] ** 2) / (8 * self.viscosity) * \
+                                ((self.re[i][j] ** 2 - self.ri[i][j] ** 2 -
+                                  (self.re[i][j] ** 4 - self.ri[i][j] ** 4) /
+                                  (2 * self.ri[i][j] ** 2)) +
+                                 ((self.re[i][j] ** 2 - self.ri[i][j] ** 2) /
+                                  (self.ri[i][j] ** 2 *
+                                   np.log(self.re[i][j] / self.ri[i][j]))) *
+                                 (self.re[i][j] ** 2 * np.log(self.re[i][j] / self.ri[i][j]) -
+                                  (self.re[i][j] ** 2 - self.ri[i][j] ** 2) / 2))
+
+                self.c0w[i][j] = (- w * self.ri[i][j] *
+                                  (np.log(self.re[i][j] / self.ri[i][j]) *
+                                   (1 + (self.ri[i][j] ** 2) / (self.re[i][j] ** 2 - self.ri[i][j] ** 2)) - 1 / 2))
                 if direction == "x":
-                    a = self.omegap * self.xp * np.cos(self.omegap * self.t)
-                    c0w[i, j] += self.ri[i, j] * a * np.sin(self.gama[i, j])
+                    a = self.omegap * (self.xp) * np.cos(self.omegap * self.t)
+                    self.c0w[i][j] += self.ri[i][j] * a * np.sin(self.gama[i][j])
                 elif direction == "y":
-                    b = self.omegap * self.yp * np.cos(self.omegap * self.t)
-                    c0w[i, j] -= self.ri[i, j] * b * np.cos(self.gama[i, j])
+                    b = self.omegap * (self.yp) * np.cos(self.omegap * self.t)
+                    self.c0w[i][j] -= self.ri[i][j] * b * np.cos(self.gama[i][j])
                 else:
-                    c0w[i, j] += 0
+                    self.c0w[i][j] += 0
                 # fmt: on
                 if not eccentricity_error:
-                    if abs(self.xri[i, j]) > abs(self.xre[i, j]) or abs(
-                        self.yri[i, j]
-                    ) > abs(self.yre[i, j]):
+                    if abs(self.xri[i][j]) > abs(self.xre[i][j]) or abs(
+                        self.yri[i][j]
+                    ) > abs(self.yre[i][j]):
                         eccentricity_error = True
             if eccentricity_error:
                 raise ValueError(
                     "Error: The given parameters create a rotor that is not inside the stator. "
                     "Check parameters and fix accordingly."
                 )
-        return c1, c2, c0w
 
-    def mounting_matrix(self, c1, c2, c0w):
+    def mounting_matrix(self):
         """This function assembles the matrix M and the independent vector f.
-        Parameters
-        ----------
-        c1, c2, c0w: matrix of float
-            Constants that form the Poisson equation.
-        Returns
-        --------
-        M: matrix of float
-            Matrix composed of coefficients that multiply the pressures at each point in the discrete domain.
-        f: array of float
-            Pressure independent terms.
         Examples
         --------
         >>> my_fluid_flow = fluid_flow_example()
-        >>> c1, c2, c0w = my_fluid_flow.calculate_coefficients()
-        >>> my_fluid_flow.mounting_matrix(c1, c2, c0w)# doctest: +ELLIPSIS
-        (array([[...
+        >>> my_fluid_flow.mounting_matrix()
+        >>> my_fluid_flow.M # doctest: +ELLIPSIS
+        array([[...
         """
         # fmt: off
-        M = np.zeros([self.ntotal, self.ntotal])
-        f = np.zeros([self.ntotal, 1])
         count = 0
         for x in range(self.ntheta):
-            M[count, count] = 1
-            f[count, 0] = self.p_in
+            self.M[count][count] = 1
+            self.f[count][0] = self.p_in
             count = count + self.nz - 1
-            M[count, count] = 1
-            f[count, 0] = self.p_out
+            self.M[count][count] = 1
+            self.f[count][0] = self.p_out
             count = count + 1
         count = 0
         for x in range(self.nz - 2):
-            M[self.ntotal - self.nz + 1 + count, 1 + count] = 1
-            M[self.ntotal - self.nz + 1 + count, self.ntotal - self.nz + 1 + count] = -1
+            self.M[self.ntotal - self.nz + 1 + count][1 + count] = 1
+            self.M[self.ntotal - self.nz + 1 + count][self.ntotal - self.nz + 1 + count] = -1
             count = count + 1
         count = 1
         j = 0
         for i in range(1, self.nz - 1):
-            a = (1 / self.dtheta ** 2) * (c1[i, self.ntheta - 1])
-            M[count, self.ntotal - 2 * self.nz + count] = a
-            b = (1 / self.dz ** 2) * (c2[i - 1, j])
-            M[count, count - 1] = b
-            c = -((1 / self.dtheta ** 2) * ((c1[i, j]) + c1[i, self.ntheta - 1])
-                  + (1 / self.dz ** 2) * (c2[i, j] + c2[i - 1, j]))
-            M[count, count] = c
-            d = (1 / self.dz ** 2) * (c2[i, j])
-            M[count, count + 1] = d
-            e = (1 / self.dtheta ** 2) * (c1[i, j])
-            M[count, count + self.nz] = e
+            a = (1 / self.dtheta ** 2) * (self.c1[i][self.ntheta - 1])
+            self.M[count][self.ntotal - 2 * self.nz + count] = a
+            b = (1 / self.dz ** 2) * (self.c2[i - 1, j])
+            self.M[count][count - 1] = b
+            c = -((1 / self.dtheta ** 2) * ((self.c1[i][j]) + self.c1[i][self.ntheta - 1])
+                  + (1 / self.dz ** 2) * (self.c2[i][j] + self.c2[i - 1][j]))
+            self.M[count, count] = c
+            d = (1 / self.dz ** 2) * (self.c2[i][j])
+            self.M[count][count + 1] = d
+            e = (1 / self.dtheta ** 2) * (self.c1[i][j])
+            self.M[count][count + self.nz] = e
             count = count + 1
         count = self.nz + 1
         for j in range(1, self.ntheta - 1):
             for i in range(1, self.nz - 1):
-                a = (1 / self.dtheta ** 2) * (c1[i, j - 1])
-                M[count, count - self.nz] = a
-                b = (1 / self.dz ** 2) * (c2[i - 1, j])
-                M[count, count - 1] = b
-                c = -((1 / self.dtheta ** 2) * ((c1[i, j]) + c1[i, j - 1])
-                      + (1 / self.dz ** 2) * (c2[i, j] + c2[i - 1, j]))
-                M[count, count] = c
-                d = (1 / self.dz ** 2) * (c2[i, j])
-                M[count, count + 1] = d
-                e = (1 / self.dtheta ** 2) * (c1[i, j])
-                M[count, count + self.nz] = e
+                a = (1 / self.dtheta ** 2) * (self.c1[i, j - 1])
+                self.M[count][count - self.nz] = a
+                b = (1 / self.dz ** 2) * (self.c2[i - 1][j])
+                self.M[count][count - 1] = b
+                c = -((1 / self.dtheta ** 2) * ((self.c1[i][j]) + self.c1[i][j - 1])
+                      + (1 / self.dz ** 2) * (self.c2[i][j] + self.c2[i - 1][j]))
+                self.M[count, count] = c
+                d = (1 / self.dz ** 2) * (self.c2[i][j])
+                self.M[count][count + 1] = d
+                e = (1 / self.dtheta ** 2) * (self.c1[i][j])
+                self.M[count][count + self.nz] = e
                 count = count + 1
             count = count + 2
         count = 1
         for j in range(self.ntheta - 1):
             for i in range(1, self.nz - 1):
                 if j == 0:
-                    f[count, 0] = (c0w[i, j] - c0w[i, self.ntheta - 1]) / self.dtheta
+                    self.f[count][0] = (self.c0w[i][j] - self.c0w[i][self.ntheta - 1]) / self.dtheta
                 else:
-                    f[count, 0] = (c0w[i, j] - c0w[i, j - 1]) / self.dtheta
+                    self.f[count][0] = (self.c0w[i, j] - self.c0w[i, j - 1]) / self.dtheta
                 count = count + 1
             count = count + 2
         # fmt: on
-        return M, f
 
-    def resolves_matrix(self, M, f):
+    def resolves_matrix(self):
         """This function resolves the linear system [M]{P} = {f}.
-         Parameters
-        ----------
-        M: matrix of float
-            Matrix composed of coefficients that multiply the pressures at each point in the discrete domain.
-        f: array of float
-            Pressure independent terms.
-        Returns
-        --------
-        P: array of floats
-            Pressure. Unknowns of the finite difference system.
         Examples
         --------
         >>> my_fluid_flow = fluid_flow_example()
-        >>> c1, c2, c0w = my_fluid_flow.calculate_coefficients()
-        >>> M, f = my_fluid_flow.mounting_matrix(c1, c2, c0w)
-        >>> my_fluid_flow.resolves_matrix(M, f)# doctest: +ELLIPSIS
+        >>> my_fluid_flow.mounting_matrix()
+        >>> my_fluid_flow.resolves_matrix()
+        >>> my_fluid_flow.P # doctest: +ELLIPSIS
         array([[...
         """
-        sparse_matrix = sp.sparse.csc_matrix(M)
-        P = sp.sparse.linalg.spsolve(sparse_matrix, f)
-        P.shape = (P.size, 1)
-        return P
+        sparse_matrix = sp.sparse.csc_matrix(self.M)
+        self.P = sp.sparse.linalg.spsolve(sparse_matrix, self.f)
+        self.P.shape = (self.P.size, 1)
 
-    def calculate_pressure_matrix_numerical(self, direction=None):
+    def calculate_pressure_matrix_numerical(self):
         """This function calculates the pressure matrix numerically.
-        Parameters
-        ----------
-        direction: str
-            If defined, it calculates the model based on the disturbance in the chosen direction: 'x' or 'y'.
         Returns
         -------
         p_mat_numerical: matrix of float
@@ -584,21 +541,15 @@ class FluidFlow:
         >>> my_fluid_flow.calculate_pressure_matrix_numerical() # doctest: +ELLIPSIS
         array([[...
         """
-        if direction == "x":
-            c1, c2, c0w = self.calculate_coefficients(direction="x")
-        elif direction == "y":
-            c1, c2, c0w = self.calculate_coefficients(direction="y")
-        else:
-            c1, c2, c0w = self.calculate_coefficients()
-        M, f = self.mounting_matrix(c1, c2, c0w)
-        P = self.resolves_matrix(M, f)
+        self.mounting_matrix()
+        self.resolves_matrix()
         for i in range(self.nz):
             for j in range(self.ntheta):
                 k = j * self.nz + i
-                if P[k] < 0:
-                    self.p_mat_numerical[i, j] = 0
+                if self.P[k] < 0:
+                    self.p_mat_numerical[i][j] = 0
                 else:
-                    self.p_mat_numerical[i, j] = P[k]
+                    self.p_mat_numerical[i][j] = self.P[k]
         self.numerical_pressure_matrix_available = True
         return self.p_mat_numerical
 
@@ -624,6 +575,7 @@ def fluid_flow_example():
     my_pressure_matrix = FluidFlow(
         nz=8,
         ntheta=32,
+        nradius=8,
         length=0.04,
         omega=100.0 * 2 * np.pi / 60,
         p_in=0.0,
@@ -659,6 +611,7 @@ def fluid_flow_example2():
     """
     nz = 8
     ntheta = 16
+    nradius = 8
     length = 0.03
     omega = 157.1
     p_in = 0.0
@@ -671,6 +624,7 @@ def fluid_flow_example2():
     return FluidFlow(
         nz,
         ntheta,
+        nradius,
         length,
         omega,
         p_in,
diff --git a/ross/fluid_flow/fluid_flow_coefficients.py b/ross/fluid_flow/fluid_flow_coefficients.py
index 9813904c..e3c20087 100644
--- a/ross/fluid_flow/fluid_flow_coefficients.py
+++ b/ross/fluid_flow/fluid_flow_coefficients.py
@@ -197,8 +197,8 @@ def calculate_stiffness_and_damping_coefficients(fluid_flow_object):
             * fluid_flow_object.xp
             * np.cos(fluid_flow_object.omegap * fluid_flow_object.t)
         )
-        fluid_flow_object.geometry_description()
-        fluid_flow_object.calculate_pressure_matrix_numerical(direction="x")
+        fluid_flow_object.calculate_coefficients(direction="x")
+        fluid_flow_object.calculate_pressure_matrix_numerical()
         [
             radial_force[i],
             tangential_force[i],
@@ -217,8 +217,8 @@ def calculate_stiffness_and_damping_coefficients(fluid_flow_object):
             * fluid_flow_object.yp
             * np.cos(fluid_flow_object.omegap * fluid_flow_object.t)
         )
-        fluid_flow_object.geometry_description()
-        fluid_flow_object.calculate_pressure_matrix_numerical(direction="y")
+        fluid_flow_object.calculate_coefficients(direction="y")
+        fluid_flow_object.calculate_pressure_matrix_numerical()
         [
             radial_force[i],
             tangential_force[i],
@@ -226,7 +226,7 @@ def calculate_stiffness_and_damping_coefficients(fluid_flow_object):
             force_yy[i],
         ] = calculate_oil_film_force(fluid_flow_object, force_type="numerical")
         move_rotor_center(fluid_flow_object, 0, -delta_y)
-        fluid_flow_object.geometry_description()
+        fluid_flow_object.calculate_coefficients()
         fluid_flow_object.calculate_pressure_matrix_numerical()
 
         X1[i] = [1, dx[i], xdot[i]]
diff --git a/ross/fluid_flow/fluid_flow_graphics.py b/ross/fluid_flow/fluid_flow_graphics.py
index c19849f7..69d69be7 100644
--- a/ross/fluid_flow/fluid_flow_graphics.py
+++ b/ross/fluid_flow/fluid_flow_graphics.py
@@ -1,5 +1,5 @@
 import numpy as np
-from plotly import graph_objects as go
+import plotly.graph_objects as go
 
 from ross.plotly_theme import tableau_colors
 
@@ -394,7 +394,11 @@ def plot_pressure_theta_cylindrical(
         else:
             p_mat = fluid_flow_object.p_mat_numerical
 
-    r = np.linspace(fluid_flow_object.radius_rotor, fluid_flow_object.radius_stator)
+    r = np.linspace(
+        fluid_flow_object.radius_rotor,
+        fluid_flow_object.radius_stator,
+        fluid_flow_object.nradius,
+    )
     theta = np.linspace(
         0.0, 2.0 * np.pi + fluid_flow_object.dtheta / 2, fluid_flow_object.ntheta
     )
diff --git a/ross/plotly_theme.py b/ross/plotly_theme.py
index d0d3ba6e..b038bf47 100644
--- a/ross/plotly_theme.py
+++ b/ross/plotly_theme.py
@@ -1,5 +1,5 @@
-from plotly import graph_objects as go
-from plotly import io as pio
+import plotly.graph_objects as go
+import plotly.io as pio
 
 # tableau colors
 tableau_colors = {
diff --git a/ross/point_mass.py b/ross/point_mass.py
index 8452e3e8..e2360c75 100644
--- a/ross/point_mass.py
+++ b/ross/point_mass.py
@@ -6,8 +6,8 @@ import os
 from pathlib import Path
 
 import numpy as np
+import plotly.graph_objects as go
 import toml
-from plotly import graph_objects as go
 
 from ross.element import Element
 from ross.units import check_units
diff --git a/ross/results.py b/ross/results.py
index c68c2329..bf7d75fc 100644
--- a/ross/results.py
+++ b/ross/results.py
@@ -5,10 +5,10 @@ This module returns graphs for each type of analyses in rotor_assembly.py.
 import copy
 
 import numpy as np
-from plotly import graph_objects as go
+import plotly.graph_objects as go
+import scipy.linalg as la
 from plotly.subplots import make_subplots
 from scipy import interpolate
-from scipy import linalg as la
 
 from ross.plotly_theme import tableau_colors
 
@@ -2072,18 +2072,14 @@ class StaticResults:
         for deformation, Vx, Bm, nodes, nodes_pos, Vx_axis in zip(
             self.deformation, self.Vx, self.Bm, self.nodes, self.nodes_pos, self.Vx_axis
         ):
-            interpolated = interpolate.interp1d(nodes_pos, deformation, kind="cubic")
-            xnew = np.linspace(
-                nodes_pos[0], nodes_pos[-1], num=len(nodes_pos) * 20, endpoint=True
-            )
-
-            ynew = interpolated(xnew)
 
             fig.add_trace(
                 go.Scatter(
-                    x=xnew,
-                    y=ynew,
+                    x=nodes_pos,
+                    y=deformation,
                     mode="lines",
+                    line_shape="spline",
+                    line_smoothing=1.0,
                     name=f"Shaft {count}",
                     showlegend=True,
                     hovertemplate=(
@@ -2352,6 +2348,8 @@ class StaticResults:
                     x=nodes_pos,
                     y=Bm,
                     mode="lines",
+                    line_shape="spline",
+                    line_smoothing=1.0,
                     name=f"Shaft {j}",
                     legendgroup=f"Shaft {j}",
                     showlegend=True,
diff --git a/ross/rotor_assembly.py b/ross/rotor_assembly.py
index a1caedb3..74adcbcf 100644
--- a/ross/rotor_assembly.py
+++ b/ross/rotor_assembly.py
@@ -8,18 +8,18 @@ from copy import copy, deepcopy
 from itertools import chain, cycle
 from pathlib import Path
 
+import matplotlib.pyplot as plt
 import numpy as np
 import pandas as pd
+import plotly.express as px
+import plotly.graph_objects as go
+import scipy.io as sio
+import scipy.linalg as la
+import scipy.signal as signal
+import scipy.sparse.linalg as las
 import toml
-from matplotlib import pyplot as plt
-from plotly import express as px
-from plotly import graph_objects as go
-from scipy import io as sio
-from scipy import linalg as la
-from scipy import signal as signal
 from scipy.interpolate import UnivariateSpline
 from scipy.optimize import newton
-from scipy.sparse import linalg as las
 
 from ross.bearing_seal_element import (BallBearingElement, BearingElement,
                                        BearingElement6DoF,
@@ -1043,7 +1043,7 @@ class Rotor(object):
         >>> rotor = rotor_example()
         >>> speed_range = rotor._clustering_points(num_modes=12, num_points=5)
         >>> speed_range.shape
-        (61,)
+        (60,)
         """
         critical_speeds = self.run_critical_speed(num_modes=num_modes, rtol=rtol)
         omega = critical_speeds.wd
@@ -1067,7 +1067,6 @@ class Rotor(object):
 
         omega = omega.reshape((len(omega), 1))
         speed_range = np.sort(np.ravel(np.concatenate((omega / a, omega * a))))
-        speed_range = np.insert(speed_range, 0, 0)
 
         return speed_range
 
@@ -1354,7 +1353,7 @@ class Rotor(object):
 
         >>> response = rotor.run_freq_response(cluster_points=True, num_points=5)
         >>> response.speed_range.shape
-        (61,)
+        (60,)
 
         # plot frequency response function:
         >>> fig = response.plot(inp=13, out=13)
@@ -1469,7 +1468,7 @@ class Rotor(object):
         ...     force=force, cluster_points=True, num_modes=12, num_points=5
         ... )
         >>> response.speed_range.shape
-        (61,)
+        (60,)
         """
         if speed_range is None:
             if cluster_points:
@@ -1634,7 +1633,7 @@ class Rotor(object):
         ...     node=3, magnitude=0.01, phase=0.0, cluster_points=True, num_points=5
         ... )
         >>> response2.speed_range.shape
-        (61,)
+        (60,)
 
         plot unbalance response:
         >>> fig = response.plot(dof=13)
diff --git a/ross/shaft_element.py b/ross/shaft_element.py
index eb44c9ac..8ba9f7c4 100644
--- a/ross/shaft_element.py
+++ b/ross/shaft_element.py
@@ -8,8 +8,8 @@ import os
 from pathlib import Path
 
 import numpy as np
+import plotly.graph_objects as go
 import toml
-from plotly import graph_objects as go
 
 from ross.element import Element
 from ross.materials import Material, steel
diff --git a/ross/stochastic/st_results.py b/ross/stochastic/st_results.py
index c18ae745..ca1e4e21 100644
--- a/ross/stochastic/st_results.py
+++ b/ross/stochastic/st_results.py
@@ -3,9 +3,9 @@
 This module returns graphs for each type of analyses in st_rotor_assembly.py.
 """
 import numpy as np
-from plotly import express as px
-from plotly import graph_objects as go
-from plotly import io as pio
+import plotly.express as px
+import plotly.graph_objects as go
+import plotly.io as pio
 from plotly.subplots import make_subplots
 
 pio.renderers.default = "browser"
diff --git a/ross/stochastic/st_results_elements.py b/ross/stochastic/st_results_elements.py
index 31eee27c..46d38c82 100644
--- a/ross/stochastic/st_results_elements.py
+++ b/ross/stochastic/st_results_elements.py
@@ -3,8 +3,8 @@
 This modules provides functions to plot the elements statistic data.
 """
 import numpy as np
-from plotly import graph_objects as go
-from plotly import io as pio
+import plotly.graph_objects as go
+import plotly.io as pio
 from plotly.subplots import make_subplots
 from scipy.stats import gaussian_kde
 
diff --git a/ross/utils.py b/ross/utils.py
index 1f77a2a2..bdb986a3 100644
--- a/ross/utils.py
+++ b/ross/utils.py
@@ -2,7 +2,7 @@ import re
 
 import numpy as np
 import pandas as pd
-from plotly import graph_objects as go
+import plotly.graph_objects as go
 
 
 class DataNotFoundError(Exception):


Test patch:
diff --git a/ross/tests/test_bearing_seal_element.py b/ross/tests/test_bearing_seal_element.py
index 2951e5fb..2515cd4d 100644
--- a/ross/tests/test_bearing_seal_element.py
+++ b/ross/tests/test_bearing_seal_element.py
@@ -9,7 +9,6 @@ from numpy.testing import assert_allclose
 
 from ross.bearing_seal_element import (BallBearingElement, BearingElement,
                                        BearingElement6DoF,
-                                       MagneticBearingElement,
                                        RollerBearingElement)
 
 # fmt: on
@@ -293,41 +292,6 @@ def test_roller_bearing_element():
     assert_allclose(rollerbearing.G(), G)
 
 
-def test_magnetic_bearing_element():
-    n = 0
-    g0 = 1e-3
-    i0 = 1.0
-    ag = 1e-4
-    nw = 200
-    alpha = 0.392
-    kp_pid = 1.0
-    kd_pid = 1.0
-    k_amp = 1.0
-    k_sense = 1.0
-    tag = "magneticbearing"
-    mbearing = MagneticBearingElement(
-        n=n,
-        g0=g0,
-        i0=i0,
-        ag=ag,
-        nw=nw,
-        alpha=alpha,
-        kp_pid=kp_pid,
-        kd_pid=kd_pid,
-        k_amp=k_amp,
-        k_sense=k_sense,
-    )
-    M = np.array([[0.0, 0.0], [0.0, 0.0]])
-    K = np.array([[-4640.62337718, 0.0], [0.0, -4640.62337718]])
-    C = np.array([[4.64526865, 0.0], [0.0, 4.64526865]])
-    G = np.array([[0.0, 0.0], [0.0, 0.0]])
-
-    assert_allclose(mbearing.M(), M)
-    assert_allclose(mbearing.K(0), K)
-    assert_allclose(mbearing.C(0), C)
-    assert_allclose(mbearing.G(), G)
-
-
 @pytest.fixture
 def bearing_6dof():
     bearing_6dof = BearingElement6DoF(
diff --git a/ross/tests/test_fluid_flow.py b/ross/tests/test_fluid_flow.py
index 68808ab8..5ea73416 100644
--- a/ross/tests/test_fluid_flow.py
+++ b/ross/tests/test_fluid_flow.py
@@ -2,9 +2,9 @@
 import math
 
 import numpy as np
+import plotly.graph_objects as go
 import pytest
 from numpy.testing import assert_allclose
-from plotly import graph_objects as go
 
 from ross.fluid_flow import fluid_flow as flow
 from ross.fluid_flow.fluid_flow_coefficients import (
@@ -23,6 +23,7 @@ from ross.fluid_flow.fluid_flow_graphics import (
 def fluid_flow_short_eccentricity():
     nz = 8
     ntheta = 32
+    nradius = 8
     omega = 100.0 * 2 * np.pi / 60
     p_in = 0.0
     p_out = 0.0
@@ -35,6 +36,7 @@ def fluid_flow_short_eccentricity():
     return flow.FluidFlow(
         nz,
         ntheta,
+        nradius,
         length,
         omega,
         p_in,
@@ -51,6 +53,7 @@ def fluid_flow_short_eccentricity():
 def fluid_flow_short_friswell(set_load=True):
     nz = 8
     ntheta = 32
+    nradius = 8
     length = 0.03
     omega = 157.1
     p_in = 0.0
@@ -65,6 +68,7 @@ def fluid_flow_short_friswell(set_load=True):
         return flow.FluidFlow(
             nz,
             ntheta,
+            nradius,
             length,
             omega,
             p_in,
@@ -80,6 +84,7 @@ def fluid_flow_short_friswell(set_load=True):
         return flow.FluidFlow(
             nz,
             ntheta,
+            nradius,
             length,
             omega,
             p_in,
@@ -180,6 +185,7 @@ def test_damping_matrix():
 def fluid_flow_short_numerical():
     nz = 8
     ntheta = 32
+    nradius = 8
     length = 0.01
     omega = 100.0 * 2 * np.pi / 60
     p_in = 0.0
@@ -193,6 +199,7 @@ def fluid_flow_short_numerical():
     return flow.FluidFlow(
         nz,
         ntheta,
+        nradius,
         length,
         omega,
         p_in,
@@ -210,6 +217,7 @@ def fluid_flow_short_numerical():
 def fluid_flow_long_numerical():
     nz = 8
     ntheta = 32
+    nradius = 8
     omega = 100.0 * 2 * np.pi / 60
     p_in = 0.0
     p_out = 0.0
@@ -223,6 +231,7 @@ def fluid_flow_long_numerical():
     return flow.FluidFlow(
         nz,
         ntheta,
+        nradius,
         length,
         omega,
         p_in,
diff --git a/ross/tests/test_stochastic_elements.py b/ross/tests/test_stochastic_elements.py
index 373a52e8..1c89dfcc 100644
--- a/ross/tests/test_stochastic_elements.py
+++ b/ross/tests/test_stochastic_elements.py
@@ -6,8 +6,8 @@ Tests for:
     st_point_mass.py
 """
 import numpy as np
+import plotly.graph_objects as go
 import pytest
-from plotly import graph_objects as go
 
 from ross.stochastic.st_bearing_seal_element import ST_BearingElement
 from ross.stochastic.st_disk_element import ST_DiskElement