petrobras / ross

ROSS is a library written in Python for rotordynamic analysis.
https://ross.readthedocs.io
Apache License 2.0
119 stars 95 forks source link

Convert CoAxialRotor class to MultiRotor #755

Open rodrigomoliveira1 opened 3 years ago

rodrigomoliveira1 commented 3 years ago

The CoAxialRotor class constructs a series of shafts in a coaxial and parallel manner, limiting itself to positioning the shafts internally and externally. Some configurations demands it not to be parallel of even coaxial, for example, compressors which have gear coupling between shafts.

CoAxialRotor class already has support for multiple shafts but isn't general enough. So, we could change its name to MultiRotor class and make some adaptations to suit these situations. Anyway, there's still a need for allowing the user to set a speed relation between shafts, since CoAxialRotor just make the shafts to rotate at the same speed.

Another idea is to create a new element called GearLink (GearCouple, etc) which would provide gear coupling (stiffness and damping) between 2 nodes from different shafts, and would inherit from BearingElement.

rodrigomoliveira1 commented 3 years ago

Some ideas:

raphaeltimbo commented 3 years ago

Some ideas:

  • MultiRotor class would take multiple Rotor objects and create a new object by adding some linkage between them.
  • MultiRotor class would inherit from Rotor class to make the same original methods available.
  • Plotting multiple rotors in a 2D configuration would be challenging. Instead, we could plot each rotor model individually and add it to a subplot.

Agreed. I think we can go in this direction.

Regarding the rotor speed, if we take multiple rotor objects, for the analysis we could have an API like:

import ross as rs

rotor1 = rs.Rotor(...)
rotor2 = rs.Rotor(...)

multirotor = rs.MultiRotor(rotor1, rotor2, links)

speed1 = 100
speed2 = 100
modal = multirotor.run_modal(speed=(speed1, speed2))

Here we would have to take in consideration the order in which we have instantiated the multirotor object and we would have to pass each rotor speed in the same order. In this case we would have more freedom defining each rotor speed, and if the user wants to have a speed relation, they can do speed2 = 2*speed1 for example. Here, internally, to assemble the matrices, first we would have separate calls to each rotor M, C, K and G methods with their respective speed and then we would have the global matrices assembled considering their links.

rodrigomoliveira1 commented 3 years ago

Taking 2 (or more) rotors and merging them requires renumbering the elements to make sure there'll be a continuous values for the elements, and set the degrees of freedom correctly.

However, once rotors are built, there's no way we can change the n values for each element, except for shaft elements. So, I need to add the same feature ShaftElement has to the other elements.

To make things shorter and more general, I'm adding two methods to Element class, so all the others inherit from it:

class Element(ABC):
    def __init__(self, n, tag=None):
        self._n = n
        self.tag = tag

    @property
    def n(self):
        return self._n

    @n.setter
    def n(self, value):
        self._n = value
        self.n_l = value
        if value is not None:
            self.n_r = value + 1

These methods will allows to manipulate the nodal location of each element and won't change the user experience at all. Although it seems a pretty simple way to get over this situation, these changes may require some change on rotors DataFrames, because we had a column df["n"], and with those changes, it will disappear, leaving only the df["_n"]

raphaeltimbo commented 3 years ago

Taking 2 (or more) rotors and merging them requires renumbering the elements to make sure there'll be a continuous values for the elements, and set the degrees of freedom correctly.

@rodrigomoliveira1, initially I wanted to avoid having to change the Element class just to have an extra method for this specific functionality. But if you think this modification improves the library as a whole, I think we could proceed with that modification.

I am only worried that we could break or make things more complex just to make this multirotor functionality work. In some cases I would suggest that we try to implement things by keeping the original rotors as they are and, if needed, we could make copies of these rotors and add attributes/methods to them after we create them.

rodrigomoliveira1 commented 3 years ago

I have suggested that because MultiRotor must have, at least, the same attributes than Rotor object to work properly. Having the same attributes, we avoid the need for changes in the main functions.

Even making copies of the input rotors, we'd still need to build those DataFrames with modified informations to the global assembly, so, when other functions refer to them, they should work without further issues.

The other option I see is copying the rotors' data and re-instantiate the elements to build a modified global assembly, but it probably would take a bit longer than just changing the n value.

The original rotors would not be changed at all in both cases.

ross-bott commented 3 years ago

Hi there! I have marked this issue as stale because it has not had activity for 45 days. Consider the following options: