2025-02-27 22:18:40 +10:00

314 lines
11 KiB
Python

# These could be from the std math lib, but I like the numpy ones better personally
from numpy import sin, cos, pi, sqrt, pow
# Pull a1 support
from a1_support import GRAVITY_ACC, WATER_DENSITY, HELP_MESSAGE
from a1_support import load_data, plot_water_height
# Fill these in with your details
__author__ = "Cal Wing"
__email__ = "cal@wing.id.au"
__date__ = "14/02/2025"
__version__ = "1.0.0"
# Task 1
def determine_power_used(water_mass: float, elevation: float,
pumping_time: float, efficiency: float) -> float:
"""
Calculates the power required to pump a certain mass of water a certain height
taking into account the pumping_time and efficiency.
Parameters:
water_mass (float): the mass of the water pumped [kg]
elevation (float): the height difference [m]
pumping_time (float): the amount of time the pump is running for [hrs]
efficiency (float): the conversion efficiency [%]
Returns:
(float): the power required by the pump [kW]
"""
# Ideal energy needed to lift the water
potenital_energy = water_mass * GRAVITY_ACC * elevation # J = kg * m/s^2 * m = mgh
# Actual amount of energy needed based on eff
# Here an 85% eff means an extra 15% is needed to pump the water up
# [NOTE] I got stuck on this for a bit, unsure if it was my sleep deprived brain but took me
# me a bit to get the efficiency calc.
electrical_energy = potenital_energy / (efficiency/100) # J = J * SCALER
# Actual electrial power used to pump the water
power_used = electrical_energy / (pumping_time*60*60) # W = J / S = J / (hr*60*60)
return power_used / 1e3 # W -> kW
# Task 2
def determine_water_released(gen_power: float, elevation: float,
pumping_time: float, efficiency: float) -> float:
"""
Calculates the mass of water released required to generate a specified power
Parameters:
gen_power (float): the specified power to be generated [kW]
elevation (float): the height difference [m]
pumping_time (float): the time the pump is running for [hrs]
efficiency (float): the conversion efficiency [%]
Returns:
(float): the mass of the water required [kg]
"""
# How much electrical engery was generated?
electrical_energy = (gen_power * 1e3) * (pumping_time*60*60) # J = W * S = (kW * 10^3) * (hrs*60*60)
# Need more potential energy to get electrial energy
# Again here for 85% eff need 15% more potenitial enegry to get pot-eng
potential_energy = electrical_energy * (efficiency/100) # J = J * Scaler
water_mass = potential_energy / (GRAVITY_ACC * elevation) # kg = J / (m/s^2 * m)
return water_mass
# Task 3
def determine_cost_to_pump(gen_power: float, pumping_time: float,
off_peak_tariff: float) -> float:
"""
Calculates the cost of using the pump during off peak period
Parameters:
gen_power (float): the amount of power generated by the pump [kW]
pumping_time (float): the amount of time the pump is running for [hrs]
off_peak_tariff (float): the off-peak tarriff cost for electricity [$/kWh]
Returns:
(float): the cost of running the pump ($)
"""
cost = gen_power * pumping_time * off_peak_tariff
return cost
# Task 4
def calc_speed_at_outlet(water_height: float) -> float:
"""
Calculates the speed of the water at the outlet of the dam
Parameters:
water_height (float): the height of the water in the pipe [m]
Returns:
(float): the speed of the water at the outlet [m/s]
"""
speed = sqrt(2 * water_height * GRAVITY_ACC)
return speed
# Task 5
def calc_new_water_height(old_water_height: float, reservoir_area: float,
outlet_area: float, time_inc: float) -> tuple[float, float]:
water_mass_out = outlet_area * calc_speed_at_outlet(old_water_height) \
* time_inc * WATER_DENSITY
new_water_height = old_water_height - \
(water_mass_out / (reservoir_area * WATER_DENSITY))
return new_water_height, water_mass_out
# Task 6
def calc_heights_water_out(initial_height: float, final_height: float,
reservoir_area: float, outlet_area: float,
time_inc: float
) -> tuple[tuple[float, ...], tuple[float, ...]]:
# Track the water height & mass
water_height, water_mass = [], []
# Do the first iteration
new_water_height, water_mass_out = \
calc_new_water_height(initial_height, reservoir_area,
outlet_area, time_inc)
# Store the new values
water_height.append(new_water_height)
water_mass.append(water_mass_out)
# Do the loop
while water_height[-1] > final_height:
new_water_height, water_mass_out = \
calc_new_water_height(water_height[-1], reservoir_area,
outlet_area, time_inc)
water_height.append(new_water_height)
water_mass.append(water_mass_out)
return water_height, water_mass
# Task 7
def calc_energy_power(heights: tuple[float, ...], water_mass_outs: tuple[float, ...],
relative_elevation: float, efficiency: float,
time_inc: float) -> tuple[tuple[float, ...], tuple[float, ...]]:
energy, power = (), ()
for i in range(len(heights)):
energy_jules = water_mass_outs[i] * GRAVITY_ACC * \
(heights[i] + relative_elevation) * (efficiency/100) # note the comma
energy += energy_jules / 3.6e6, # convert to kWh
power += (energy_jules / time_inc) / 1e3, # convert to kW
return energy, power
# Task 8
def calc_daily_profit(energy: tuple[float, ...], peak_tariff: float,
off_peak_tariff: float, efficiency: float) -> float:
total_profit = sum(energy) * (peak_tariff - off_peak_tariff / pow(efficiency/100, 2))
return total_profit
# Task 9
def print_table(start_relative_elevation: float, step_size: float,
num_steps: int, initial_height: float, final_height: float,
reservoir_area: float, outlet_area: float, time_inc: float,
peak_tariff: float, off_peak_tariff: float, efficiency: float):
# Print the header
print("#"*79)
print("# Relative elevation (m) # Daily Profit ($) # Total Energy (kWh) #")
print("#"*79)
table_data = ()
rel_elevation = start_relative_elevation
for i in range(num_steps):
heights, water_mass_outs = calc_heights_water_out(initial_height, final_height, reservoir_area, outlet_area, time_inc)
energy, _ = calc_energy_power(heights, water_mass_outs, rel_elevation, efficiency, time_inc)
total_energy = sum(energy)
profit = calc_daily_profit(energy, peak_tariff, off_peak_tariff, efficiency)
table_data += (rel_elevation, profit, total_energy),
rel_elevation += step_size
# Print the table
for elevation, profit, total_energy in table_data:
print(f"#{elevation:^25d}#{profit:^25.2f}#{total_energy:^25.2f}#")
print("#"*79)
def main():
cmd, data = None, None
while True:
cmd = input("Please enter a command: ").lower()
# Help CMD
if cmd[0] == "h":
print(HELP_MESSAGE)
# Quit
elif cmd[0] == "q":
while True:
cmd = input("Are you sure (y/n): ").lower()
if cmd in ['y', 'n']:
break
print("Please enter a valid reponse")
if cmd == 'y':
break
# Read Data
elif cmd[0] == "r":
directory = input("Please specify the directory: ")
filename = input("Please specify the filename: ")
data = load_data(directory, filename)
# Print Table
elif cmd[0] == "p":
if data is None:
print("Please load data before using this command")
continue
cmds = cmd.split()
if len(cmds) != 4:
print("Please enter the correct number of arguments")
continue
# This makes ints & floats
foo = ()
for c in cmds:
if "." in str(c):
foo += float(c),
elif c.isnumeric():
foo += int(c),
else:
foo += c,
print_table(*foo[1:], *data)
# Make Graph
elif cmd[0] == "s":
if data is None:
print("Please load data before using this command")
continue
print("Simulating water heights...")
heights, _ = calc_heights_water_out(*data[0:5])
plot_water_height(heights, data[4])
# Catch All
else:
print("Please enter a valid command")
##### End of Assisgnment #####
if __name__ == '__main__':
# See if I get what the task sheet wants
# [NOTE] It seems I am witing my own test suite :/ that wasn't the initention lol
# Tests do equal what I get when i test it in the shell
def sheet_tasks():
from debug_lib import NO_EVAL, TUPLE_EVAL
from debug_lib import compair_outputs, auto_input
# from a1_alex import calc_daily_profit
TASKS = (
(determine_power_used, (5e6, 250, 8, 85), 500.9191176470588),
(determine_water_released, (300, 250, 8, 85), 2994495.4128440367),
(determine_cost_to_pump, (300, 8, 0.02), 48),
(calc_speed_at_outlet, (30,), 24.261079942986875),
(calc_new_water_height, (20, 40000, 1, 30), (19.985143183382704, 592567.1021442247)),
(calc_heights_water_out, (40, 5, 40000, 1, 30), ((39.97898928844613, 39.95798409574207, 39.93698442188801), (838016.4324684857, 837796.3120398963, 837576.1916037091), TUPLE_EVAL)),
(calc_energy_power, tuple(i for i in calc_heights_water_out(30, 20, 40000, 1, 30)) + (200, 85, 30), ((386.6002008976669, 386.4523727180418, 386.3045723539472), (46392.024107720026, 46374.28472616501, 46356.548682473665), TUPLE_EVAL)),
(calc_daily_profit, (calc_energy_power(*(tuple(i for i in calc_heights_water_out(30, 20, 40000, 1, 30)) + (200, 85, 30)))[0], 0.02, 0.005, 85), 2718.700033709491)
)
compair_outputs(TASKS)
print("\nTask 8")
print_table(280, 20, 6, 30, 20, 40000, 1, 30, 0.02, 0.005, 85)
print("\nTask 9")
global input # This is some magic I wrote a while ago to be an automatic input func
input = auto_input([
"h", "s", "q", "n",
"r", "test", "test_data.txt",
"p 280 20 6",
"r", "test", "test_data_2.txt",
's',
"q", "y"
])
main()
sheet_tasks()