Repository: ross-rotordynamics/ross (python)

Issue:
Error in Bearing: "Arguments (coefficients and w) must have the same dimension"
The following code is returning this error:

`from ross.bearing_seal_element import BearingElement`

`bearing = BearingElement(n=0, kxx=[481, 4810, 18810], cxx=[3.13, 10.81, 22.99], kyy=[481, 4810, 18810], kxy=[194, 2078, 8776], kyx=[-194, -2078, -8776], cyy=[3.13, 10.81, 22.99], cxy=[0.276, 0.69, 1.19], cyx=[-0.276, -0.69, -1.19], w=[115.19, 345.575, 691.15])`

Every argument has dimension 3, but somehow it sees as if they didn't.

Pull request description:
Fix bearing interpolation error
This fixes the interpolation code for the cases where the array
dimension is < 4. UnivariateSpline won't work for 3 or 2 points, so
these cases are now handled with interp1d.

Closes #253 

Patch:
diff --git a/ross/bearing_seal_element.py b/ross/bearing_seal_element.py
index f0754b8e..6b6bb666 100644
--- a/ross/bearing_seal_element.py
+++ b/ross/bearing_seal_element.py
@@ -36,14 +36,20 @@ class _Coefficient:
             #  dfitpack.error is not exposed by scipy
             #  so a bare except is used
             except:
-                raise ValueError(
-                    "Arguments (coefficients and w)" " must have the same dimension"
-                )
+                try:
+                    if len(self.w) in (2, 3):
+                        self.interpolated = interpolate.interp1d(
+                            self.w, self.coefficient, kind=len(self.w) - 1
+                        )
+                except:
+                    raise ValueError(
+                        "Arguments (coefficients and w)" " must have the same dimension"
+                    )
         else:
             self.interpolated = lambda x: np.array(self.coefficient[0])
 
     def __eq__(self, other):
-        if np.allclose(self.__dict__["coefficient"],other.__dict__["coefficient"]):
+        if np.allclose(self.__dict__["coefficient"], other.__dict__["coefficient"]):
             return True
         else:
             return False
@@ -332,19 +338,19 @@ class BearingElement(Element):
         Returns
         -------
         """
-        default_values = dict(lw=1., alpha=1., c='k')
+        default_values = dict(lw=1.0, alpha=1.0, c="k")
         for k, v in default_values.items():
             kwargs.setdefault(k, v)
 
         # geometric factors
         zpos, ypos = position
-        coils = 6               # number of points to generate spring
-        step = mean / 5         # spring step
-        a = 2.2                 # range(1.8 to 2.8)
-        b = 1.4                 # range(1.2 to 1.5)
-        c = mean / 2.9          # defines width
-        d = (coils / a)*step    # modifies damper width
-        n = 5                   # number of ground lines
+        coils = 6  # number of points to generate spring
+        step = mean / 5  # spring step
+        a = 2.2  # range(1.8 to 2.8)
+        b = 1.4  # range(1.2 to 1.5)
+        c = mean / 2.9  # defines width
+        d = (coils / a) * step  # modifies damper width
+        n = 5  # number of ground lines
 
         zs0 = zpos - c
         zs1 = zpos + c
@@ -363,7 +369,7 @@ class BearingElement(Element):
             b * ys0 + (coils + 1) * step,
             ys0 + (coils + 1) * step,
             ys0 + (coils + 1) * step,
-            ys0 + (coils + 1) * step
+            ys0 + (coils + 1) * step,
         ]
         yu_top = [-y for y in yl_top]
 
@@ -379,7 +385,7 @@ class BearingElement(Element):
 
         step2 = (zl_g[1] - zl_g[0]) / n
         for i in range(n + 1):
-            zl_g2 = [(zs0 - step) + step2*(i), (zs0 - step) + step2*(i+1)]
+            zl_g2 = [(zs0 - step) + step2 * (i), (zs0 - step) + step2 * (i + 1)]
             yl_g2 = [yl_g[0], 1.1 * yl_g[0]]
             yu_g2 = [-y for y in yl_g2]
             ax.add_line(mlines.Line2D(zl_g2, yl_g2, **kwargs))
@@ -388,11 +394,7 @@ class BearingElement(Element):
         # plot spring
         z_spring = np.array([zs0, zs0, zs0, zs0])
         yl_spring = np.array(
-            [ys0,
-             ys0 + step,
-             ys0 + coils * step,
-             ys0 + (coils + 1) * step
-             ]
+            [ys0, ys0 + step, ys0 + coils * step, ys0 + (coils + 1) * step]
         )
 
         for i in range(coils):
@@ -423,7 +425,7 @@ class BearingElement(Element):
             ys0 + 1.5 * d,
             ys0 + 1.5 * d,
             ys0 + 1.5 * d,
-            ys0 + (coils + 1) * step
+            ys0 + (coils + 1) * step,
         ]
         yu_damper3 = [-y for y in yl_damper3]
 
@@ -452,13 +454,13 @@ class BearingElement(Element):
 
         # geometric factors
         zpos, ypos = position
-        coils = 6               # number of points to generate spring
-        step = mean / 5         # spring step
-        a = 2.2                 # range(1.8 to 2.8)
-        b = 1.4                 # range(1.2 to 1.5)
-        c = mean / 2.9          # defines width
-        d = (coils / a)*step    # modifies damper width
-        n = 5                   # number of ground lines
+        coils = 6  # number of points to generate spring
+        step = mean / 5  # spring step
+        a = 2.2  # range(1.8 to 2.8)
+        b = 1.4  # range(1.2 to 1.5)
+        c = mean / 2.9  # defines width
+        d = (coils / a) * step  # modifies damper width
+        n = 5  # number of ground lines
 
         zs0 = zpos - c
         zs1 = zpos + c
@@ -477,7 +479,7 @@ class BearingElement(Element):
             b * ys0 + (coils + 1) * step,
             ys0 + (coils + 1) * step,
             ys0 + (coils + 1) * step,
-            ys0 + (coils + 1) * step
+            ys0 + (coils + 1) * step,
         ]
         yu_top = [-y for y in yl_top]
 
@@ -492,8 +494,8 @@ class BearingElement(Element):
         bk_ax.line(x=zl_g, y=yu_g, **kwargs)
 
         step2 = (zl_g[1] - zl_g[0]) / n
-        for i in range(n+1):
-            zl_g2 = [(zs0 - step) + step2*(i), (zs0 - step) + step2*(i+1)]
+        for i in range(n + 1):
+            zl_g2 = [(zs0 - step) + step2 * (i), (zs0 - step) + step2 * (i + 1)]
             yl_g2 = [yl_g[0], 1.1 * yl_g[0]]
             yu_g2 = [-y for y in yl_g2]
             bk_ax.line(x=zl_g2, y=yl_g2, **kwargs)
@@ -502,11 +504,7 @@ class BearingElement(Element):
         # plot spring
         z_spring = np.array([zs0, zs0, zs0, zs0])
         yl_spring = np.array(
-            [ys0,
-             ys0 + step,
-             ys0 + coils * step,
-             ys0 + (coils + 1) * step
-             ]
+            [ys0, ys0 + step, ys0 + coils * step, ys0 + (coils + 1) * step]
         )
 
         for i in range(coils):
@@ -537,7 +535,7 @@ class BearingElement(Element):
             ys0 + 1.5 * d,
             ys0 + 1.5 * d,
             ys0 + 1.5 * d,
-            ys0 + (coils + 1) * step
+            ys0 + (coils + 1) * step,
         ]
         yu_damper3 = [-y for y in yl_damper3]
 
@@ -593,18 +591,18 @@ class BearingElement(Element):
         -------
         A bearing object.
         """
-        parameters = read_table_file(file, 'bearing', sheet_name, n)
+        parameters = read_table_file(file, "bearing", sheet_name, n)
         return cls(
-            n=parameters['n'],
-            kxx=parameters['kxx'],
-            cxx=parameters['cxx'],
-            kyy=parameters['kyy'],
-            kxy=parameters['kxy'],
-            kyx=parameters['kyx'],
-            cyy=parameters['cyy'],
-            cxy=parameters['cxy'],
-            cyx=parameters['cyx'],
-            w=parameters['w'],
+            n=parameters["n"],
+            kxx=parameters["kxx"],
+            cxx=parameters["cxx"],
+            kyy=parameters["kyy"],
+            kxy=parameters["kxy"],
+            kyx=parameters["kyx"],
+            cyy=parameters["cyy"],
+            cxy=parameters["cxy"],
+            cyx=parameters["cyx"],
+            w=parameters["w"],
         )
 
     @classmethod
@@ -757,26 +755,22 @@ class SealElement(BearingElement):
 
         #  node (x pos), outer diam. (y pos)
         bearing_points_u = [
-            [zpos - step, 1.1*ypos],  # upper
-            [zpos - step, 1.1*ypos + 2*step],
-            [zpos + step, 1.1*ypos + 2*step],
-            [zpos + step, 1.1*ypos],
-            [zpos - step, 1.1*ypos],
+            [zpos - step, 1.1 * ypos],  # upper
+            [zpos - step, 1.1 * ypos + 2 * step],
+            [zpos + step, 1.1 * ypos + 2 * step],
+            [zpos + step, 1.1 * ypos],
+            [zpos - step, 1.1 * ypos],
         ]
         bearing_points_l = [
-            [zpos - step, -1.1*ypos],  # upper
-            [zpos - step, -1.1*ypos - 2*step],
-            [zpos + step, -1.1*ypos - 2*step],
-            [zpos + step, -1.1*ypos],
-            [zpos - step, -1.1*ypos],
+            [zpos - step, -1.1 * ypos],  # upper
+            [zpos - step, -1.1 * ypos - 2 * step],
+            [zpos + step, -1.1 * ypos - 2 * step],
+            [zpos + step, -1.1 * ypos],
+            [zpos - step, -1.1 * ypos],
         ]
 
-        ax.add_patch(
-            mpatches.Polygon(bearing_points_u, color=self.color, picker=True)
-        )
-        ax.add_patch(
-            mpatches.Polygon(bearing_points_l, color=self.color, picker=True)
-        )
+        ax.add_patch(mpatches.Polygon(bearing_points_u, color=self.color, picker=True))
+        ax.add_patch(mpatches.Polygon(bearing_points_l, color=self.color, picker=True))
 
     def bokeh_patch(self, position, length, bk_ax):
         """Seal element patch.
@@ -797,8 +791,8 @@ class SealElement(BearingElement):
 
         # bokeh plot - upper seal visual representation
         bk_ax.quad(
-            top=1.1*ypos + 2*step,
-            bottom=1.1*ypos,
+            top=1.1 * ypos + 2 * step,
+            bottom=1.1 * ypos,
             left=zpos - step,
             right=zpos + step,
             line_color=bokeh_colors[6],
@@ -809,8 +803,8 @@ class SealElement(BearingElement):
         )
         # bokeh plot - lower seal visual representation
         bk_ax.quad(
-            top=-1.1*ypos,
-            bottom=-1.1*ypos - 2*step,
+            top=-1.1 * ypos,
+            bottom=-1.1 * ypos - 2 * step,
             left=zpos - step,
             right=zpos + step,
             line_color=bokeh_colors[6],


Test patch:
diff --git a/ross/tests/test_bearing_seal_element.py b/ross/tests/test_bearing_seal_element.py
index a698b62d..2390fbb2 100644
--- a/ross/tests/test_bearing_seal_element.py
+++ b/ross/tests/test_bearing_seal_element.py
@@ -119,7 +119,7 @@ def test_bearing1_matrices(bearing1):
     assert_allclose(bearing1.C(314.2), C)
 
 
-def test_bearing_error1():
+def test_bearing_error_speed_not_given():
     speed = np.linspace(0, 10000, 5)
     kx = 1e8 * speed
     cx = 1e8 * speed
@@ -157,6 +157,38 @@ def test_bearing_constant(bearing_constant):
     assert_allclose(bearing_constant.cxx.interpolated(300.9), 0, rtol=1e5)
 
 
+def test_bearing_len_2():
+    bearing = BearingElement(
+        n=0,
+        kxx=[481, 4810],
+        cxx=[3.13, 10.81],
+        kyy=[481, 4810],
+        kxy=[194, 2078],
+        kyx=[-194, -2078],
+        cyy=[3.13, 10.81],
+        cxy=[0.276, 0.69],
+        cyx=[-0.276, -0.69],
+        w=[115.19, 345.575],
+    )
+    assert_allclose(bearing.kxx.interpolated(115.19), 481, rtol=1e5)
+
+
+def test_bearing_len_3():
+    bearing = BearingElement(
+        n=0,
+        kxx=[481, 4810, 18810],
+        cxx=[3.13, 10.81, 22.99],
+        kyy=[481, 4810, 18810],
+        kxy=[194, 2078, 8776],
+        kyx=[-194, -2078, -8776],
+        cyy=[3.13, 10.81, 22.99],
+        cxy=[0.276, 0.69, 1.19],
+        cyx=[-0.276, -0.69, -1.19],
+        w=[115.19, 345.575, 691.15],
+    )
+    assert_allclose(bearing.kxx.interpolated(115.19), 481, rtol=1e5)
+
+
 def test_equality(bearing0, bearing1, bearing_constant):
     assert bearing0 == bearing0
     assert bearing0 == bearing1
@@ -165,7 +197,9 @@ def test_equality(bearing0, bearing1, bearing_constant):
 
 
 def test_from_table():
-    bearing_file = os.path.dirname(os.path.realpath(__file__)) + "/data/bearing_seal.xls"
+    bearing_file = (
+        os.path.dirname(os.path.realpath(__file__)) + "/data/bearing_seal.xls"
+    )
     bearing = BearingElement.from_table(0, bearing_file)
     assert bearing.n == 0
     assert math.isclose(bearing.w[2], 523.6, abs_tol=0.1)