diff --git a/lib/controllers/motor.py b/lib/controllers/motor.py index 62950a2..abad70c 100644 --- a/lib/controllers/motor.py +++ b/lib/controllers/motor.py @@ -1,9 +1,12 @@ from fastapi import Response, status from typing import Any, Dict, Union from rocketpy.motors.solid_motor import SolidMotor +from rocketpy.motors.liquid_motor import LiquidMotor +from rocketpy.motors.hybrid_motor import HybridMotor +from rocketpy import TankGeometry, Fluid import jsonpickle -from lib.models.motor import Motor +from lib.models.motor import Motor, MotorKinds from lib.repositories.motor import MotorRepository from lib.views.motor import MotorSummary, MotorData, MotorCreated, MotorUpdated, MotorDeleted, MotorPickle @@ -18,23 +21,52 @@ class MotorController(): - Create a rocketpy.Motor object from a Motor model object. """ def __init__(self, motor: Motor, motor_kind, motor_option): - rocketpy_motor = SolidMotor( - burn_time=motor.burn_time, + motor_core = { + thrust_source: f"lib/data/motors/{motor.thrust_source.value}.eng", + burn_time: motor.burn_time, + nozzle_radius: motor.nozzle_radius, + dry_mass: motor.dry_mass, + dry_inertia: motor.dry_inertia, + center_of_dry_mass_position: motor.center_of_dry_mass_position + } + motors = { + MotorKinds.solid: SolidMotor( + **motor_core, grain_number=motor.grain_number, grain_density=motor.grain_density, grain_outer_radius=motor.grain_outer_radius, grain_initial_inner_radius=motor.grain_initial_inner_radius, grain_initial_height=motor.grain_initial_height, - grains_center_of_mass_position=-motor.grains_center_of_mass_position, - thrust_source=f"lib/data/motors/{motor.thrust_source.value}.eng", + grains_center_of_mass_position=motor.grains_center_of_mass_position, grain_separation=motor.grain_separation, - nozzle_radius=motor.nozzle_radius, - dry_mass=motor.dry_mass, - center_of_dry_mass_position=motor.center_of_dry_mass_position, - dry_inertia=motor.dry_inertia, throat_radius=motor.throat_radius, interpolation_method=motor.interpolation_method - ) + ), + MotorKinds.liquid: LiquidMotor( + **motor_core, + tanks=motor.tanks + ), + MotorKinds.hybrid: HybridMotor( + **motor_core, + throat_radius=motor.throat_radius, + grain_number=motor.grain_number, + grain_density=motor.grain_density, + grain_outer_radius=motor.grain_outer_radius, + grain_initial_inner_radius=motor.grain_initial_inner_radius, + grain_initial_height=motor.grain_initial_height, + grain_separation=motor.grain_separation, + grains_center_of_mass_position=motor.grains_center_of_mass_position, + tanks=motor.tanks + ) + } + + rocketpy_motor = motors[motor_kind] + for tank in motor.tanks: + tank.geometry = TankGeometry(tank.geometry) + tank.gas = Fluid(tank.gas.name, tank.gas.density) + tank.liquid = Fluid(tank.liquid.name, tank.liquid.density) + rocketpy_motor.add_tank(tank.tank, tank.position) + self.rocketpy_motor = rocketpy_motor self.motor = motor diff --git a/lib/models/motor.py b/lib/models/motor.py index df91b13..35fc9aa 100644 --- a/lib/models/motor.py +++ b/lib/models/motor.py @@ -1,4 +1,5 @@ -from typing import Optional, Tuple +from rocketpy import LevelBasedTank, MassBasedTank, MassFlowRateBasedTank, UllageBasedTank, SolidMotor, LiquidMotor, HybridMotor +from typing import Optional, Tuple, List from enum import Enum from pydantic import BaseModel @@ -14,21 +15,76 @@ class MotorKinds(str, Enum): class MotorEngine(BaseModel, frozen=True): pass +class TankKinds(str, Enum): + level: str = "Level" + mass: str = "Mass" + mass_flow: str = "MassFlow" + ullage: str = "Ullage" + +class TankFluids(BaseModel, frozen=True): + name: str = "FluidName" + density: float = 100.0 + +class MotorTank(BaseModel, frozen=True): + tank_kind: TankKinds = TankKinds.mass_flow + position: float = 1.0 + name: str = "Tank" + geometry: "Tuple[Tuple[float, float]]" = ((0, 0), (0, 1)) + flux_time: "List[float]" = [0, 8] + gas: TankFluids = TankFluids() + liquid: TankFluids = TankFluids() + discretize: Optional[int] = 100 + liquid_height: Optional[float] + liquid_mass: Optional[float] = 5.0 + gass_mass: Optional[float] = 0.1 + gas_mass_flow_rate_in: Optional[float] + gas_mass_flow_rate_out: Optional[float] + liquid_mass_flow_rate_in: Optional[float] + liquid_mass_flow_rate_out: Optional[float] + ullage: Optional[float] + + def __init__(self, **data): + super().__init__(**data) + tank_core = { + name: self.name, + geometry: self.geometry, + flux_time: self.flux_time, + gas: self.gas, + liquid: self.liquid, + discretize: self.discretize + } + tanks = { + TanksKind.level: LevelBasedTank(**tank_core, liquid_height=self.liquid_height), + TanksKind.mass: MassBasedTank(**tank_core, + liquid_mass=self.liquid_mass, + gas_mass=self.gas_mass + ), + TanksKind.mass_flow: MassFlowRateBasedTank(**tank_core, + gas_mass_flow_rate_in=self.gas_mass_flow_rate_in, + gas_mass_flow_rate_out=self.gas_mass_flow_rate_out, + liquid_mass_flow_rate_in=self.liquid_mass_flow_rate_in, + liquid_mass_flow_rate_out=self.liquid_mass_flow_rate_out + ), + TanksKind.ullage: UllageBasedTank(**tank_core, ullage=self.ullage), + } + self.tank = tanks[self.tank_kind] + class Motor(BaseModel, frozen=True): + thrust_source: MotorEngine = MotorEngine() burn_time: float = 3.9 + nozzle_radius: float = 0.033 dry_mass: float = 1.815 dry_inertia: "Tuple[float, float, float]" = (0.125, 0.125, 0.002) center_of_dry_mass_position: float = 0.317 - grain_number: int = 5 - grain_density: float = 1815 - grain_outer_radius: float = 0.033 - grain_initial_inner_radius: float = 0.015 - grain_initial_height: float = 0.12 - grains_center_of_mass_position: float = -0.85704 + grain_number: Optional[int] = 5 + grain_density: Optional[float] = 1815 + grain_outer_radius: Optional[float] = 0.033 + grain_initial_inner_radius: Optional[float] = 0.015 + grain_initial_height: Optional[float] = 0.12 + grains_center_of_mass_position: Optional[float] = -0.85704 #TBD: thrust_source must be the id of a previously uploaded .eng file and a list of "default" files must be provided in the api docs - thrust_source: MotorEngine = MotorEngine() - grain_separation: float = 0.005 - nozzle_radius: float = 0.033 - throat_radius: float = 0.011 - interpolation_method: str = "linear" - coordinate_system_orientation: str = "nozzle_to_combustion_chamber" + grain_separation: Optional[float] = 0.005 + throat_radius: Optional[float] = 0.011 + interpolation_method: Optional[str] = "linear" + coordinate_system_orientation: Optional[str] = "nozzle_to_combustion_chamber" + tanks: Optional["List[MotorTank]"]