From 4b271ba243997305b031c49b11a1b8b2fcbc3162 Mon Sep 17 00:00:00 2001 From: Luca Miguel Date: Tue, 27 Jun 2023 16:25:21 +0200 Subject: [PATCH] Corrected pipe design, added sequences --- rocket_twin/drivers/fuelling_rocket.py | 5 +- rocket_twin/drivers/vertical_flying_rocket.py | 5 +- rocket_twin/notebooks/Visualisation.ipynb | 99 ++----- .../notebooks/test_design_method.ipynb | 163 +++++++++++ rocket_twin/notebooks/test_sequences.ipynb | 269 ++++++++++++++++++ rocket_twin/systems/ground.py | 20 +- rocket_twin/systems/physics/dynamics.py | 2 +- rocket_twin/systems/rocket/rocket.py | 5 +- rocket_twin/systems/tank/pipe.py | 7 +- rocket_twin/systems/tank/tank.py | 18 +- rocket_twin/test.py | 3 - rocket_twin/tests/test_flying_rocket.py | 2 +- rocket_twin/tests/test_mission.py | 4 +- rocket_twin/tests/test_refuel_rocket.py | 4 +- rocket_twin/tests/test_tank.py | 4 +- rocket_twin/utils/__init__.py | 3 + rocket_twin/utils/run_sequences.py | 63 ++++ 17 files changed, 570 insertions(+), 106 deletions(-) create mode 100644 rocket_twin/notebooks/test_design_method.ipynb create mode 100644 rocket_twin/notebooks/test_sequences.ipynb delete mode 100644 rocket_twin/test.py create mode 100644 rocket_twin/utils/__init__.py create mode 100644 rocket_twin/utils/run_sequences.py diff --git a/rocket_twin/drivers/fuelling_rocket.py b/rocket_twin/drivers/fuelling_rocket.py index 05e4d65..1370d25 100644 --- a/rocket_twin/drivers/fuelling_rocket.py +++ b/rocket_twin/drivers/fuelling_rocket.py @@ -17,10 +17,9 @@ def __init__(self, name: str, flux, dt, owner: Optional["System"] = None, **kwar init = { "rocket.dyn.switch": False, - "rocket.tank.p_out": 0.0, + "rocket.tank.flux": 0.0, "g_tank.p_in": 0.0, - "pipe.pi_in": flux, - "pipe.pi_out": flux, + "g_tank.flux": flux, } stop = "rocket.tank.w_p >= rocket.tank.w_max" diff --git a/rocket_twin/drivers/vertical_flying_rocket.py b/rocket_twin/drivers/vertical_flying_rocket.py index 8fc7f59..a031956 100644 --- a/rocket_twin/drivers/vertical_flying_rocket.py +++ b/rocket_twin/drivers/vertical_flying_rocket.py @@ -18,9 +18,8 @@ def __init__(self, name: str, flux, dt, owner: Optional["System"] = None, **kwar init = { "rocket.dyn.switch": True, "g_tank.p_in": 0.0, - "pipe.pi_in": 0.0, - "pipe.pi_out": 0.0, - "rocket.tank.p_out": flux, + "g_tank.flux": 0.0, + "rocket.tank.flux": flux, } stop = "rocket.tank.w_p <= 0." diff --git a/rocket_twin/notebooks/Visualisation.ipynb b/rocket_twin/notebooks/Visualisation.ipynb index d26d3f3..188320e 100644 --- a/rocket_twin/notebooks/Visualisation.ipynb +++ b/rocket_twin/notebooks/Visualisation.ipynb @@ -7,7 +7,7 @@ "metadata": {}, "outputs": [], "source": [ - "from rocket_twin import Rocket" + "from rocket_twin.systems import Ground" ] }, { @@ -17,7 +17,7 @@ "metadata": {}, "outputs": [], "source": [ - "rocket = Rocket('rocket')" + "ground = Ground('ground')" ] }, { @@ -33,7 +33,7 @@ " \n", - "\n", - "| | |\n", - "---|---\n", - " **p_in** 🔒🔒 : 0 kg/s | Fuel income rate\n", - "\n", - "\n", - "### Outputs\n", - "\n", - "- `outwards`: ExtensiblePort\n", - "\n", - "
\n", - "\n", - "| | |\n", - "---|---\n", - " **center**: 1 m | Center of gravity\n", - " **a**: 1 m/s**2 | Acceleration\n", - "
" + "- `pipe`: Pipe\n", + "- `g_tank`: Tank\n", + "- `rocket`: Rocket" ], "text/plain": [ - "rocket - Rocket" + "ground - Ground" ] }, "execution_count": 3, @@ -82,69 +58,32 @@ } ], "source": [ - "rocket" + "ground" ] }, { "cell_type": "code", - "execution_count": 4, + "execution_count": null, "id": "6b46cce2-b0da-44dc-a19d-1f261002608b", "metadata": {}, "outputs": [], - "source": [ - "from ground import Ground" - ] + "source": [] }, { "cell_type": "code", - "execution_count": 5, + "execution_count": null, "id": "b951bdb0-98eb-405d-9f37-8b0c6bc76568", "metadata": {}, "outputs": [], - "source": [ - "ground = Ground('ground')" - ] + "source": [] }, { "cell_type": "code", - "execution_count": 7, + "execution_count": null, "id": "ae5b4ea2-e71e-4dc7-ad37-9b47eb0e3daa", "metadata": {}, - "outputs": [ - { - "data": { - "text/html": [ - "\n", - " \n", - " " - ], - "text/markdown": [ - "\n", - "### Child components\n", - "\n", - "- `rocket`: Rocket\n", - "- `pipe`: Pipe\n", - "- `g_res`: GroundReservatory" - ], - "text/plain": [ - "ground - Ground" - ] - }, - "execution_count": 7, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "ground" - ] + "outputs": [], + "source": [] }, { "cell_type": "code", @@ -153,6 +92,14 @@ "metadata": {}, "outputs": [], "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "d41a129f-04d4-43d3-8aa8-fd234ce0f517", + "metadata": {}, + "outputs": [], + "source": [] } ], "metadata": { diff --git a/rocket_twin/notebooks/test_design_method.ipynb b/rocket_twin/notebooks/test_design_method.ipynb new file mode 100644 index 0000000..a787121 --- /dev/null +++ b/rocket_twin/notebooks/test_design_method.ipynb @@ -0,0 +1,163 @@ +{ + "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 new file mode 100644 index 0000000..b111cc4 --- /dev/null +++ b/rocket_twin/notebooks/test_sequences.ipynb @@ -0,0 +1,269 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "id": "daf09369-65d2-4485-9fa0-5249c2319670", + "metadata": {}, + "outputs": [], + "source": [ + "from rocket_twin.systems import Ground\n", + "from rocket_twin.utils import run_sequences" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "f85217e8-8b9e-406a-80e6-89ac379c0d98", + "metadata": {}, + "outputs": [], + "source": [ + "#System creation\n", + "\n", + "sys = Ground('sys')" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "e6d21709-780d-436d-a905-d9bd8b7b554f", + "metadata": {}, + "outputs": [], + "source": [ + "#Check ground tank values\n", + "\n", + "sys.g_tank.inwards" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "0d928614-9bf0-49e2-b9a7-e59e89c3b1d3", + "metadata": {}, + "outputs": [], + "source": [ + "#Run initial sequence (loads initial values for ground tank)\n", + "\n", + "s1 = [{'name' : 'start', 'design_method' : ['start'], 'type' : 'static'}]\n", + "run_sequences(sys, s1)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "62fc9c93-8ade-4013-9385-55041ba48090", + "metadata": {}, + "outputs": [], + "source": [ + "#Checks ground tank values after initialising the correct values\n", + "\n", + "sys.g_tank.inwards" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "d0ead49d-b704-4f88-9cd2-c21aff56902f", + "metadata": {}, + "outputs": [], + "source": [ + "#Checks rocket tank values before fuel sequence\n", + "\n", + "sys.rocket.tank.inwards" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "b409104c-8011-4e10-b1fe-71f60743012a", + "metadata": {}, + "outputs": [], + "source": [ + "#Checks if rocket is off\n", + "\n", + "sys.rocket.dyn.inwards" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "1063b389-6907-4b4a-a5c2-501f0228d6da", + "metadata": {}, + "outputs": [], + "source": [ + "#Run fuelling sequence (transfers fuel from ground tank to rocket tank until it is full)\n", + "\n", + "s2 = [{'name' : 'fuel', 'type' : 'transient', 'init' : {'g_tank.flux' : 1.}, 'dt' : 0.1, 'Tf' : 5., 'stop' : 'rocket.tank.w_p == rocket.tank.w_max'}]\n", + "run_sequences(sys, s2)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "54bbeed1-3300-4ec9-b17b-11ee53caeeb1", + "metadata": {}, + "outputs": [], + "source": [ + "#Checks ground tank values after fuel transfer\n", + "\n", + "sys.g_tank.inwards" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "55107b5c-679c-422f-99e8-387585c1f3d9", + "metadata": {}, + "outputs": [], + "source": [ + "#Checks rocket tank values after fuel transfer and before flight\n", + "\n", + "sys.rocket.tank.inwards" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "76ed20d9-ac6c-468a-97b6-2d9756c2e82b", + "metadata": {}, + "outputs": [], + "source": [ + "#Checks rocket is still of\n", + "\n", + "sys.rocket.dyn.inwards" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "97c1d128-b1bd-4c39-9d62-f2d801515da0", + "metadata": {}, + "outputs": [], + "source": [ + "#Run flight sequence (turns rocket on and discards rocket tank fuel until it is empty)\n", + "\n", + "s3 = [{'name' : 'flight', 'type' : 'transient', 'init' : {'rocket.tank.flux' : 0.5, 'g_tank.flux' : 0., 'rocket.dyn.switch' : True},\n", + " 'dt' : 0.1, 'Tf' : 10., 'stop' : 'rocket.tank.w_p == 0.'}]\n", + "run_sequences(sys, s3)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "485e441e-d02a-46c3-b495-d535fefb2e80", + "metadata": {}, + "outputs": [], + "source": [ + "#Checks rocket tank values after flight sequence\n", + "\n", + "sys.rocket.tank.inwards" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "e1011a26-cd3d-48e4-a505-e1941a9b7bc5", + "metadata": {}, + "outputs": [], + "source": [ + "#Checks rocket is on\n", + "\n", + "sys.rocket.dyn.inwards" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "7da35ade-209f-4166-92c5-d53fca4c1733", + "metadata": {}, + "outputs": [], + "source": [ + "#Creates a second system to check behaviour when all sequences are executed together\n", + "\n", + "sys2 = Ground('sys2')" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "b834bf3d-45e7-42be-873d-4233ba51d618", + "metadata": {}, + "outputs": [], + "source": [ + "#Run all sequences\n", + "\n", + "sequences = [\n", + " {'name' : 'start', 'design_method' : ['start'], 'type' : 'static'},\n", + " {'name' : 'fuel', 'type' : 'transient', 'init' : {'g_tank.flux' : 1.}, 'dt' : 0.1, 'Tf' : 5., 'stop' : 'rocket.tank.w_p == rocket.tank.w_max'},\n", + " {'name' : 'flight', 'type' : 'transient', 'init' : {'rocket.tank.flux' : 0.5, 'g_tank.flux' : 0.}, 'dt' : 0.1, 'Tf' : 10., 'stop' : 'rocket.tank.w_p == 0.'}\n", + "]\n", + "run_sequences(sys2, sequences)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "53936c3a-1c1f-42b2-aad7-5c6642390c17", + "metadata": {}, + "outputs": [], + "source": [ + "#Checks ground tank values after sequences\n", + "\n", + "sys2.g_tank.inwards" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "2e0535c1-2c05-49c8-9aef-c19ad59d331c", + "metadata": {}, + "outputs": [], + "source": [ + "#Checks rocket tank values after sequences\n", + "\n", + "sys2.rocket.tank.inwards" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "9a2e5622-040a-4443-a0c4-7874141bd450", + "metadata": {}, + "outputs": [], + "source": [ + "#System visualisation\n", + "\n", + "sys" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "34efe4f9-0e6c-4a65-91c3-0d879a10153e", + "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/systems/ground.py b/rocket_twin/systems/ground.py index f61c8fe..786d4c9 100644 --- a/rocket_twin/systems/ground.py +++ b/rocket_twin/systems/ground.py @@ -9,7 +9,23 @@ def setup(self): self.add_child(Pipe("pipe")) self.add_child(Tank("g_tank")) - self.connect(self.pipe.outwards, self.g_tank.inwards, {"p_in": "p_out"}) - self.connect(self.pipe.outwards, self.rocket.inwards, {"p_out": "p_in"}) + self.connect(self.g_tank.outwards, self.pipe.inwards, {'p_out' : 'p_in'}) + self.connect(self.pipe.outwards, self.rocket.inwards, {'p_out' : 'p_in'}) + + self.g_tank.w_max = 10. + self.rocket.tank.w_p = 0. self.exec_order = ["pipe", "g_tank", "rocket"] + + #Design methods + dm = self.add_design_method('start') + dm.add_unknown('g_tank.w_p') + dm.add_equation('g_tank.w_p == g_tank.w_max') + + #dm = self.add_design_method('fuel') + #dm.add_unknown('pipe.p') + #dm.add_target('rocket.tank.w_p') + + #dm = self.add_design_method('flight') + #dm.add_unknown('rocket.tank.p_out') + #dm.add_target('rocket.tank.w_p') diff --git a/rocket_twin/systems/physics/dynamics.py b/rocket_twin/systems/physics/dynamics.py index 337ef33..a4424c9 100644 --- a/rocket_twin/systems/physics/dynamics.py +++ b/rocket_twin/systems/physics/dynamics.py @@ -11,7 +11,7 @@ def setup(self, forces=None, weights=None): self.add_property("forces", forces) self.add_property("weights", weights) - self.add_inward("switch", True, desc="Whether rocket is on or off") + self.add_inward("switch", False, desc="Whether rocket is on or off") self.add_inward("g", -10.0, desc="Gravity", unit="m/s**2") self.add_outward("a", 1.0, desc="Acceleration", unit="m/s**2") diff --git a/rocket_twin/systems/rocket/rocket.py b/rocket_twin/systems/rocket/rocket.py index d71915c..89226d4 100644 --- a/rocket_twin/systems/rocket/rocket.py +++ b/rocket_twin/systems/rocket/rocket.py @@ -9,11 +9,10 @@ def setup(self): self.add_child(Engine("engine")) self.add_child(Tank("tank"), pulling=["p_in"]) self.add_child( - RocketGeom("geom", centers=["engine", "tank"], weights=["weight_eng", "weight_tank"]), - pulling=["center"], + RocketGeom("geom", centers=["engine", "tank"], weights=["weight_eng", "weight_tank"]) ) self.add_child( - Dynamics("dyn", forces=["thrust"], weights=["weight_eng", "weight_tank"]), pulling=["a"] + Dynamics("dyn", forces=["thrust"], weights=["weight_eng", "weight_tank"]) ) self.connect( diff --git a/rocket_twin/systems/tank/pipe.py b/rocket_twin/systems/tank/pipe.py index e0c96ac..9e911a7 100644 --- a/rocket_twin/systems/tank/pipe.py +++ b/rocket_twin/systems/tank/pipe.py @@ -3,12 +3,9 @@ class Pipe(System): def setup(self): - self.add_inward("pi_in", 0.0, desc="Fuel income rate", unit="kg/s") - self.add_inward("pi_out", 0.0, desc="Fuel exit rate", unit="kg/s") - self.add_outward("p_in", 0.0, desc="Fuel income rate", unit="kg/s") + self.add_inward("p_in", 0.0, desc="Fuel income rate", unit="kg/s") self.add_outward("p_out", 0.0, desc="Fuel exit rate", unit="kg/s") def compute(self): - self.p_in = self.pi_in - self.p_out = self.pi_out + self.p_out = self.p_in diff --git a/rocket_twin/systems/tank/tank.py b/rocket_twin/systems/tank/tank.py index 7daa6c2..4ece7b0 100644 --- a/rocket_twin/systems/tank/tank.py +++ b/rocket_twin/systems/tank/tank.py @@ -3,16 +3,28 @@ class Tank(System): def setup(self): + + #Geometry self.add_inward("w_s", 1.0, desc="Structure weight", unit="kg") - self.add_inward("p_in", 0.0, desc="Fuel income rate", unit="kg/s") - self.add_inward("p_out", 0.0, desc="Fuel consumption rate", unit="kg/s") self.add_inward("w_max", 5.0, desc="Maximum fuel capacity", unit="kg") - self.add_transient("w_p", der="p_in - p_out", desc="Propellant weight") + #Inputs + self.add_inward("p_in", 0.0, desc="Fuel income rate", unit="kg/s") + + #Flux control + self.add_inward('flux', 0., desc="Fuel output rate", unit='kg/s') + + #Transient + self.add_outward("dp_dt", 0., desc="Fuel mass rate of change", unit="kg/s") + self.add_transient("w_p", der="dp_dt", desc="Propellant weight") + #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("p_out", 0.0, desc="Fuel output rate", unit="kg/s") def compute(self): + self.p_out = self.flux + self.dp_dt = self.p_in - self.p_out self.weight = self.w_s + self.w_p self.cg = 3.0 diff --git a/rocket_twin/test.py b/rocket_twin/test.py deleted file mode 100644 index d7ab3de..0000000 --- a/rocket_twin/test.py +++ /dev/null @@ -1,3 +0,0 @@ -from rocket_twin.systems import Ground - -print("oi") diff --git a/rocket_twin/tests/test_flying_rocket.py b/rocket_twin/tests/test_flying_rocket.py index e789141..c6bf0de 100644 --- a/rocket_twin/tests/test_flying_rocket.py +++ b/rocket_twin/tests/test_flying_rocket.py @@ -19,7 +19,7 @@ def test_run_once(self): data = sys.drivers["vfr"].data data = data.drop(["Section", "Status", "Error code"], axis=1) - np.testing.assert_allclose(sys.rocket.a, 40.0, atol=10 ** (-10)) + np.testing.assert_allclose(sys.rocket.dyn.a, 40.0, atol=10 ** (-10)) np.testing.assert_allclose(sys.rocket.tank.w_p, 0.0, atol=10 ** (-10)) np.testing.assert_allclose(sys.g_tank.w_p, 0.0, atol=10 ** (-10)) diff --git a/rocket_twin/tests/test_mission.py b/rocket_twin/tests/test_mission.py index bc0c60f..23da801 100644 --- a/rocket_twin/tests/test_mission.py +++ b/rocket_twin/tests/test_mission.py @@ -20,9 +20,9 @@ def test_run_once(self): data = sys.drivers["mission"].data data = data.drop(["Section", "Status", "Error code"], axis=1) - np.testing.assert_allclose(sys.rocket.a, 40.0, atol=10 ** (-10)) + np.testing.assert_allclose(sys.rocket.dyn.a, 40.0, atol=10 ** (-10)) np.testing.assert_allclose(sys.rocket.tank.w_p, 0.0, atol=10 ** (-10)) - np.testing.assert_allclose(sys.g_tank.w_p, 0.0, atol=10 ** (-10)) + np.testing.assert_allclose(sys.g_tank.w_p, 5.0, atol=10 ** (-10)) test_mission = TestMission() diff --git a/rocket_twin/tests/test_refuel_rocket.py b/rocket_twin/tests/test_refuel_rocket.py index ff4f97e..96fbe57 100644 --- a/rocket_twin/tests/test_refuel_rocket.py +++ b/rocket_twin/tests/test_refuel_rocket.py @@ -19,9 +19,9 @@ def test_run_once(self): data = sys.drivers["fr"].data data = data.drop(["Section", "Status", "Error code"], axis=1) - np.testing.assert_allclose(sys.rocket.a, 0.0, atol=10 ** (-10)) + np.testing.assert_allclose(sys.rocket.dyn.a, 0.0, atol=10 ** (-10)) np.testing.assert_allclose(sys.rocket.tank.w_p, 5.0, atol=10 ** (-10)) - np.testing.assert_allclose(sys.g_tank.w_p, 0.0, atol=10 ** (-10)) + np.testing.assert_allclose(sys.g_tank.w_p, 5.0, atol=10 ** (-10)) test_fr = TestFuellingRocket() diff --git a/rocket_twin/tests/test_tank.py b/rocket_twin/tests/test_tank.py index 842da75..9f02915 100644 --- a/rocket_twin/tests/test_tank.py +++ b/rocket_twin/tests/test_tank.py @@ -10,7 +10,7 @@ def test_fuel(self): driver = sys.add_driver(RungeKutta(order=4, dt=0.1)) driver.time_interval = (0, 5) - init = {"p_in": 3.0, "p_out": 0.0, "w_p": 0.0} + init = {"p_in": 3.0, "flux": 0.0, "w_p": 0.0} driver.set_scenario(init=init) @@ -23,7 +23,7 @@ def test_flight(self): driver = sys.add_driver(RungeKutta(order=4, dt=0.1)) driver.time_interval = (0, 5) - init = {"p_in": 0.0, "p_out": 3.0, "w_p": 15.0} + init = {"p_in": 0.0, "flux": 3.0, "w_p": 15.0} driver.set_scenario(init=init) diff --git a/rocket_twin/utils/__init__.py b/rocket_twin/utils/__init__.py new file mode 100644 index 0000000..76f89fb --- /dev/null +++ b/rocket_twin/utils/__init__.py @@ -0,0 +1,3 @@ +from rocket_twin.utils.run_sequences import run_sequences + +__all__ = ['run_sequences'] \ No newline at end of file diff --git a/rocket_twin/utils/run_sequences.py b/rocket_twin/utils/run_sequences.py new file mode 100644 index 0000000..fe00130 --- /dev/null +++ b/rocket_twin/utils/run_sequences.py @@ -0,0 +1,63 @@ +from cosapp.drivers import NonLinearSolver, RungeKutta, RunSingleCase +from cosapp.recorders import DataFrameRecorder + +def run_sequences(sys, sequences): + rk = sys.add_driver(RungeKutta('rk')) + rk.add_recorder(DataFrameRecorder(hold = True)) + + for seq in sequences: + print('sequence ', seq['name']) + + 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) + + if 'dt' in seq: + rk.dt = seq['dt'] + + if 'stop' in seq: + rk.set_scenario(stop = seq['stop']) + + 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(): + 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']: + run.add_unknown(uk, max_rel_step=0.9) + if 'equation' in seq: + for eq in seq['equation']: + run.add_equation(eq) + 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']: + 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()