From 619478dae3b3c116c0ecdfecdd2a02e769b47168 Mon Sep 17 00:00:00 2001 From: Cal Wing Date: Thu, 27 Feb 2025 20:46:41 +1000 Subject: [PATCH] Add alex's code as referance & re-generate output for compairasons --- a1.py | 19 ++-- a1_alex.py | 284 ++++++++++++++++++++++++++++++++++++++++++++++++++ alex_dump.txt | 35 +++++++ debug_lib.py | 3 +- 4 files changed, 330 insertions(+), 11 deletions(-) create mode 100644 a1_alex.py create mode 100644 alex_dump.txt diff --git a/a1.py b/a1.py index fec92c8..e29e0b5 100644 --- a/a1.py +++ b/a1.py @@ -1,5 +1,5 @@ # These could be from the std math lib, but I like the numpy ones better personally -from numpy import sin, cos, pi, sqrt +from numpy import sin, cos, pi, sqrt, pow # Pull a1 support from a1_support import GRAVITY_ACC, WATER_DENSITY, HELP_MESSAGE @@ -158,11 +158,8 @@ def calc_energy_power(heights: tuple[float, ...], water_mass_outs: tuple[float, energy_jules = water_mass_outs[i] * GRAVITY_ACC * \ (heights[i] + relative_elevation) * (efficiency/100) # note the comma - energy += energy_jules / 3.6e+6, # convert to kWh - - power_watts = energy[i] / time_inc - - power += power_watts / 1e3, # convert to kW + energy += energy_jules / 3.6e6, # convert to kWh + power += (energy_jules / time_inc) / 1e3, # convert to kW return energy, power @@ -170,9 +167,9 @@ def calc_energy_power(heights: tuple[float, ...], water_mass_outs: tuple[float, 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 0.0 + return total_profit # 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 @@ -181,6 +178,8 @@ def sheet_tasks(): from debug_lib import NO_EVAL, TUPLE_EVAL from debug_lib import compair_outputs + # 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), @@ -188,8 +187,8 @@ def sheet_tasks(): (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), ((387.7129370269342, 387.56468335928287, 387.4164575872225), (46525.5524432321, 46507.762003113945, 46489.9749104667), 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), 2726.5251609213365) + (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) diff --git a/a1_alex.py b/a1_alex.py new file mode 100644 index 0000000..ad0e23e --- /dev/null +++ b/a1_alex.py @@ -0,0 +1,284 @@ +from a1_support import * + +def determine_power_used(water_mass, elevation, pumping_time, efficiency): + """ + 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] + """ + potential_energy = water_mass * elevation * GRAVITY_ACC + power = potential_energy / (pumping_time*3600 * (efficiency/100))/1000 + return power + +def determine_water_released(gen_power, elevation, pumping_time, efficiency): + """ + 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 water required [kg] + """ + power = gen_power * 1000 + water_mass = power * pumping_time*3600 * (efficiency/100) / (elevation * GRAVITY_ACC) + return water_mass + +def determine_cost_to_pump(gen_power, pumping_time, off_peak_tariff): + """ + 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 + +def calc_speed_at_outlet(water_height): + """ + 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 = (2*GRAVITY_ACC*water_height)**0.5 + return speed + +def calc_new_water_height(old_water_height, reservoir_area, outlet_area, time_inc): + """ + Calculates the new water height in the reservoir after a certain time increment + + Parameters: + old_water_height (float): the initial height of the water in the reservoir [m] + reservoir_area (float): the area of the reservoir [m^2] + outlet_area (float): the area of the outlet [m^2] + time_inc (float): the time increment [s] + + Returns: + (tuple): the new water height and the mass of water outflow + """ + water_mass_out = outlet_area * calc_speed_at_outlet(old_water_height) * WATER_DENSITY * time_inc + + new_water_height = old_water_height - (water_mass_out / (reservoir_area * WATER_DENSITY)) + return new_water_height, water_mass_out + +def calc_heights_water_out(initial_height, final_height, reservoir_area, outlet_area, time_inc): + """ + Calculates the water height in the reservoir and the water outflow after a certain time increment + + Parameters: + initial_height (float): the initial height of the water in the reservoir [m] + final_height (float): the final height of the water in the reservoir [m] + reservoir_area (float): the area of the reservoir [m^2] + outlet_area (float): the area of the outlet [m^2] + time_inc (float): the time increment [s] + + Returns: + (tuple): the water heights and water masses + """ + water_heights = () + water_height = initial_height + water_masses = () + + while water_height > final_height: + water_height, water_mass_out = calc_new_water_height(water_height, reservoir_area, outlet_area, time_inc) + water_heights += (water_height, ) + water_masses += (water_mass_out, ) + + return water_heights, water_masses + +def calc_energy_power(heights, water_mass_outs, relative_elevation, efficiency, time_inc): + """ + Calculates the energy generated and the power generated + + Parameters: + heights (tuple): the water heights [m] + water_mass_outs (tuple): the water masses [kg] + relative_elevation (float): the height difference between the generators and the dam [m] + efficiency (float): the conversion efficiency [%] + time_inc (float): the time increment [s] + + Returns: + (tuple): the energy generated and the power generated [kWh, kW] + """ + energies = () + powers = () + for i in range(len(heights)): + energy = water_mass_outs[i] * GRAVITY_ACC * (heights[i] + relative_elevation) * efficiency / 100 /1000 / 3600 + power = energy*3600/(time_inc) + energies += (energy, ) + powers += (power, ) + + return energies, powers + +def calc_daily_profit(energies, peak_tariff, off_peak_tariff, efficiency): + """ + Calculates the daily profit generated by the dam + + Parameters: + energy (tuple): the energy generated by the dam [kWh] + peak_tariff (float): the peak tariff cost for electricity [$/kWh] + off_peak_tariff (float): the off-peak tariff cost for electricity [$/kWh] + efficiency (float): the conversion efficiency [%] + + Returns: + (float): the daily profit generated by the dam ($) + """ + profit = 0 + for energy in energies: + profit += energy * (peak_tariff - off_peak_tariff/((efficiency/100)**2)) + + return profit + +def print_table(start_relative_elevation, step_size, num_steps, initial_height, + final_height, reservoir_area, outlet_area, time_inc, peak_tariff, + off_peak_tariff, efficiency): + """ + Prints a table of the daily profit generated by the dam for different water heights + + Parameters: + start_relative_elevation (float): the height difference between the generators and the dam [m] + step_size (float): the increment in water height [m] + num_steps (int): the number of steps to take + initial_height (float): the initial height of the water in the reservoir [m] + final_height (float): the final height of the water in the reservoir [m] + reservoir_area (float): the area of the reservoir [m^2] + outlet_area (float): the area of the outlet [m^2] + time_inc (float): the time increment [s] + peak_tariff (float): the peak tariff cost for electricity [$/kWh] + off_peak_tariff (float): the off-peak tariff cost for electricity [$/kWh] + efficiency (float): the conversion efficiency [%] + + Returns: + None + """ + COLUMN_WIDTH = 25 + HEADER = '#'*((COLUMN_WIDTH + 1)*3 + 1) + print(HEADER) + print(f"#{'Relative elevation (m)':^{COLUMN_WIDTH}}#{'Daily Profit ($)':^{COLUMN_WIDTH}}#{'Total Energy (kWh)':^{COLUMN_WIDTH}}#") + print(HEADER) + + for _ in range(num_steps): + water_heights, water_masses = calc_heights_water_out(initial_height, final_height, reservoir_area, outlet_area, time_inc) + energy, power = calc_energy_power(water_heights, water_masses, start_relative_elevation, efficiency, time_inc) + profit = calc_daily_profit(energy, peak_tariff, off_peak_tariff, efficiency) + print(f"#{start_relative_elevation:^{COLUMN_WIDTH}}#{profit:^{COLUMN_WIDTH}.2f}#{sum(energy):^{COLUMN_WIDTH}.2f}#") + start_relative_elevation += step_size + + print(HEADER) + + +def main(): + """ + Main function that handles the user interface + + Parameters: + None + + Returns: + None + """ + running = True + data = None + while running: + command = input("Please enter a command: ") + if command == 'h': + print(HELP_MESSAGE) + + elif command.startswith('r'): + directory = input("Please specify the directory: ") + filename = input("Please specify the filename: ") + data = load_data(directory, filename) + + elif command.startswith('p'): + if data is None: + print("Please load data before using this command") + else: + args = command.split()[1:] + if len(args) != 3: + print("Please enter the correct number of arguments") + else: + start_relative_elevation = int(args[0]) + step_size = float(args[1]) + num_steps = int(args[2]) + print_table(start_relative_elevation, step_size, num_steps, *data) + + elif command.startswith('s'): + if data is None: + print("Please load data before using this command") + else: + initial_height = data[0] + final_height = data[1] + reservoir_area = data[2] + outlet_area = data[3] + time_inc = data[4] + water_heights, _ = calc_heights_water_out(initial_height, final_height, + reservoir_area, outlet_area, time_inc) + print("Simulating water heights...") + plot_water_height(water_heights, time_inc) + + elif command == 'q': + command = input("Are you sure (y/n): ") + if command == 'y': + running = False + else: + continue + + + else: + print("Please enter a valid command") + + + + +if __name__ == '__main__': + print("Task 1") + print(determine_power_used(5e6, 250, 8, 85)) + + print("\nTask 2") + print(determine_water_released(300, 250, 8, 85)) + + print("\nTask 3") + print(determine_cost_to_pump(300, 8, 0.02)) + + print("\nTask 4") + print(calc_speed_at_outlet(30)) + + print("\nTask 5") + print(calc_new_water_height(20, 40000, 1, 30)) + + print("\nTask 6") + water_heights, water_masses = calc_heights_water_out(40, 5, 40000, 1, 30) + print(water_heights[0:3], water_masses[0:3]) + print(len(water_heights), len(water_masses)) + + print("\nTask 7") + water_heights, water_masses = calc_heights_water_out(30, 20, 40000, 1, 30) + energy, power = calc_energy_power(water_heights, water_masses, 200, 85, 30) + print(energy[0:3], power[0:3]) + print(len(energy), len(power)) + print(calc_daily_profit(energy, 0.02, 0.005, 85)) + + print("\nTask 8") + print_table(280, 20, 6, 30, 20, 40000, 1, 30, 0.02, 0.005, 85) + + # main() \ No newline at end of file diff --git a/alex_dump.txt b/alex_dump.txt new file mode 100644 index 0000000..686be8e --- /dev/null +++ b/alex_dump.txt @@ -0,0 +1,35 @@ +Task 1 +500.9191176470588 + +Task 2 +2994495.4128440367 + +Task 3 +48.0 + +Task 4 +24.261079942986875 + +Task 5 +(19.985143183382704, 592567.1021442247) + +Task 6 +(39.97898928844613, 39.95798409574207, 39.93698442188801) (838016.4324684857, 837796.3120398963, 837576.1916037091) +2461 2461 + +Task 7 +(386.6002008976669, 386.4523727180418, 386.3045723539472) (46392.024107720026, 46374.28472616501, 46356.548682473665) +605 605 +2718.700033709491 + +Task 8 +############################################################################### +# Relative elevation (m) # Daily Profit ($) # Total Energy (kWh) # +############################################################################### +# 280 # 3685.38 # 281766.19 # +# 300 # 3927.06 # 300243.16 # +# 320 # 4168.73 # 318720.14 # +# 340 # 4410.40 # 337197.12 # +# 360 # 4652.07 # 355674.09 # +# 380 # 4893.74 # 374151.07 # +############################################################################### diff --git a/debug_lib.py b/debug_lib.py index e195ca4..24d7da9 100644 --- a/debug_lib.py +++ b/debug_lib.py @@ -36,7 +36,8 @@ def compair_outputs(tasks): # Number comparison if isinstance(expected, (float, int)): foo = np.isclose(result, expected, IS_CLOSE_VAR) - print(f'{task.__qualname__}{args} -> {result} {"~=" if foo else "!="} {expected}') + print(f'{task.__qualname__}{args}') + print(f' -> {result} {"~=" if foo else "!="} {expected}') print(f'Task is{"" if foo else " NOT"} close enough to expected result.') # Run the task and print out what is is expected on a new line