class PowerGeneration(Subsystem): """Contains all Data on Power Generation.""" def __init__(self, data): """Init the Power Generation.""" self.data = data self.powergeneration = data.powergeneration efficiency = self.powergeneration["Reactor Efficiency"] self.no_reactors = IntVar(value=1) self.power_need = QuantityVar(unit="W") self.power_reactor = DoubleVar() self.mass_reactor = QuantityVar(unit="g") self.power_overall = QuantityVar(unit="W") self.power_effective = QuantityVar(unit="W") self.waste_heat = QuantityVar(unit="W") self.mass_total_reactor = QuantityVar(unit="g") self.efficiency = DoubleVar(value=efficiency) def make_entry(self, frame): """Make the Entry Form.""" entry = { "Power per Reactor": { "value": self.power_reactor, "unit": "MW", "type": "Spinbox", "config": { "from": 50, "to": 100 * 50, "increment": 50 } } } self._make_entry(frame, "Power Generation", entry) def make_display(self, frame): """Make the Data Display.""" data = { "Power Needed": { "value": self.power_need, }, "Reactor Efficiency": { "value": self.efficiency, }, "Needed Ractors": { "value": self.no_reactors, }, "Overall Reactor Power": { "value": self.power_overall, }, "Effective Power Overall": { "value": self.power_effective, }, "Waste Heat": { "value": self.waste_heat, }, "Mass per Reactor": { "value": self.mass_reactor, }, "Total Reactor Mass": { "value": self.mass_total_reactor, }, } self._make_display(frame, "Reactor Data", data) def calculate(self): """Do the calculation.""" efficiency = self.efficiency.get() power_reactor = self.power_reactor.get() * 1e6 reactor_mass = self.powergeneration["Reactor Mass"] / 1000 power_need = 0 for _, subsystem in self.data.power.items(): power_need += subsystem power_effective = power_need power_overall = self._roundup(power_need / efficiency, power_reactor) no_reactors = power_overall / power_reactor print(power_need, ', ', power_overall, ', ', no_reactors) waste_heat = power_overall - power_effective mass_reactor = power_reactor * reactor_mass mass_total = mass_reactor * no_reactors self.data.masses["Reactors"] = mass_total self.data.wasteheat["Reactors"] = waste_heat self.data.volumes["Reactors"] = mass_total * \ self.powergeneration["Volume"] print(mass_reactor) self.power_need.set(power_need) self.no_reactors.set(no_reactors) self.power_overall.set(power_overall) self.mass_reactor.set(mass_reactor) self.power_effective.set(power_effective) self.waste_heat.set(waste_heat) self.mass_total_reactor.set(mass_total)
class Size(Subsystem): """Calculates the Volume of the Spacecraft.""" def __init__(self, data): """Initalize the Class.""" self.data = data self.front_diameter = DoubleVar() self.back_diameter = DoubleVar() self.length = QuantityVar(unit="m") self.volume_total = QuantityVar(unit="m³") self.volume_propellant_H2O = QuantityVar(unit="m³") self.volume_propellant_D2 = QuantityVar(unit="m³") self.volume_propellant_H3 = QuantityVar(unit="m³") self.volume_lifesupport = QuantityVar(unit="m³") self.volume_reactors = QuantityVar(unit="m³") self.volume_thrusters = QuantityVar(unit="m³") self.volume_aux_thrusters = QuantityVar(unit="m³") def make_entry(self, frame): """Make the Entry Form.""" entry = { "Front Diameter": { "value": self.front_diameter, "unit": "m" }, "Rear Diameter": { "value": self.back_diameter, "unit": "m" }, } self._make_entry(frame, "Propulsion", entry) def make_display(self, frame): """Make the Data Display.""" data = { "Volume Propellant (H2O)": { "value": self.volume_propellant_H2O, }, "Volume Propellant (Helium_3)": { "value": self.volume_propellant_H3, }, "Volume Propellant (Deuterium)": { "value": self.volume_propellant_D2, }, "Volume Lifesupport": { "value": self.volume_lifesupport, }, "Volume Reactors": { "value": self.volume_reactors, }, "Volume Thrusters": { "value": self.volume_thrusters, }, "Volume Auxiliary Thrusters": { "value": self.volume_aux_thrusters, }, "Volume Total": { "value": self.volume_total, }, } self._make_display(frame, "Propulsion Data", data) def calculate(self): """Do the calculations.""" print("Calculate!") volume_H2O = self.data.volumes["Propellant H2O"] volume_H3 = self.data.volumes["Propellant H3"] volume_D2 = self.data.volumes["Propellant D2"] volume_lifesupport = self.data.volumes["Lifesupport"] volume_thrusters = self.data.volumes["Propulsion"] volume_reactors = self.data.volumes["Reactors"] volume_aux_thrusters = self.data.volumes["Auxiliary Thrusters"] volume_total = 0 for _, subsystem in self.data.volumes.items(): volume_total += subsystem self.volume_total.set(volume_total) self.volume_propellant_H2O.set(volume_H2O) self.volume_propellant_H3.set(volume_H3) self.volume_propellant_D2.set(volume_D2) self.volume_lifesupport.set(volume_lifesupport) self.volume_reactors.set(volume_reactors) self.volume_thrusters.set(volume_thrusters) self.volume_aux_thrusters.set(volume_aux_thrusters)
class Propulsion(Subsystem): """Contains the Propulsion Data.""" def __init__(self, data): """Init the Propulsion.""" self.data = data self.propulsion = data.propulsion self.max_acceleration = DoubleVar() self.no_thrusters = IntVar(value=2) self.power_thruster = DoubleVar(value=750) self.power_total_thruster = QuantityVar(unit="W") self.mass_total_thruster = QuantityVar(unit="g") self.waste_power = QuantityVar(unit="W") def make_entry(self, frame): """Make the Entry Form.""" entry = { "Max Acceneration": { "value": self.max_acceleration, "unit": "m/s²" }, "Thruster Power": { "value": self.power_thruster, "unit": "GW" }, "Number of Thrusters": { "value": self.no_thrusters, "unit": "" }, } self._make_entry(frame, "Propulsion", entry) def make_display(self, frame): """Make the Data Display.""" data = { "Total Thruster Power": { "value": self.power_total_thruster, }, "Total Thruster Mass": { "value": self.mass_total_thruster, }, "Retained Waste Power": { "value": self.waste_power, } } self._make_display(frame, "Propulsion Data", data) def calculate(self): """Do the calculations.""" power_thruster = self.power_thruster.get() * 1e9 # max_acceleration = self.max_acceleration.get() no_thrusters = self.no_thrusters.get() mass_thruster = power_thruster * self.propulsion["Thruster Mass"] / 1e6 power_total_thruster = power_thruster * no_thrusters mass_total_thruster = mass_thruster * no_thrusters waste_power = power_total_thruster * self.propulsion["Waste Factor"] self.data.masses["Thrusters"] = mass_total_thruster self.data.wasteheat["Thrusters"] = waste_power self.data.volumes["Propulsion"] = mass_total_thruster * \ self.propulsion["Volume"] self.data.thruster_data["Power"] = power_total_thruster self.mass_total_thruster.set(mass_total_thruster) self.power_total_thruster.set(power_total_thruster) self.waste_power.set(waste_power)
class LifeSupport(Subsystem): """Contains the Life Support Data.""" def __init__(self, data): """Init the Life Support.""" self.data = data self.life_support_data = data.life_support self.crew = IntVar() self.endurance = IntVar() self.mass_supplies_nonrenewable = QuantityVar(unit="g") self.mass_supplies_renewable = QuantityVar(unit="g") self.mass_supplies = QuantityVar(unit="g") self.volume_habitat = QuantityVar(unit="m³") self.mass_habitat = QuantityVar(unit="g") self.volume_supplies = QuantityVar(unit="m³") self.volume_total = QuantityVar(unit="m³") self.mass_total = QuantityVar(unit="g") self.power_requirements = QuantityVar(unit="W") self.radiator = Radiator(data, "Life Support") def make_entry(self, frame): """Create the Entry Form for Data.""" entry = { "Crew size": { "value": self.crew, "unit": "" }, "Endurance": { "value": self.endurance, "unit": "days", "type": "Spinbox", "config": { "from": 30, "to": 50 * 30, "increment": 30 } } } self._make_entry(frame, "Crew", entry) def make_display(self, frame): """Create the Data Display for Data.""" self.data_display = MultiDisplay(frame, "Crew Data") self.radiator.make_display(self.data_display.frame) data = { "Non-Renewable Supplies": { "value": self.mass_supplies_nonrenewable, }, "Renewable Supplies": { "value": self.mass_supplies_renewable, }, "Supplies Volume": { "value": self.volume_supplies, }, "Total Supplies Mass": { "value": self.mass_supplies, }, "Habitat Volume": { "value": self.volume_habitat, }, "Habitat Mass": { "value": self.mass_habitat, }, "Total Volume": { "value": self.volume_total, }, "Total Mass": { "value": self.mass_total, }, "Energy Requirements": { "value": self.power_requirements, }, "Radiator": { "value": self.radiator.data_display } } self.data_display.make_display(data) self.data_display.frame.grid(column=1, row=1, sticky='new', padx=5) def calculate(self): """Calculates the Life support Data.""" crew = self.crew.get() endurance = self.endurance.get() mass_supplies_nonrenewable = crew * endurance \ * self.life_support_data["Non-renewable Supplies"] * 1000 mass_supplies_renewable = crew * endurance * \ self.life_support_data["Renewable Supplies"] * 1000 volume_habitat = crew * self.life_support_data["Habitat Volume"] mass_habitat = volume_habitat * self.life_support_data["Habitat Mass"] \ * 1000 volume_supplies = (mass_supplies_renewable + mass_supplies_nonrenewable) \ / self.life_support_data["Supply Volume"] / 1000 waste_heat = crew * self.life_support_data["Waste Heat"] * 1e3 self.radiator.calculate(waste_heat) power_requirements = crew * \ self.life_support_data["Energy Requirements"] * 1e6 volume_total = (volume_supplies + volume_habitat) * 1.1 mass_total = mass_habitat + mass_supplies_renewable + mass_supplies_nonrenewable self.data.masses["Lifesupport"] = mass_total self.data.power["LifeSupport"] = power_requirements self.radiator.calculate(waste_heat) self.data.volumes["Lifesupport"] = volume_total # Change the Labels self.mass_supplies_nonrenewable.set(mass_supplies_nonrenewable) self.mass_supplies_renewable.set(mass_supplies_renewable) self.mass_supplies.set(mass_supplies_renewable + mass_supplies_nonrenewable) self.volume_habitat.set(volume_habitat) self.volume_supplies.set(volume_supplies) self.volume_total.set(volume_total) self.mass_habitat.set(mass_habitat) self.mass_total.set(mass_total) self.power_requirements.set(power_requirements)
class Radiator(Subsystem): """Contains Radiator Data.""" def __init__(self, data, type): """Init the Radiator.""" self.data = data self.radiators = data.radiators self.radiator_data = data.radiators[type] self.radiators_type = StringVar(value=type) self.mass = QuantityVar(unit="g") self.area = QuantityVar(unit="m²") self.waste_heat = QuantityVar(unit="W") self.radiator_temperature = QuantityVar(unit="K") def make_entry(self, frame): """Creates the Entry for Radiator Stuff.""" entry = { "Radiator": { "value": self.radiators_type, "unit": "", "type": "Combobox", "list": [key for key in self.radiators] } } self._make_entry(frame, "Auxiliary Thruster", entry) def make_display(self, frame=None): """Creates the Display for the Radiator Stuff.""" data = { "Radiator Type": { "value": self.radiators_type, }, "Radiator Temperature": { "value": self.radiator_temperature, }, "Waste Heat": { "value": self.waste_heat, }, "Area": { "value": self.area, }, "Mass": { "value": self.mass, } } self._make_display(frame, "Radiators", data) def calculate(self, waste_heat=0): """Calculates the Radiator Data.""" radiator_type = self.radiators_type.get() data = self.radiators[radiator_type] if not waste_heat: for _, subsystem in self.data.wasteheat.items(): waste_heat += subsystem self.waste_heat.set(waste_heat) area = waste_heat / (data["Specific area heat"] * 1000) mass = (area * 1000) * data["Specific area mass"] self.data.masses["Lifesupport Radiators"] = mass self.area.set(area) self.mass.set(mass) self.radiator_temperature.set( self.radiators[radiator_type]["Radiator Temperature"]) def make_tab(self, root): """Creates a Tab Widgets with the Entry and Data Displays. Makes use of self.make_entry and self.make_display. """ self.frame = Frame(root) self.make_entry(self.frame) self.make_display(self.frame) return self.frame
class Spacecraft(Subsystem): """Spacecraft Class.""" def __init__(self, data): """Init the Spacecraft.""" self.data = data self.subsections = { "Lifesupport": LifeSupport(data), "Propulsion": Propulsion(data), "Aux Thrusters": AuxThrusters(data), "Power Generation": PowerGeneration(data), "Radiators": Radiator(data, "Microtube Array"), } self.no_reactors = IntVar() self.mass_ratio = DoubleVar(value=3) self.mass_armor = DoubleVar() self.mass_defensive = DoubleVar() self.mass_cargo = DoubleVar() self.mass_other = DoubleVar() self.mass_lifesupport = QuantityVar(unit="g") self.mass_propulsion = QuantityVar(unit="g") self.mass_reactor = QuantityVar(unit="g") self.mass_aux_thrusters = QuantityVar(unit="g") self.mass_total_dry = QuantityVar(unit="g") self.mass_total_wet = QuantityVar(unit="g") self.mass_propellant = QuantityVar(unit="g") self.mass_H2O = QuantityVar(unit="g") self.mass_H3 = QuantityVar(unit="g") self.mass_D2 = QuantityVar(unit="g") self.sizes = Size(data) self.velocities = VelocityProfile(data) def calculate(self): """Calculates the spacecraft.""" for _, subsection in self.subsections.items(): subsection.calculate() mass_lifesupport = self.data.masses["Lifesupport"] mass_propulsion = self.data.masses["Thrusters"] mass_reactor = self.data.masses["Reactors"] mass_aux_thrusters = self.data.masses["Auxiliary Thrusters"] mass_total_dry = self.mass_armor.get() + \ self.mass_cargo.get() + \ self.mass_other.get() + \ self.mass_defensive.get() + \ mass_aux_thrusters + \ mass_propulsion + \ mass_lifesupport + \ mass_reactor mass_propellant = mass_total_dry * self.mass_ratio.get() mass_total_wet = mass_total_dry + mass_propellant mass_H3 = mass_propellant / 750 mass_D2 = mass_H3 * 1.25 mass_H2O = mass_propellant - mass_D2 - mass_H3 volume_H3 = mass_H3 / (442.7 * 1e3) volume_D2 = mass_D2 / (169 * 1e3) volume_H2O = mass_H2O / (1000 * 1e3) self.data.volumes["Propellant H2O"] = volume_H2O self.data.volumes["Propellant H3"] = volume_H3 self.data.volumes["Propellant D2"] = volume_D2 self.data.thruster_data["Mass Ratio"] = self.mass_ratio.get() self.data.thruster_data["Mass"] = mass_total_wet self.sizes.calculate() self.velocities.calculate() self.mass_lifesupport.set(mass_lifesupport) self.mass_propulsion.set(mass_propulsion) self.mass_reactor.set(mass_reactor) self.mass_total_dry.set(mass_total_dry) self.mass_propellant.set(mass_propellant) self.mass_total_wet.set(mass_total_wet) self.mass_aux_thrusters.set(mass_aux_thrusters) self.mass_H2O.set(mass_H2O) self.mass_D2.set(mass_D2) self.mass_H3.set(mass_H3) def make_entry(self, frame): """Creates the Multi Entry Widget.""" entry = { "Armor Mass": { "value": self.mass_armor, "unit": "kg" }, "Cargo Mass": { "value": self.mass_cargo, "unit": "kg" }, "Other Mass": { "value": self.mass_other, "unit": "kg" }, "Mass Ratio": { "value": self.mass_ratio, "unit": "" } } self._make_entry(frame, "Other Entries", entry) def make_display(self, frame): """Creates the Multi Display Widget.""" data = { "Overall Lifesupport Mass": { "value": self.mass_lifesupport, }, "Overall Propulsion Mass": { "value": self.mass_propulsion, }, "Overall Auxiliary Thruster Mass": { "value": self.mass_aux_thrusters, }, "Overall Reactor Mass": { "value": self.mass_reactor, }, "Propellant Mass": { "value": self.mass_propellant, }, "Propellant Mass (H2O)": { "value": self.mass_H2O, }, "Propellant Mass (Helium-3)": { "value": self.mass_H3, }, "Propellant Mass (Deuterium)": { "value": self.mass_D2, }, "Total Dry Mass": { "value": self.mass_total_dry, }, "Total Wet Mass": { "value": self.mass_total_wet, } } self._make_display(frame, "Masses", data)
class AuxThrusters(Subsystem): """Class for Auxiliary Thrusters.""" def __init__(self, data): """Initialize the class.""" self.data = data self.aux_thrusters = data.aux_thrusters self.aux_thruster = StringVar() self.power_aux_thrusters = QuantityVar(unit='W') self.mass_aux_thrusters = QuantityVar(unit='g') self.thrust_aux_thrusters = QuantityVar(unit='N') self.no_thrusters = IntVar(value=6 * 4) self.power_total = QuantityVar(unit='W') self.mass_total = QuantityVar(unit='g') self.thrust_total_direction = QuantityVar(unit='N') def make_entry(self, frame): """Make the Data Entry.""" entry = { "Auxiliary Thruster": { "value": self.aux_thruster, "unit": "", "type": "Combobox", "list": [key for key in self.aux_thrusters] } } self._make_entry(frame, "Auxiliary Thruster", entry) def make_display(self, frame): """Make the Data Display.""" data = { "Auxiliary Thruster Power": { "value": self.power_aux_thrusters, }, "Auxiliary Thruster Mass": { "value": self.mass_aux_thrusters, }, "Thrust per Auxiliary Thruster": { "value": self.thrust_aux_thrusters, }, "Number of Auxiliary Thrusters": { "value": self.no_thrusters, }, "Total Auxiliary Thruster Power": { "value": self.power_total, }, "Total Auxiliary Thruster Mass": { "value": self.mass_total, }, "Total Thrust per Direction": { "value": self.thrust_total_direction, } } self._make_display(frame, "Auxiliary Thruster", data) def calculate(self): """Calculates the Data.""" thruster = self.aux_thruster.get() thruster_data = self.aux_thrusters[thruster] power_aux_thrusters = thruster_data['Power'] * 1e6 mass_aux_thrusters = thruster_data['Thruster Mass'] * 1e3 thrust_aux_thrusters = thruster_data['Thrust'] * 1e3 no_thrusters = self.no_thrusters.get() power_total = no_thrusters * power_aux_thrusters mass_total = no_thrusters * mass_aux_thrusters thrust_total_direction = no_thrusters * thrust_aux_thrusters / 6 self.data.masses["Auxiliary Thrusters"] = mass_total self.data.power["Auxiliary Thrusters"] = power_total self.data.volumes["Auxiliary Thrusters"] = mass_total * \ thruster_data["Volume"] self.power_aux_thrusters.set(power_aux_thrusters) self.mass_aux_thrusters.set(mass_aux_thrusters) self.thrust_aux_thrusters.set(thrust_aux_thrusters) self.power_total.set(power_total) self.mass_total.set(mass_total) self.thrust_total_direction.set(thrust_total_direction)