Repository: petrobras/ross
Issue: Open specific dataframe to SealElement

The existing dataframe in rotor_assembly.py has 3 separated blocks: one for shaft elements, one for disk elements and one for bearing and seal elements.

Grouping bearing and seal elements is useful to instantiate them, but when it comes to the dataframe, we have a bug. The static analysis reads the dataframe for bearings and seals (`df_bearings`) to locate the bearings and calculate the reaction forces. So, the code does not only get the bearings but also the seals, and point reaction forces on seals, which is wrong in the static scenario.

So, we should separate them it different dataframes, like:
- df_bearings: for bearing elements;
- df_seal: for seal elements

Changed files:
ross/tests/test_rotor_assembly.py, ross/rotor_assembly.py

diff --git a/ross/rotor_assembly.py b/ross/rotor_assembly.py
index d512dd9..066a72f 100644
--- a/ross/rotor_assembly.py
+++ b/ross/rotor_assembly.py
@@ -227,7 +227,12 @@ class Rotor(object):
 
         df_shaft = pd.DataFrame([el.summary() for el in self.shaft_elements])
         df_disks = pd.DataFrame([el.summary() for el in self.disk_elements])
-        df_bearings = pd.DataFrame([el.summary() for el in self.bearing_seal_elements])
+        df_bearings = pd.DataFrame(
+                [el.summary() for el in self.bearing_seal_elements if (
+                        el.__class__.__name__ == 'BearingElement')])
+        df_seals = pd.DataFrame(
+                [el.summary() for el in self.bearing_seal_elements if (
+                        el.__class__.__name__ == 'SealElement')])
 
         nodes_pos_l = np.zeros(len(df_shaft.n_l))
         nodes_pos_r = np.zeros(len(df_shaft.n_l))
@@ -245,15 +250,15 @@ class Rotor(object):
 
         df_shaft["nodes_pos_l"] = nodes_pos_l
         df_shaft["nodes_pos_r"] = nodes_pos_r
-        # bearings
 
-        df = pd.concat([df_shaft, df_disks, df_bearings], sort=True)
+        df = pd.concat([df_shaft, df_disks, df_bearings, df_seals], sort=True)
         df = df.sort_values(by="n_l")
         df = df.reset_index(drop=True)
 
         self.df_disks = df_disks
         self.df_bearings = df_bearings
         self.df_shaft = df_shaft
+        self.df_seals = df_seals
 
         # check consistence for disks and bearings location
         if df.n_l.max() > df_shaft.n_r.max():
@@ -492,11 +497,11 @@ class Rotor(object):
                [ 0., -6.,  1.,  0.],
                [ 6.,  0.,  0.,  1.]])
         """
+        K0 = np.zeros((self.ndof, self.ndof))
+
         if frequency is None:
             frequency = self.w
 
-        K0 = np.zeros((self.ndof, self.ndof))
-
         for elm in self.elements:
             dofs = elm.dof_global_index()
             n0 = dofs[0]
@@ -529,11 +534,11 @@ class Rotor(object):
                [0., 0., 0., 0.],
                [0., 0., 0., 0.]])
         """
+        C0 = np.zeros((self.ndof, self.ndof))
+
         if frequency is None:
             frequency = self.w
 
-        C0 = np.zeros((self.ndof, self.ndof))
-
         for elm in self.elements:
             dofs = elm.dof_global_index()
             n0 = dofs[0]
@@ -1871,8 +1876,25 @@ class Rotor(object):
             for node_y in range(int(len(self.M()) / 4)):
                 grav[4 * node_y + 1] = -9.8065
 
+            aux_brg = []
+            for n in self.df_bearings["n"]:
+                aux_brg.append(BearingElement(n=n, kxx=1e14, cxx=0))
+
+            aux_rotor = Rotor(self.shaft_elements, self.disk_elements, aux_brg)
+            aux_K = np.zeros((aux_rotor.ndof, aux_rotor.ndof))
+
+            for elm in aux_rotor.elements:
+                if elm.__class__.__name__ != "SealElement":
+                    dofs = elm.dof_global_index()
+                    n0 = dofs[0]
+                    n1 = dofs[-1] + 1  # +1 to include this dof in the slice
+                    try:
+                        aux_K[n0:n1, n0:n1] += elm.K(0)
+                    except TypeError:
+                        aux_K[n0:n1, n0:n1] += elm.K()
+
             # calculates x, for [K]*(x) = [M]*(g)
-            disp = (la.solve(self.K(0), self.M() @ grav)).flatten()
+            disp = (la.solve(aux_K, self.M() @ grav)).flatten()
 
             # calculates displacement values in gravity's direction
             # dof = degree of freedom
@@ -1890,10 +1912,10 @@ class Rotor(object):
             BrgForceToReturn = []
             for i, node in enumerate(self.df_bearings["n"]):
                 BrgForce[node] = (
-                    -disp_y[node] * self.df_bearings.loc[i, "kyy"].coefficient[0]
+                    -disp_y[node] * aux_rotor.df_bearings.loc[i, "kyy"].coefficient[0]
                 )
                 BrgForceToReturn.append(
-                    np.around(-disp_y[node] * self.df_bearings.loc[i, "kyy"].coefficient[0], decimals=1)
+                    np.around(-disp_y[node] * aux_rotor.df_bearings.loc[i, "kyy"].coefficient[0], decimals=1)
                 )
 
             # Disk Forces
@@ -1973,7 +1995,7 @@ class Rotor(object):
                 self.Bm,
                 self.df_shaft,
                 self.df_disks,
-                self.df_bearings,
+                aux_rotor.df_bearings,
                 self.nodes,
                 self.nodes_pos,
                 Vx_axis,
diff --git a/ross/tests/test_rotor_assembly.py b/ross/tests/test_rotor_assembly.py
index 059cc3a..fee2a57 100644
--- a/ross/tests/test_rotor_assembly.py
+++ b/ross/tests/test_rotor_assembly.py
@@ -711,13 +711,13 @@ def test_static_analysis_rotor3(rotor3):
         rotor3.disp_y,
         (
             [
-                -0.00061784,
-                -0.00108199,
-                -0.00143205,
-                -0.00157464,
-                -0.00147798,
-                -0.00115111,
-                -0.00069521,
+                -4.94274533e-12,
+                -4.51249085e-04,
+                -7.88420867e-04,
+                -9.18114192e-04,
+                -8.08560219e-04,
+                -4.68788888e-04,
+                -5.56171636e-12
             ]
         ),
         decimal=6,
@@ -779,17 +779,17 @@ def test_static_analysis_rotor5(rotor5):
         rotor5.disp_y,
         (
             [
-                0.00026382,
-                -0.00015021,
-                -0.00056947,
-                -0.00098566,
-                -0.00130592,
-                -0.00143686,
-                -0.00134669,
-                -0.00104446,
-                -0.00063136,
-                -0.00021282,
-                0.0002005,
+                8.12651626e-04,
+                4.08939282e-04,
+                -5.69465378e-12,
+                -4.05876595e-04,
+                -7.15824882e-04,
+                -8.36443708e-04,
+                -7.35964234e-04,
+                -4.23416398e-04,
+                -6.31362481e-12,
+                4.28859620e-04,
+                8.52492302e-04
             ]
         ),
         decimal=6,
@@ -868,17 +868,17 @@ def test_static_analysis_rotor6(rotor6):
         rotor6.disp_y,
         (
             [
-                -2.58459386e-06,
-                -8.83514255e-05,
-                -1.79345202e-04,
-                -2.82280131e-04,
-                -3.83451012e-04,
-                -4.71329601e-04,
-                -5.55753491e-04,
-                -7.08192594e-04,
-                -1.02148266e-03,
-                -1.55824814e-03,
-                -2.22220183e-03,
+                -1.03951876e-04,
+                -4.93624668e-05,
+                -1.79345202e-12,
+                3.74213098e-05,
+                7.66066703e-05,
+                1.29084322e-04,
+                1.85016673e-04,
+                1.72933811e-04,
+                -1.02148266e-11,
+                -3.96409257e-04,
+                -9.20006704e-04
             ]
         ),
         decimal=6,