From 1270e472b0c797bcf825e4eda0566e0e7c360e5d Mon Sep 17 00:00:00 2001 From: Luca Miguel Date: Wed, 28 Jun 2023 14:42:58 +0200 Subject: [PATCH] Modular ground class, pre-commit, typos --- .flake8 | 2 +- .github/workflows/commit-verification.yml | 2 +- .gitignore | 2 +- .isort.cfg | 2 +- AUTHORS.md | 2 +- LICENSE | 2 +- MANIFEST.in | 2 +- README.md | 6 +- pyproject.toml | 2 +- requirements.txt | 2 +- rocket_twin/drivers/__init__.py | 4 +- .../{fuelling_rocket.py => fueling_rocket.py} | 22 ++- rocket_twin/drivers/mission.py | 27 ++- rocket_twin/drivers/vertical_flying_rocket.py | 21 ++- .../notebooks/test_design_method.ipynb | 163 ------------------ rocket_twin/notebooks/test_sequences.ipynb | 6 +- rocket_twin/systems/__init__.py | 9 +- rocket_twin/systems/engine/engine.py | 15 ++ rocket_twin/systems/ground.py | 32 ++-- rocket_twin/systems/physics/dynamics.py | 19 ++ rocket_twin/systems/rocket/__init__.py | 2 +- rocket_twin/systems/rocket/rocket.py | 13 +- rocket_twin/systems/rocket/rocket_geom.py | 15 ++ rocket_twin/systems/station/__init__.py | 3 + rocket_twin/systems/station/station.py | 31 ++++ rocket_twin/systems/tank/pipe.py | 13 ++ rocket_twin/systems/tank/tank.py | 31 +++- rocket_twin/tests/test_dynamics.py | 2 + rocket_twin/tests/test_flying_rocket.py | 6 +- rocket_twin/tests/test_mission.py | 6 +- rocket_twin/tests/test_refuel_rocket.py | 14 +- rocket_twin/tests/test_rocket_geom.py | 2 + rocket_twin/tests/test_tank.py | 2 + rocket_twin/utils/__init__.py | 2 +- rocket_twin/utils/run_sequences.py | 78 ++++----- setup.cfg | 2 +- setup.py | 6 +- 37 files changed, 294 insertions(+), 276 deletions(-) rename rocket_twin/drivers/{fuelling_rocket.py => fueling_rocket.py} (71%) delete mode 100644 rocket_twin/notebooks/test_design_method.ipynb create mode 100644 rocket_twin/systems/station/__init__.py create mode 100644 rocket_twin/systems/station/station.py diff --git a/.flake8 b/.flake8 index 0708213..0a150be 100644 --- a/.flake8 +++ b/.flake8 @@ -1,4 +1,4 @@ [flake8] max-line-length=100 extend-ignore=E203,D104,D100,I004 -exclude=*/tests/*,docs/source/tools/* \ No newline at end of file +exclude=*/tests/*,docs/source/tools/* diff --git a/.github/workflows/commit-verification.yml b/.github/workflows/commit-verification.yml index a0902f2..461062a 100644 --- a/.github/workflows/commit-verification.yml +++ b/.github/workflows/commit-verification.yml @@ -40,4 +40,4 @@ jobs: - name: Test with pytest run: | - pytest \ No newline at end of file + pytest diff --git a/.gitignore b/.gitignore index 83bbfa4..b65bf91 100644 --- a/.gitignore +++ b/.gitignore @@ -250,4 +250,4 @@ $RECYCLE.BIN/ # Cosapp Systems representations **.html -# End of https://www.gitignore.io/api/git,linux,macos,python,windows,pycharm,jupyternotebook \ No newline at end of file +# End of https://www.gitignore.io/api/git,linux,macos,python,windows,pycharm,jupyternotebook diff --git a/.isort.cfg b/.isort.cfg index 7bb41c7..9be0762 100644 --- a/.isort.cfg +++ b/.isort.cfg @@ -4,4 +4,4 @@ known_third_party=pybind11,conda,conda_env multi_line_output=3 include_trailing_comma=True force_grid_wrap=0 -use_parentheses=True \ No newline at end of file +use_parentheses=True diff --git a/AUTHORS.md b/AUTHORS.md index ff1cc64..c42248f 100644 --- a/AUTHORS.md +++ b/AUTHORS.md @@ -1 +1 @@ -Luca Rodrigues Miguel \ No newline at end of file +Luca Rodrigues Miguel diff --git a/LICENSE b/LICENSE index af026cf..2e03597 100644 --- a/LICENSE +++ b/LICENSE @@ -3,4 +3,4 @@ Copyright (c) 2022, twiinIT - All Rights Reserved Unauthorized copying and/or distribution of this source-code, via any medium is strictly prohibited without the express permission of twiinIT. -Proprietary and confidential. \ No newline at end of file +Proprietary and confidential. diff --git a/MANIFEST.in b/MANIFEST.in index 179f965..e2924f8 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -4,4 +4,4 @@ include README.md recursive-exclude tests * recursive-exclude * __pycache__ -recursive-exclude * *.py[co] \ No newline at end of file +recursive-exclude * *.py[co] diff --git a/README.md b/README.md index 46f9c28..10bfa83 100644 --- a/README.md +++ b/README.md @@ -6,12 +6,12 @@ This library was built with CoSApp, an open source framework allowing complex sy ## Getting Started -After cloning the repository thanks to +After cloning the repository thanks to ```bash git clone https://github.com/twiinIT/rocket-twin.git ``` -install the dependencies via +install the dependencies via ```bash pip install -r requirements.txt @@ -19,7 +19,7 @@ pip install -r requirements.txt ## How to use -In order to use the graphic interface, move to the UI directory +In order to use the graphic interface, move to the UI directory and browse the jupyter notebook `user_interface.ipynb`. ## Overview diff --git a/pyproject.toml b/pyproject.toml index c2d1f46..f8b8adb 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -7,4 +7,4 @@ profile = "black" [tool.pytest.ini_options] pythonpath = [ "." -] \ No newline at end of file +] diff --git a/requirements.txt b/requirements.txt index b802e13..4e49bbe 100644 --- a/requirements.txt +++ b/requirements.txt @@ -17,4 +17,4 @@ pytest flake8 isort black -pre-commit \ No newline at end of file +pre-commit diff --git a/rocket_twin/drivers/__init__.py b/rocket_twin/drivers/__init__.py index d30e6d7..2d8ca74 100644 --- a/rocket_twin/drivers/__init__.py +++ b/rocket_twin/drivers/__init__.py @@ -1,5 +1,5 @@ -from rocket_twin.drivers.fuelling_rocket import FuellingRocket +from rocket_twin.drivers.fueling_rocket import FuelingRocket from rocket_twin.drivers.mission import Mission from rocket_twin.drivers.vertical_flying_rocket import VerticalFlyingRocket -__all__ = ["FuellingRocket", "VerticalFlyingRocket", "Mission"] +__all__ = ["FuelingRocket", "VerticalFlyingRocket", "Mission"] diff --git a/rocket_twin/drivers/fuelling_rocket.py b/rocket_twin/drivers/fueling_rocket.py similarity index 71% rename from rocket_twin/drivers/fuelling_rocket.py rename to rocket_twin/drivers/fueling_rocket.py index 751ebc8..71b0de0 100644 --- a/rocket_twin/drivers/fuelling_rocket.py +++ b/rocket_twin/drivers/fueling_rocket.py @@ -5,7 +5,23 @@ from cosapp.systems import System -class FuellingRocket(Driver): +class FuelingRocket(Driver): + """Driver that simulates the fueling of a rocket. + + Inputs + ------ + name: string, + the name of the driver + w_out [kg/s]: float, + mass flow of fuel exiting the ground tank + dt [s]: float, + integration time step + owner: System, + the system that owns the driver + + Outputs + ------ + """ def __init__(self, name: str, w_out, dt, owner: Optional["System"] = None, **kwargs): super().__init__(name, owner, **kwargs) @@ -26,7 +42,9 @@ def __init__(self, name: str, w_out, dt, owner: Optional["System"] = None, **kwa self.rk.set_scenario(init=init, stop=stop) self.rk.add_recorder( - DataFrameRecorder(includes=["rocket.dyn.a", "g_tank.weight", "rocket.tank.weight_p"], hold=True), + DataFrameRecorder( + includes=["rocket.dyn.a", "g_tank.weight", "rocket.tank.weight_p"], hold=True + ), period=dt, ) self.data = None diff --git a/rocket_twin/drivers/mission.py b/rocket_twin/drivers/mission.py index c1007bd..620fe14 100644 --- a/rocket_twin/drivers/mission.py +++ b/rocket_twin/drivers/mission.py @@ -4,18 +4,35 @@ from cosapp.drivers import Driver from cosapp.systems import System -from rocket_twin.drivers.fuelling_rocket import FuellingRocket +from rocket_twin.drivers.fueling_rocket import FuelingRocket from rocket_twin.drivers.vertical_flying_rocket import VerticalFlyingRocket class Mission(Driver): - def __init__( - self, name: str, w_in, w_out, dt, owner: Optional["System"] = None, **kwargs - ): + """Driver that simulates the fueling and the vertical flight of a rocket. + + Inputs + ------ + name: string, + the name of the driver + w_in [kg/s]: float, + mass flow of fuel entering the rocket tank during refueling + w_out [kg/s]: float, + mass flow of fuel exiting the rocket tank during flight + dt [s]: float, + integration time step + owner: System, + the system that owns the driver + + Outputs + ------ + """ + + def __init__(self, name: str, w_in, w_out, dt, owner: Optional["System"] = None, **kwargs): super().__init__(name, owner, **kwargs) # Fuelling - self.add_child(FuellingRocket("fuelling", w_out=w_in, dt=dt, owner=owner)) + self.add_child(FuelingRocket("fuelling", w_out=w_in, dt=dt, owner=owner)) # Flying self.add_child(VerticalFlyingRocket("flying", w_out=w_out, dt=dt, owner=owner)) diff --git a/rocket_twin/drivers/vertical_flying_rocket.py b/rocket_twin/drivers/vertical_flying_rocket.py index 115bf27..9976904 100644 --- a/rocket_twin/drivers/vertical_flying_rocket.py +++ b/rocket_twin/drivers/vertical_flying_rocket.py @@ -6,6 +6,23 @@ class VerticalFlyingRocket(Driver): + """Driver that simulates the vertical flight of a rocket. + + Inputs + ------ + name: string, + the name of the driver + w_out [kg/s]: float, + mass flow of fuel exiting the rocket tank + dt [s]: float, + integration time step + owner: System, + the system that owns the driver + + Outputs + ------ + """ + def __init__(self, name: str, w_out, dt, owner: Optional["System"] = None, **kwargs): super().__init__(name, owner, **kwargs) @@ -26,7 +43,9 @@ def __init__(self, name: str, w_out, dt, owner: Optional["System"] = None, **kwa self.rk.set_scenario(init=init, stop=stop) self.rk.add_recorder( - DataFrameRecorder(includes=["rocket.dyn.a", "g_tank.weight", "rocket.tank.weight_p"], hold=True), + DataFrameRecorder( + includes=["rocket.dyn.a", "g_tank.weight", "rocket.tank.weight_p"], hold=True + ), period=dt, ) self.data = None diff --git a/rocket_twin/notebooks/test_design_method.ipynb b/rocket_twin/notebooks/test_design_method.ipynb deleted file mode 100644 index a787121..0000000 --- a/rocket_twin/notebooks/test_design_method.ipynb +++ /dev/null @@ -1,163 +0,0 @@ -{ - "cells": [ - { - "cell_type": "code", - "execution_count": 3, - "id": "312c249e-eb51-4474-b794-d130e6f6c2bd", - "metadata": {}, - "outputs": [], - "source": [ - "from cosapp.base import System\n", - "from cosapp.drivers import RunSingleCase, NonLinearSolver, RungeKutta\n", - "import numpy as np" - ] - }, - { - "cell_type": "code", - "execution_count": 4, - "id": "2d1ffcfa-ad28-4f46-b757-2cc91e033b72", - "metadata": {}, - "outputs": [], - "source": [ - "class Ball2(System):\n", - "\n", - " def setup(self):\n", - "\n", - " self.add_inward('b', 1.)\n", - " self.add_transient('a', der='b')\n", - "\n", - " dm = self.add_design_method('test_1')\n", - " dm.add_unknown('a')\n", - " dm.add_equation('b == 3')\n", - "\n", - " def compute(self):\n", - "\n", - " self.b = 2*self.a" - ] - }, - { - "cell_type": "code", - "execution_count": 5, - "id": "08720b0e-5e11-42b1-9ed3-6d8d1e327abf", - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "1.5\n" - ] - } - ], - "source": [ - "ball2 = Ball2('ball2')\n", - "solver = ball2.add_driver(NonLinearSolver('solver', tol=1e-12))\n", - "case = solver.add_child(RunSingleCase('case'))\n", - "\n", - "case.design.extend(ball2.design_methods['test_1'])\n", - "\n", - "ball2.run_drivers()\n", - "\n", - "print(ball2.a)\n" - ] - }, - { - "cell_type": "code", - "execution_count": 9, - "id": "de43078b-8360-4913-991f-31aa805fa427", - "metadata": {}, - "outputs": [], - "source": [ - "class Ball(System):\n", - "\n", - " def setup(self):\n", - "\n", - " self.add_inward('v', 1., unit='m/s')\n", - " self.add_transient('x', der='v')" - ] - }, - { - "cell_type": "code", - "execution_count": 10, - "id": "e9b2a14e-018d-4502-8fde-a789b4dad1a1", - "metadata": {}, - "outputs": [ - { - "data": { - "text/markdown": [ - "`ball.inwards`: ExtensiblePort\n", - "
\n", - "\n", - "| | |\n", - "---|---\n", - " **v** 🔒🔒 : 4 m/s |\n", - " **x** 🔒🔒 : 16 | Transient variable defined as d(x)/dt = v\n", - "
\n" - ], - "text/plain": [ - "ExtensiblePort: {'v': 4.000000000000002, 'x': 15.99999999999997}" - ] - }, - "execution_count": 10, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "ball = Ball('ball')\n", - "solver = ball.add_driver(NonLinearSolver('solver', factor=0.9, tol=1e-5))\n", - "target = solver.add_child(RunSingleCase('target'))\n", - "driver = target.add_child(RungeKutta('rk', order=4))\n", - "\n", - "driver.time_interval = (0, 4)\n", - "driver.dt = 0.1\n", - "init = {'x' : 0.}\n", - "driver.set_scenario(init = init)\n", - "\n", - "target.design.add_unknown('v')\n", - "target.design.add_equation('x == 16.')\n", - "\n", - "ball.run_drivers()\n", - "\n", - "ball.inwards" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "40a151fe-6547-47d1-bb80-8d5bc8bb82cd", - "metadata": {}, - "outputs": [], - "source": [] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "f4e00fcd-aecf-495c-87ba-aa179c187eef", - "metadata": {}, - "outputs": [], - "source": [] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3 (ipykernel)", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.11.3" - } - }, - "nbformat": 4, - "nbformat_minor": 5 -} diff --git a/rocket_twin/notebooks/test_sequences.ipynb b/rocket_twin/notebooks/test_sequences.ipynb index b111cc4..acfd04e 100644 --- a/rocket_twin/notebooks/test_sequences.ipynb +++ b/rocket_twin/notebooks/test_sequences.ipynb @@ -7,7 +7,7 @@ "metadata": {}, "outputs": [], "source": [ - "from rocket_twin.systems import Ground\n", + "from rocket_twin.systems import Station\n", "from rocket_twin.utils import run_sequences" ] }, @@ -20,7 +20,7 @@ "source": [ "#System creation\n", "\n", - "sys = Ground('sys')" + "sys = Station('sys')" ] }, { @@ -180,7 +180,7 @@ "source": [ "#Creates a second system to check behaviour when all sequences are executed together\n", "\n", - "sys2 = Ground('sys2')" + "sys2 = Station('sys2')" ] }, { diff --git a/rocket_twin/systems/__init__.py b/rocket_twin/systems/__init__.py index b593bbf..0cdcde0 100644 --- a/rocket_twin/systems/__init__.py +++ b/rocket_twin/systems/__init__.py @@ -1,8 +1,9 @@ from rocket_twin.systems.engine import Engine from rocket_twin.systems.physics import Dynamics +from rocket_twin.systems.station import Station # isort : skip -from rocket_twin.systems.tank import Pipe, Tank # isort: skip -from rocket_twin.systems.rocket import Rocket, RocketGeom # isort: skip -from rocket_twin.systems.ground import Ground # isort: skip +from rocket_twin.systems.tank import Pipe, Tank # isort: skip +from rocket_twin.systems.rocket import Rocket, RocketGeom # isort: skip +from rocket_twin.systems.ground import Ground # isort: skip -__all__ = ["Engine", "Tank", "RocketGeom", "Rocket", "Pipe", "Dynamics", "Ground"] +__all__ = ["Engine", "Tank", "RocketGeom", "Rocket", "Pipe", "Dynamics", "Station", "Ground"] diff --git a/rocket_twin/systems/engine/engine.py b/rocket_twin/systems/engine/engine.py index 19a3a5c..30c50d5 100644 --- a/rocket_twin/systems/engine/engine.py +++ b/rocket_twin/systems/engine/engine.py @@ -2,6 +2,21 @@ class Engine(System): + """Simple model of an engine. + + Inputs + ------ + + Outputs + ------ + weight [kg]: float, + weight + cg [m]: float, + position of the center of gravity + force [N]: float, + thrust force + """ + def setup(self): self.add_outward("weight", 1.0, desc="weight", unit="kg") self.add_outward("cg", 1.0, desc="Center of Gravity", unit="m") diff --git a/rocket_twin/systems/ground.py b/rocket_twin/systems/ground.py index ebda172..361a33f 100644 --- a/rocket_twin/systems/ground.py +++ b/rocket_twin/systems/ground.py @@ -1,23 +1,25 @@ from cosapp.base import System -from rocket_twin.systems import Pipe, Rocket, Tank - class Ground(System): - def setup(self): - self.add_child(Rocket("rocket")) - self.add_child(Pipe("pipe")) - self.add_child(Tank("g_tank")) + """Ground system that manages the stations. + + Inputs + ------ + stations : System, + space stations + + Outputs + ------ + """ + + def setup(self, stations=None): - self.connect(self.g_tank.outwards, self.pipe.inwards, {'w_out' : 'w_in'}) - self.connect(self.pipe.outwards, self.rocket.inwards, {'w_out' : 'w_in'}) + if stations is None: + stations = [] - self.g_tank.weight_max = 10. - self.rocket.tank.weight_p = 0. + self.add_property("stations", stations) - self.exec_order = ["pipe", "g_tank", "rocket"] + for station in stations: - #Design methods - dm = self.add_design_method('start') - dm.add_unknown('g_tank.weight_p') - dm.add_equation('g_tank.weight_p == g_tank.weight_max') + self.add_child(station) diff --git a/rocket_twin/systems/physics/dynamics.py b/rocket_twin/systems/physics/dynamics.py index a4424c9..82c4fb8 100644 --- a/rocket_twin/systems/physics/dynamics.py +++ b/rocket_twin/systems/physics/dynamics.py @@ -2,6 +2,25 @@ class Dynamics(System): + """Dynamics of a physical system. + + Inputs + ------ + forces [N]: float, + total force in each component of the system + weights [kg]: float, + total weight of each component of the system + + Outputs + ------ + force [N]: float, + total force + weight [kg]: float, + total weight + a [m/s**2] : float, + acceleration + """ + def setup(self, forces=None, weights=None): if forces is None: forces = [] diff --git a/rocket_twin/systems/rocket/__init__.py b/rocket_twin/systems/rocket/__init__.py index f2ad143..4789d86 100644 --- a/rocket_twin/systems/rocket/__init__.py +++ b/rocket_twin/systems/rocket/__init__.py @@ -1,4 +1,4 @@ -from rocket_twin.systems.rocket.rocket_geom import RocketGeom # isort: skip +from rocket_twin.systems.rocket.rocket_geom import RocketGeom # isort: skip from rocket_twin.systems.rocket.rocket import Rocket __all__ = ["RocketGeom", "Rocket"] diff --git a/rocket_twin/systems/rocket/rocket.py b/rocket_twin/systems/rocket/rocket.py index 891f23e..649dbf0 100644 --- a/rocket_twin/systems/rocket/rocket.py +++ b/rocket_twin/systems/rocket/rocket.py @@ -5,15 +5,22 @@ class Rocket(System): + """A simple model of a rocket. + + Inputs + ------ + + Outputs + ------ + """ + def setup(self): self.add_child(Engine("engine")) self.add_child(Tank("tank"), pulling=["w_in"]) self.add_child( RocketGeom("geom", centers=["engine", "tank"], weights=["weight_eng", "weight_tank"]) ) - self.add_child( - Dynamics("dyn", forces=["thrust"], weights=["weight_eng", "weight_tank"]) - ) + self.add_child(Dynamics("dyn", forces=["thrust"], weights=["weight_eng", "weight_tank"])) self.connect( self.engine.outwards, self.geom.inwards, {"cg": "engine", "weight": "weight_eng"} diff --git a/rocket_twin/systems/rocket/rocket_geom.py b/rocket_twin/systems/rocket/rocket_geom.py index aa9fe57..fdd767d 100644 --- a/rocket_twin/systems/rocket/rocket_geom.py +++ b/rocket_twin/systems/rocket/rocket_geom.py @@ -2,6 +2,21 @@ class RocketGeom(System): + """Calculates the necessary geometric parameters of a rocket. + + Inputs + ------ + centers [m]: float, + center of gravity of each component of the rocket + weights [kg]: float, + weight of each component of the rocket + + Outputs + ------ + center [m]: float, + center of gravity of the rocket + """ + def setup(self, centers=None, weights=None): if centers is None: centers = [] diff --git a/rocket_twin/systems/station/__init__.py b/rocket_twin/systems/station/__init__.py new file mode 100644 index 0000000..5e49db6 --- /dev/null +++ b/rocket_twin/systems/station/__init__.py @@ -0,0 +1,3 @@ +from rocket_twin.systems.station.station import Station + +__all__ = ["Station"] \ No newline at end of file diff --git a/rocket_twin/systems/station/station.py b/rocket_twin/systems/station/station.py new file mode 100644 index 0000000..05d2857 --- /dev/null +++ b/rocket_twin/systems/station/station.py @@ -0,0 +1,31 @@ +from cosapp.base import System + +from rocket_twin.systems import Pipe, Rocket, Tank + + +class Station(System): + """A space station composed by a rocket, a tank and a pipe connecting them. + + Inputs + ------ + + Outputs + ------ + """ + def setup(self): + self.add_child(Rocket("rocket")) + self.add_child(Pipe("pipe")) + self.add_child(Tank("g_tank")) + + self.connect(self.g_tank.outwards, self.pipe.inwards, {"w_out": "w_in"}) + self.connect(self.pipe.outwards, self.rocket.inwards, {"w_out": "w_in"}) + + self.g_tank.weight_max = 10.0 + self.rocket.tank.weight_p = 0.0 + + self.exec_order = ["pipe", "g_tank", "rocket"] + + # Design methods + dm = self.add_design_method("start") + dm.add_unknown("g_tank.weight_p") + dm.add_equation("g_tank.weight_p == g_tank.weight_max") \ No newline at end of file diff --git a/rocket_twin/systems/tank/pipe.py b/rocket_twin/systems/tank/pipe.py index 7e4b6f8..59e6e1e 100644 --- a/rocket_twin/systems/tank/pipe.py +++ b/rocket_twin/systems/tank/pipe.py @@ -2,6 +2,19 @@ class Pipe(System): + """A simple model of a pipe. + + Inputs + ------ + w_in [kg/s]: float, + mass flow of fuel entering the pipe + + Outputs + ------ + w_out [kg/s]: floatm + mass flow of fuel exiting the pipe + """ + def setup(self): self.add_inward("w_in", 0.0, desc="Fuel income rate", unit="kg/s") diff --git a/rocket_twin/systems/tank/tank.py b/rocket_twin/systems/tank/tank.py index 17dd292..8487b5a 100644 --- a/rocket_twin/systems/tank/tank.py +++ b/rocket_twin/systems/tank/tank.py @@ -2,23 +2,40 @@ class Tank(System): + """A simple model of a fuel tank. + + Inputs + ------ + w_in [kg/s]: float, + mass flow of fuel entering the tank + + Outputs + ------ + w_out [kg/s]: float, + mass flow of fuel exiting the tank + weight [kg]: float, + weight + cg [m]: float, + center of gravity + """ + def setup(self): - #Geometry + # Geometry self.add_inward("weight_s", 1.0, desc="Structure weight", unit="kg") self.add_inward("weight_max", 5.0, desc="Maximum fuel capacity", unit="kg") - #Inputs + # Inputs self.add_inward("w_in", 0.0, desc="Fuel income rate", unit="kg/s") - #Flux control - self.add_inward('w_out_temp', 0., desc="Fuel output rate", unit='kg/s') + # Flux control + self.add_inward("w_out_temp", 0.0, desc="Fuel output rate", unit="kg/s") - #Transient - self.add_outward("dw_dt", 0., desc="Fuel mass rate of change", unit="kg/s") + # Transient + self.add_outward("dw_dt", 0.0, desc="Fuel mass rate of change", unit="kg/s") self.add_transient("weight_p", der="dw_dt", desc="Propellant weight") - #Outputs + # Outputs self.add_outward("weight", 1.0, desc="Weight", unit="kg") self.add_outward("cg", 1.0, desc="Center of gravity", unit="m") self.add_outward("w_out", 0.0, desc="Fuel output rate", unit="kg/s") diff --git a/rocket_twin/tests/test_dynamics.py b/rocket_twin/tests/test_dynamics.py index ddb5a39..b7eb03c 100644 --- a/rocket_twin/tests/test_dynamics.py +++ b/rocket_twin/tests/test_dynamics.py @@ -4,6 +4,8 @@ class TestDynamics: + """Tests for the dynamics model.""" + def test_is_on(self): sys = Dynamics("sys", forces=["F"], weights=["w"]) sys.F = 100.0 diff --git a/rocket_twin/tests/test_flying_rocket.py b/rocket_twin/tests/test_flying_rocket.py index 03ae24b..b5a4a3d 100644 --- a/rocket_twin/tests/test_flying_rocket.py +++ b/rocket_twin/tests/test_flying_rocket.py @@ -1,12 +1,14 @@ import numpy as np from rocket_twin.drivers.vertical_flying_rocket import VerticalFlyingRocket -from rocket_twin.systems.ground import Ground +from rocket_twin.systems import Station class TestVerticalFlyingRocket: + """Tests for the VerticalFlyingRocket driver.""" + def test_run_once(self): - sys = Ground("sys") + sys = Station("sys") sys.g_tank.weight_p = 0.0 sys.rocket.tank.weight_p = sys.rocket.tank.weight_max w_out = 3.0 diff --git a/rocket_twin/tests/test_mission.py b/rocket_twin/tests/test_mission.py index ab4eae1..a65fbca 100644 --- a/rocket_twin/tests/test_mission.py +++ b/rocket_twin/tests/test_mission.py @@ -1,12 +1,14 @@ import numpy as np from rocket_twin.drivers.mission import Mission -from rocket_twin.systems import Ground +from rocket_twin.systems import Station class TestMission: + """Tests for the mission driver.""" + def test_run_once(self): - sys = Ground("sys") + sys = Station("sys") sys.g_tank.weight_p = sys.g_tank.weight_max sys.rocket.tank.weight_p = 0.0 w_in = 3.0 diff --git a/rocket_twin/tests/test_refuel_rocket.py b/rocket_twin/tests/test_refuel_rocket.py index fd6fbb6..4f1c611 100644 --- a/rocket_twin/tests/test_refuel_rocket.py +++ b/rocket_twin/tests/test_refuel_rocket.py @@ -1,18 +1,20 @@ import numpy as np -from rocket_twin.drivers.fuelling_rocket import FuellingRocket -from rocket_twin.systems import Ground +from rocket_twin.drivers.fueling_rocket import FuelingRocket +from rocket_twin.systems import Station -class TestFuellingRocket: +class TestFuelingRocket: + """Tests for the FuelingRocket driver.""" + def test_run_once(self): - sys = Ground("sys") + sys = Station("sys") sys.g_tank.weight_p = sys.g_tank.weight_max sys.rocket.tank.weight_p = 0.0 w_out = 3.0 dt = 0.1 - sys.add_driver(FuellingRocket("fr", w_out=w_out, dt=dt, owner=sys)) + sys.add_driver(FuelingRocket("fr", w_out=w_out, dt=dt, owner=sys)) sys.run_drivers() @@ -24,6 +26,6 @@ def test_run_once(self): np.testing.assert_allclose(sys.g_tank.weight_p, 5.0, atol=10 ** (-10)) -test_fr = TestFuellingRocket() +test_fr = TestFuelingRocket() test_fr.test_run_once() print("Test run_once passed!") diff --git a/rocket_twin/tests/test_rocket_geom.py b/rocket_twin/tests/test_rocket_geom.py index f487e99..3a13be0 100644 --- a/rocket_twin/tests/test_rocket_geom.py +++ b/rocket_twin/tests/test_rocket_geom.py @@ -4,6 +4,8 @@ class TestRocketGeom: + """Tests for the rocket geometry model.""" + def test_run_once(self): sys = RocketGeom("sys", centers=["c1", "c2"], weights=["w1", "w2"]) diff --git a/rocket_twin/tests/test_tank.py b/rocket_twin/tests/test_tank.py index bc9e0f4..fabd764 100644 --- a/rocket_twin/tests/test_tank.py +++ b/rocket_twin/tests/test_tank.py @@ -5,6 +5,8 @@ class TestTank: + """Tests for the tank model.""" + def test_fuel(self): sys = Tank("sys") driver = sys.add_driver(RungeKutta(order=4, dt=0.1)) diff --git a/rocket_twin/utils/__init__.py b/rocket_twin/utils/__init__.py index 76f89fb..0c17755 100644 --- a/rocket_twin/utils/__init__.py +++ b/rocket_twin/utils/__init__.py @@ -1,3 +1,3 @@ from rocket_twin.utils.run_sequences import run_sequences -__all__ = ['run_sequences'] \ No newline at end of file +__all__ = ["run_sequences"] diff --git a/rocket_twin/utils/run_sequences.py b/rocket_twin/utils/run_sequences.py index fe00130..1bd2fc9 100644 --- a/rocket_twin/utils/run_sequences.py +++ b/rocket_twin/utils/run_sequences.py @@ -1,63 +1,57 @@ -from cosapp.drivers import NonLinearSolver, RungeKutta, RunSingleCase +from cosapp.drivers import NonLinearSolver, RungeKutta from cosapp.recorders import DataFrameRecorder + def run_sequences(sys, sequences): - rk = sys.add_driver(RungeKutta('rk')) - rk.add_recorder(DataFrameRecorder(hold = True)) + """Run the command sequences over a system. + + Inputs + ------ + sys: System, + the system over which the commands are applied + sequences: dictionary, + the commands to be applied + """ + rk = sys.add_driver(RungeKutta("rk")) + rk.add_recorder(DataFrameRecorder(hold=True)) for seq in sequences: - print('sequence ', seq['name']) + print("sequence ", seq["name"]) - if seq['type'] == 'transient': + if seq["type"] == "transient": sys.drivers.clear() rk.children.clear() sys.add_driver(rk) - run = rk.add_driver(NonLinearSolver('nls', tol=1e-6)) - rk.time_interval=(rk.time, rk.time + 10000) + run = rk.add_driver(NonLinearSolver("nls", tol=1e-6)) + rk.time_interval = (rk.time, rk.time + 10000) - if 'dt' in seq: - rk.dt = seq['dt'] + if "dt" in seq: + rk.dt = seq["dt"] - if 'stop' in seq: - rk.set_scenario(stop = seq['stop']) + if "stop" in seq: + rk.set_scenario(stop=seq["stop"]) - if seq['type'] == 'static': + if seq["type"] == "static": sys.drivers.clear() - run = sys.add_driver(NonLinearSolver('nls', tol=1e-6)) - - if 'init' in seq: - for key, val in seq['init'].items(): + run = sys.add_driver(NonLinearSolver("nls", tol=1e-6)) + + if "init" in seq: + for key, val in seq["init"].items(): sys[key] = val - if 'Tf' in seq: - rk.time_interval = (rk.time, rk.time + seq['Tf']) - if 'unknown' in seq: - for uk in seq['unknown']: + if "Tf" in seq: + rk.time_interval = (rk.time, rk.time + seq["Tf"]) + if "unknown" in seq: + for uk in seq["unknown"]: run.add_unknown(uk, max_rel_step=0.9) - if 'equation' in seq: - for eq in seq['equation']: + if "equation" in seq: + for eq in seq["equation"]: run.add_equation(eq) - if 'target' in seq: - for var, tar in seq['target'].items(): + if "target" in seq: + for var, tar in seq["target"].items(): sys[var] = tar - if 'design_method' in seq: - for dm in seq['design_method']: + if "design_method" in seq: + for dm in seq["design_method"]: run.runner.design.extend(sys.design_methods[dm]) sys.run_drivers() - -def run_endpoint(sys, sequence): - - solver = sys.add_driver(NonLinearSolver('solver', factor=0.9, tol=1e-5)) - target = solver.add_child(RunSingleCase('target')) - driver = target.add_child(RungeKutta('rk', order=4)) - - if 'dt' in sequence: - driver.dt = sequence['dt'] - if 'Tf' in sequence: - driver.time_interval = (0, sequence['Tf']) - if 'init' in sequence: - for key, val in sequence['init'].items(): - sys[key] = val - if 'unknown' in sequence: - target.design.add_unknown() diff --git a/setup.cfg b/setup.cfg index 81f0e4c..54d5e25 100644 --- a/setup.cfg +++ b/setup.cfg @@ -20,4 +20,4 @@ classifiers = zip_safe = False include_package_data = True packages = find: -python_requires = >= 3.6 \ No newline at end of file +python_requires = >= 3.6 diff --git a/setup.py b/setup.py index 6a32e0a..eb54417 100644 --- a/setup.py +++ b/setup.py @@ -2,9 +2,7 @@ from setuptools import setup -with open('requirements.txt') as requirements_file: +with open("requirements.txt") as requirements_file: requirements = [package.strip() for package in requirements_file.readlines()] -setup( - install_requires=requirements -) \ No newline at end of file +setup(install_requires=requirements)