From 640be4ab931bdc857e4fe7c67c215214a9285b76 Mon Sep 17 00:00:00 2001 From: Luca Miguel Date: Mon, 28 Aug 2023 12:25:52 +0200 Subject: [PATCH] pre-commit --- .pre-commit-config.yaml | 1 + rocket_twin/notebooks/Demonstration.ipynb | 316 +++++++++++++++++++--- 2 files changed, 286 insertions(+), 31 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index a0d97f2..47d2ec2 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -29,6 +29,7 @@ repos: - id: check-merge-conflict - id: pretty-format-json args: [--autofix] + exclude: /.*\.ipynb - id: debug-statements language_version: python3 - repo: https://github.com/pre-commit/mirrors-isort diff --git a/rocket_twin/notebooks/Demonstration.ipynb b/rocket_twin/notebooks/Demonstration.ipynb index 6d09680..720c08a 100644 --- a/rocket_twin/notebooks/Demonstration.ipynb +++ b/rocket_twin/notebooks/Demonstration.ipynb @@ -24,6 +24,8 @@ "outputs": [], "source": [ "from rocket_twin.systems import Station, StationControllerFMU, RocketControllerFMU, StageControllerFMU\n", + "from rocket_twin.drivers import FuelingRocket, VerticalFlyingRocket, Mission\n", + "from rocket_twin.utils import run_sequences\n", "from cosapp.utils import swap_system\n", "from cosapp.drivers import RungeKutta, NonLinearSolver\n", "from cosapp.recorders import DataFrameRecorder\n", @@ -61,10 +63,6 @@ "# Adjust interval between fueling end and launch\n", "sys.time_int = 10.\n", "\n", - "# Set system to fueling mode:\n", - "sys.fueling = True\n", - "sys.rocket.flying = False\n", - "\n", "# Note that fueling and flying can be false at the same time: this happens between the fueling phase end and the launch time" ] }, @@ -104,13 +102,12 @@ "Here we set the parameters for all the fuel tanks (for each stage and the ground). The tanks are assumed to be cylindrical (they have thick walls and a thick bottom), meaning we need to define:\n", "\n", "1. The max fuel output rate\n", - "2. The initial fuel mass\n", - "3. The internal radius\n", - "4. The external radius (same as the rocket radius)\n", - "5. The thickness of the bottom surface\n", - "6. The height\n", - "7. The densities for both the structure and the fuel\n", - "8. In the case of the stage tanks, their position\n", + "2. The internal radius\n", + "3. The external radius (same as the rocket radius)\n", + "4. The thickness of the bottom surface\n", + "5. The height\n", + "6. The densities for both the structure and the fuel\n", + "7. In the case of the stage tanks, their position\n", "\n", "Each tank has a geometry module, which handles the structure and the fuel's shape and properties, and a fuel module, which handles the fuel mass at each instant. Besides their shape and properties (which are directly passed to the geometry module), each tank outputs their current fuel weight, their current fuel exit flow, and the maximum fuel capacity." ] @@ -130,21 +127,6 @@ "sys.rocket.stage_3.tank.fuel.w_out_max = 1." ] }, - { - "cell_type": "code", - "execution_count": null, - "id": "df5a15ed-cbd1-4ea5-abe9-0f2a574fda77", - "metadata": {}, - "outputs": [], - "source": [ - "# Initial fuel mass\n", - "\n", - "sys.g_tank.fuel.weight_p = 20.\n", - "sys.rocket.stage_1.tank.fuel.weight_p = 0.\n", - "sys.rocket.stage_2.tank.fuel.weight_p = 0.\n", - "sys.rocket.stage_3.tank.fuel.weight_p = 0." - ] - }, { "cell_type": "code", "execution_count": null, @@ -642,12 +624,56 @@ " swap_system(sys.rocket[f\"stage_{i}\"].controller, StageControllerFMU(\"controller\", model_path=model_path_s, model_name=model_name_s))" ] }, + { + "cell_type": "markdown", + "id": "d341bae3-a636-4204-bee0-23b3210cafb0", + "metadata": {}, + "source": [ + "## Initial conditions\n", + "\n", + "We consider that the rocket, while at the station, is at the origin of our coordinate system and has null speed. Therefore, the only initial conditions to be defined are the fuel masses in each tank and whether the rocket is mid-fueling or mid-flight, which we define below:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "c7370468-2245-498a-88f7-c86f8d1640c2", + "metadata": {}, + "outputs": [], + "source": [ + "# Initial fuel mass\n", + "\n", + "ground_tank_mass = 2.\n", + "stage1_tank_mass = 5.\n", + "stage2_tank_mass = 6.\n", + "stage3_tank_mass = 7.\n", + "\n", + "# Phase\n", + "\n", + "fuel = False\n", + "flight = True" + ] + }, { "cell_type": "markdown", "id": "4c3cff2c-de08-463a-8af2-14b23221f97a", "metadata": {}, "source": [ - "## Simulation" + "## Simulation\n", + "\n", + "The rocket simulation may be done through three different means:\n", + "\n", + "1. By manually adding a time driver (EulerExplicit or RungeKutta) coupled with a NonLinearSolver, which can be imported from cosapp.drivers;\n", + "2. By using the rocket-specific drivers FuelingRocket (which simulates the fueling phase), VerticalFlyingRocket (which simulates the flight), or Mission (which simulates both), which can be imported from rocket_twin.drivers;\n", + "3. By using the command through sequences, importing the function run_sequences from rocket_twin.utils." + ] + }, + { + "cell_type": "markdown", + "id": "1f5f6cf7-dcec-433f-a910-acae75ef7f8f", + "metadata": {}, + "source": [ + "## Simulation by manually adding drivers" ] }, { @@ -658,19 +684,249 @@ "outputs": [], "source": [ "# Time interval and step\n", + "\n", + "man_sim = False\n", + "\n", "dt = 1.\n", "T = 50.\n", "\n", + "init = {\"g_tank.fuel.weight_p\" : ground_tank_mass,\n", + " \"rocket.stage_1.tank.fuel.weight_p\" : stage1_tank_mass,\n", + " \"rocket.stage_2.tank.fuel.weight_p\" : stage2_tank_mass,\n", + " \"rocket.stage_3.tank.fuel.weight_p\" : stage3_tank_mass,\n", + " \"fueling\" : fuel,\n", + " \"rocket.flying\" : flight,\n", + " }\n", + "\n", "sys.drivers.clear()\n", "driver = sys.add_driver(RungeKutta(order=4, dt=dt))\n", "driver.add_child(NonLinearSolver('solver'))\n", "driver.time_interval = (0, T)\n", "\n", - "includes = [\"rocket.a\", \"rocket.geom.weight\", \"rocket.weight_prop_1\", \"rocket.weight_prop_2\", \"rocket.weight_prop_3\", \"g_tank.weight_prop\"]\n", + "includes = [\"rocket.a\", \"rocket.geom.weight\", \"rocket.weight_prop_1\", \n", + " \"rocket.weight_prop_2\", \"rocket.weight_prop_3\", \"g_tank.weight_prop\"]\n", "\n", "driver.add_recorder(DataFrameRecorder(includes=includes), period=1.0)\n", "\n", - "sys.run_drivers()" + "if man_sim:\n", + " sys.run_drivers()\n", + " data = driver.recorder.export_data()" + ] + }, + { + "cell_type": "markdown", + "id": "cd6b2576-b5bb-4e71-988f-02af1a468cb6", + "metadata": {}, + "source": [ + "## Simulation by rocket_twin drivers" + ] + }, + { + "cell_type": "markdown", + "id": "0b1fbbe2-a2bf-4616-8c7b-151e5d7895d7", + "metadata": {}, + "source": [ + "### Fueling" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "3fba5efd-0cd2-4021-ab22-298aa03bb26a", + "metadata": {}, + "outputs": [], + "source": [ + "fuel_sim = False\n", + "\n", + "dt = 1.\n", + "\n", + "init = {\"g_tank.fuel.weight_p\" : ground_tank_mass,\n", + " \"rocket.stage_1.tank.fuel.weight_p\" : stage1_tank_mass,\n", + " \"rocket.stage_2.tank.fuel.weight_p\" : stage2_tank_mass,\n", + " \"rocket.stage_3.tank.fuel.weight_p\" : stage3_tank_mass,\n", + " \"fueling\" : True,\n", + " \"rocket.flying\" : False,\n", + " }\n", + "\n", + "stop = \"rocket.flying == 1.\"\n", + "\n", + "includes = [\"rocket.a\", \"rocket.geom.weight\", \"rocket.weight_prop_1\", \n", + " \"rocket.weight_prop_2\", \"rocket.weight_prop_3\", \"g_tank.weight_prop\"]\n", + "\n", + "sys.drivers.clear()\n", + "sys.add_driver(FuelingRocket('fr', owner=sys, init=init, stop=stop, includes=includes, dt=dt))\n", + "\n", + "if fuel_sim:\n", + " sys.run_drivers()\n", + " data = sys.drivers[\"fr\"].data" + ] + }, + { + "cell_type": "markdown", + "id": "c9187b92-0273-41a3-befc-d58ffa746a87", + "metadata": {}, + "source": [ + "### Flying" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "380230af-5678-418c-8ba6-6d0995173fa1", + "metadata": {}, + "outputs": [], + "source": [ + "fly_sim = True\n", + "\n", + "dt = 1.\n", + "\n", + "init = {\"g_tank.fuel.weight_p\" : ground_tank_mass,\n", + " \"rocket.stage_1.tank.fuel.weight_p\" : stage1_tank_mass,\n", + " \"rocket.stage_2.tank.fuel.weight_p\" : stage2_tank_mass,\n", + " \"rocket.stage_3.tank.fuel.weight_p\" : stage3_tank_mass,\n", + " \"fueling\" : False,\n", + " \"rocket.flying\" : True,\n", + " }\n", + "\n", + "stop = f\"rocket.stage_{n_stages}.tank.weight_prop < 0\"\n", + "\n", + "includes = [\"rocket.a\", \"rocket.geom.weight\", \"rocket.weight_prop_1\", \n", + " \"rocket.weight_prop_2\", \"rocket.weight_prop_3\", \"g_tank.weight_prop\"]\n", + "\n", + "sys.drivers.clear()\n", + "sys.add_driver(VerticalFlyingRocket('vfr', owner=sys, init=init, stop=stop, includes=includes, dt=dt))\n", + "\n", + "if fly_sim:\n", + " sys.run_drivers()\n", + " data = sys.drivers[\"vfr\"].data" + ] + }, + { + "cell_type": "markdown", + "id": "29b6343b-7ca7-4db4-acff-f33ff3bc745a", + "metadata": {}, + "source": [ + "### Mission (fueling + flying)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "0c5e8840-180f-430b-b37a-3592300355a5", + "metadata": {}, + "outputs": [], + "source": [ + "mis_sim = False\n", + "\n", + "dt = 1.\n", + "\n", + "init = {\"g_tank.fuel.weight_p\" : ground_tank_mass,\n", + " \"rocket.stage_1.tank.fuel.weight_p\" : stage1_tank_mass,\n", + " \"rocket.stage_2.tank.fuel.weight_p\" : stage2_tank_mass,\n", + " \"rocket.stage_3.tank.fuel.weight_p\" : stage3_tank_mass,\n", + " \"fueling\" : True,\n", + " \"rocket.flying\" : False,\n", + " }\n", + "\n", + "stop = f\"rocket.stage_{n_stages}.tank.weight_prop < 0\"\n", + "\n", + "includes = [\"rocket.a\", \"rocket.geom.weight\", \"rocket.weight_prop_1\", \n", + " \"rocket.weight_prop_2\", \"rocket.weight_prop_3\", \"g_tank.weight_prop\"]\n", + "\n", + "sys.drivers.clear()\n", + "sys.add_driver(Mission('mission', owner=sys, init=init, stop=stop, includes=includes, dt=dt))\n", + "\n", + "if mis_sim:\n", + " sys.run_drivers()\n", + " data = sys.drivers[\"mission\"].data" + ] + }, + { + "cell_type": "markdown", + "id": "deee8db0-3aba-4435-93a1-01981c98e8a1", + "metadata": {}, + "source": [ + "## Simulation by cosapp sequences" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "742acffd-710e-478e-bcf6-d6ad9a4a7fe5", + "metadata": {}, + "outputs": [], + "source": [ + "seq_sim = False" + ] + }, + { + "cell_type": "markdown", + "id": "b9a7d713-d977-4bdb-9a4e-f876c423a4ec", + "metadata": {}, + "source": [ + "### Initialisation sequence" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "06f203b4-74b8-4198-92df-918bb0d6c262", + "metadata": {}, + "outputs": [], + "source": [ + "init = {\"g_tank.fuel.weight_p\" : 20.}\n", + "\n", + "seq_init = [{\"name\" : \"start\", \"init\" : init, \"type\" : \"static\"}] \n", + "\n", + "if seq_sim:\n", + " run_sequences(sys, seq_init)" + ] + }, + { + "cell_type": "markdown", + "id": "8051e989-27cf-48c3-866a-f9e9ec366691", + "metadata": {}, + "source": [ + "### Fueling sequence" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "7c094628-fb44-4f43-9cb7-25299e40624c", + "metadata": {}, + "outputs": [], + "source": [ + "stop = f\"rocket.stage_{n_stages}.tank.weight_prop = rocket.stage_{n_stages}.tank.weight_max\"\n", + "\n", + "seq_fuel = [{\"name\" : \"fuel\", \"type\" : \"transient\", \"dt\" : 1.0, \"stop\" : stop}]\n", + "\n", + "if seq_sim:\n", + " run_sequences(sys, seq_fuel)" + ] + }, + { + "cell_type": "markdown", + "id": "e71d863c-4b2a-4aae-982f-b46ee56bad86", + "metadata": {}, + "source": [ + "### Flying sequence" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "a7f0f296-a164-42c8-9251-fda27d9038ed", + "metadata": {}, + "outputs": [], + "source": [ + "stop = f\"rocket.stage_{n_stages}.tank.weight_prop == 0.\"\n", + "\n", + "seq_fly = [{\"name\" : \"flight\", \"type\" : \"transient\", \"dt\" : 1.0, \"stop\" : stop}]\n", + "\n", + "if seq_sim:\n", + " run_sequences(sys, seq_fly)\n", + " data = sys.drivers['rk'].recorder.export_data()" ] }, { @@ -688,8 +944,6 @@ "metadata": {}, "outputs": [], "source": [ - "data = driver.recorder.export_data()\n", - "\n", "acel = np.asarray(data[\"rocket.a\"])\n", "mass = np.asarray(data[\"rocket.geom.weight\"])\n", "time = np.asarray(data[\"time\"])\n",