diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..7a27222 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,5 @@ +{ + "cSpell.words": [ + "trapiztoal" + ] +} \ No newline at end of file diff --git a/gen_latex.py b/gen_latex.py new file mode 100644 index 0000000..c4391cf --- /dev/null +++ b/gen_latex.py @@ -0,0 +1,11 @@ +import os + +root = "images\\pressure" + +for path, subdirs, files in os.walk(root): + for name in files: + if "1000rpm" not in name: continue + + filePath = os.path.join(path, name) + str = "\\begin{subfigure}{0.45\\linewidth}\n \\centering\n \\includegraphics[width=0.95\\linewidth]{" + filePath.replace("\\", '/') + "}\n \\caption{" + name.replace("Percent", "\\%").replace(".png", "").replace("m_s", "m/s") + "}\n\\end{subfigure}" + print(str) diff --git a/main.py b/main.py index d902608..30936a4 100644 --- a/main.py +++ b/main.py @@ -12,8 +12,8 @@ from numpy import sqrt from makeGraph import makeGraph, pltKeyClose, UQ_COLOURS as UQC, uq_colour_cycler_factory as uqccf # Custom Graphing Lib # Override Sin & Cos to use & return degrees -#def sin(angle): return np.sin(np.deg2rad(angle)) -#def cos(angle): return np.cos(np.deg2rad(angle)) +def sin(angle): return np.sin(np.deg2rad(angle)) +def cos(angle): return np.cos(np.deg2rad(angle)) # Make sure the relevant folders folder exists #folders = ["./images", "./tmp", "./data"] @@ -26,7 +26,7 @@ INCH_TO_M = 0.0254 GRAVITY = 9.81 #m/s^2 CHORD_LEN = 90 #mm -PITOT_PLACEMENT = np.array((0,4,8,16,25,34,43,53,61,70,5,9,17,25,34,43,53,61,70)) # mm from base of chord +PITOT_PLACEMENT = np.array((0,4,8,16,25,34,43,52,61,70,5,9,17,25,34,43,52,61,70)) # mm from base of chord PITOT_PLACEMENT_CHORD_NORM = PITOT_PLACEMENT / CHORD_LEN print("="*15, "Loading Data", "="*15) @@ -68,7 +68,7 @@ def make_pressure_graph(sheet1, aoa, rpm, air_speed, doGraph=True): graph = { "title": f"Pressure vs Pitot Placement along Chord\nfor a Clark Y 14% Aerofoil at:\nα = {int(aoa):d}° at {rpm:d} RPM ({air_speed:.1f}m/s)", - "windowTitle": f"Pressure along Clark Y 14% Airfoil - Alpha {int(aoa):d} Degrees - {rpm:d}rpm - {air_speed:.1f}m_s", + "windowTitle": f"Pressure along Clark Y 14 Percent Airfoil - Alpha {int(aoa):d} Degrees - {rpm:d}rpm - {air_speed:.1f}m_s", "xLabel": "Pitot Placement [mm]", "yLabel": "Pressure [Pa]", "grid": True, @@ -104,6 +104,72 @@ def make_pressure_graph(sheet1, aoa, rpm, air_speed, doGraph=True): return pressure, graph, (water_density, air_density, atm_presure_inch, pitot_height_inch), (p1, p2, pN) +def make_cp_graph(pressure, aoa, rpm, air_speed, data, doGraph=True): + water_density, air_density, atm_presure_inch, pitot_height_inch = data + + #print(pressure) + #print(pressure.min(), pressure.max()) + + # Calculate Cp + cp = pressure / (0.5 * air_density * (air_speed ** 2)) + + # Do the trapiztoal rule integration + da = [] + for i, _ in enumerate(pressure): + if not i: continue # Skip 0 + da.append(((pressure.iloc[i-1] + pressure.iloc[i])/2) * (PITOT_PLACEMENT_CHORD_NORM[i]-PITOT_PLACEMENT_CHORD_NORM[i-1])) + + da = np.array(da) + + force = da.sum() + lift = force * sin(aoa) + drag = force * cos(aoa) + + # Extrapolate Aerofoil Tip + p1 = (PITOT_PLACEMENT_CHORD_NORM[9], cp.iloc[9]) + p2 = (PITOT_PLACEMENT_CHORD_NORM[18], cp.iloc[18]) + pN = (0.9, p2[1] + (p1[1]-p2[1])/2) + #print(aoa, rpm, p1[1], p2[1], (p1[1]-p2[1])/2, pN[1], pN[1] > p1[1]) + + + graph = { + "title": f"$C_p$ vs Pitot Placement along Chord\nfor a Clark Y 14% Aerofoil at:\nα = {int(aoa):d}° at {rpm:d} RPM ({air_speed:.1f}m/s)", + "windowTitle": f"Cp along Clark Y 14 Percent Airfoil - Alpha {int(aoa):d} Degrees - {rpm:d}rpm - {air_speed:.1f}m_s", + "xLabel": "Normalized Pitot Placement", + "yLabel": "$C_p$", + "grid": True, + "yLim": (cp.min()-0.5, cp.max()+0.5), + "plots": [ + # Draw Lines + {"x": PITOT_PLACEMENT_CHORD_NORM[:10], "y":cp[:10], "colour": UQC["purple"]}, + {"x": PITOT_PLACEMENT_CHORD_NORM[10:], "y":cp[10:], "colour": UQC["purple"]}, + {"x": [PITOT_PLACEMENT_CHORD_NORM[0], PITOT_PLACEMENT_CHORD_NORM[10]], "y": [cp.iloc[0], cp.iloc[10]], "colour": UQC["purple"]}, + #{"x": [PITOT_PLACEMENT_CHORD_NORM[9], PITOT_PLACEMENT_CHORD_NORM[18]], "y": [cp.iloc[9], cp.iloc[18]], "colour": UQC["purple"]}, + + # Draw Extrapolated Airfoil Tip + {"x": [PITOT_PLACEMENT_CHORD_NORM[9], pN[0]], "y": [cp.iloc[9], pN[1]], "colour": UQC["aqua"], "label": "Extrapolated Airfoil Tip"}, + {"x": [PITOT_PLACEMENT_CHORD_NORM[9], pN[0]], "y": [cp.iloc[18], pN[1]], "colour": UQC["aqua"]}, + + # Draw Colour Shading + {"x": PITOT_PLACEMENT_CHORD_NORM[:10], "y":cp[:10], "colour": UQC["purple"], "alpha":0.2, "type":"fill"}, + {"x": PITOT_PLACEMENT_CHORD_NORM[10:], "y":cp[10:], "colour": "w", "type":"fill"}, + {"x":[PITOT_PLACEMENT_CHORD_NORM[0], PITOT_PLACEMENT_CHORD_NORM[10]], "y":[cp.iloc[0], cp.iloc[10]], "colour": "w", "type":"fill"}, + {"x": [PITOT_PLACEMENT_CHORD_NORM[9], pN[0]], "y": [cp.iloc[9], pN[1]], "colour": UQC["aqua"], "type":"fill", "alpha":0.2}, + {"x":[PITOT_PLACEMENT_CHORD_NORM[9], pN[0]], "y": [cp.iloc[18], pN[1]], "colour": "w", "type":"fill"}, + + # Draw Points & text + {"x":PITOT_PLACEMENT_CHORD_NORM, "y":cp, "label":"cp Data", "type":"scatter", "args":{"zorder":2}}, + {"label":[str(i) for i in range(1, len(PITOT_PLACEMENT_CHORD_NORM)+1)], "x":PITOT_PLACEMENT_CHORD_NORM, "y":cp, "type":"annotate"}, + {"type":"text", "x": 0.98, "y": 0.02, "text": f"Min $C_p$: {cp.min():.3f}\nMax $C_p$: {cp.max():.3f}\nForce: {force:.3f}N\nLift: {lift:.3f}N\nDrag: {drag:.3f}N", "align": ('bottom', 'right')} + ] + } + + if doGraph: + makeGraph(graph, False, figSavePath=f'./images/cp/{{0}}.png', closeFig=True) + + return cp, (force, lift, drag, da), graph, (p1, p2, pN), aoa + + def make_rpm_graph(): air_density = data_508rpm["data"]["0 AoA"].iloc[1, 2] # kg/m^3 rpm = np.concat((np.array([0]), np.array(data_508rpm["data"]["0 AoA"].iloc[4:14, 2]))) @@ -148,11 +214,11 @@ if __name__ == '__main__': data[raw_data["rpm"]] = aoa_data - if True: + if False: # All graph = { "title": f"Pressure vs Pitot Placement along Chord\nfor a Clark Y 14% Aerofoil at:\n{raw_data["rpm"]:d} RPM ({raw_data["airSpeed"]:.1f}m/s)", - "windowTitle": f"All Pressure along Clark Y 14% Airfoil - {raw_data["rpm"]:d}rpm - {raw_data["airSpeed"]:.1f}m_s", + "windowTitle": f"All Pressure along Clark Y 14 Percent Airfoil - {raw_data["rpm"]:d}rpm - {raw_data["airSpeed"]:.1f}m_s", "xLabel": "Pitot Placement [mm]", "yLabel": "Pressure [Pa]", "grid": True, @@ -202,7 +268,7 @@ if __name__ == '__main__': makeGraph(graph, False, figSavePath="./images/pressure/__{0}.png") graph["plots"] = [] - graph["windowTitle"] = f"Pressure along Clark Y 14% Airfoil - {raw_data["rpm"]:d}rpm - {raw_data["airSpeed"]:.1f}m_s" + graph["windowTitle"] = f"Pressure along Clark Y 14 Percent Airfoil - {raw_data["rpm"]:d}rpm - {raw_data["airSpeed"]:.1f}m_s" colour_cycle = uqccf() for aoa, c in list(zip(aoa_data, colour_cycle))[1::2]: @@ -231,7 +297,133 @@ if __name__ == '__main__': makeGraph(graph, False, figSavePath="./images/pressure/__{0}.png") - print("Data Loaded") + print("Generating Cp Graphs") + + cp_data = {} + for raw_data in tqdm((data_508rpm, data_1000rpm), position=0): + cp_pain_data = [] + for aoa in tqdm(raw_data["AoA"], position=1): + this_data = data[raw_data["rpm"]][aoa] + + cp_data_this = make_cp_graph(this_data[0], aoa, raw_data["rpm"], raw_data["airSpeed"], this_data[2], False) + cp_pain_data.append(cp_data_this) + + cp_data[raw_data["rpm"]] = cp_pain_data + + if False: + # All + graph = { + "title": f"All $C_p$ vs Pitot Placement along Chord\nfor a Clark Y 14% Aerofoil at:\n{raw_data["rpm"]:d}rpm - {raw_data["airSpeed"]:.1f}m/s)", + "windowTitle": f"All Cp along Clark Y 14 Percent Airfoil - {raw_data["rpm"]:d}rpm - {raw_data["airSpeed"]:.1f}m_s", + "xLabel": "Normalized Pitot Placement", + "yLabel": "$C_p$", + "grid": True, + "ledgLoc": 1, + "plots": [], + } + + colour_cycle = uqccf() + for this_data, c in zip(cp_pain_data, colour_cycle): + cp = this_data[0] + + # Extrapolate Aerofoil Tip + p1, p2, pN = this_data[3] + + plts = ( + # Draw Lines + {"x": PITOT_PLACEMENT_CHORD_NORM[:10], "y":cp[:10], "colour": c["color"]}, + {"x": PITOT_PLACEMENT_CHORD_NORM[10:], "y":cp[10:], "colour": c["color"]}, + {"x": [PITOT_PLACEMENT_CHORD_NORM[0], PITOT_PLACEMENT_CHORD_NORM[10]], "y": [cp.iloc[0], cp.iloc[10]], "colour": c["color"]}, + + # Draw Extrapolated Airfoil Tip + {"x": [PITOT_PLACEMENT_CHORD_NORM[9], pN[0]], "y": [cp.iloc[9], pN[1]], "colour": c["color"], "args":{"alpha":0.3}}, + {"x": [PITOT_PLACEMENT_CHORD_NORM[9], pN[0]], "y": [cp.iloc[18], pN[1]], "colour": c["color"], "args":{"alpha":0.3}}, + + # Draw Points & text + {"x":PITOT_PLACEMENT_CHORD_NORM, "y":cp, "label":f"α = {int(this_data[4]):d}°", "type":"scatter", "args":{"zorder":2}, "colour": c["color"]}, + ) + for plt in plts: + graph["plots"].append(plt) + + if raw_data["rpm"] == 508: + #graph['xLim'] = ( + # min(PITOT_PLACEMENT_CHORD_NORM) - 0.5, + # max(PITOT_PLACEMENT_CHORD_NORM) + 0.5 + #) + graph["figSize"] = (8, 6) + + + makeGraph(graph, False, figSavePath="./images/cp/__{0}.png") + + graph["title"] = f"$C_p$ vs Pitot Placement along Chord\nfor a Clark Y 14% Aerofoil at:\n{raw_data["rpm"]:d}rpm - {raw_data["airSpeed"]:.1f}m/s)" + graph["windowTitle"] = f"Cp along Clark Y 14 Percent Airfoil - {raw_data["rpm"]:d}rpm - {raw_data["airSpeed"]:.1f}m_s" + graph["plots"] = [] + colour_cycle = uqccf() + for this_data, c in list(zip(cp_pain_data, colour_cycle))[1::2]: + cp = this_data[0] + + # Extrapolate Aerofoil Tip + p1, p2, pN = this_data[3] + + plts = ( + # Draw Lines + {"x": PITOT_PLACEMENT_CHORD_NORM[:10], "y":cp[:10], "colour": c["color"]}, + {"x": PITOT_PLACEMENT_CHORD_NORM[10:], "y":cp[10:], "colour": c["color"]}, + {"x": [PITOT_PLACEMENT_CHORD_NORM[0], PITOT_PLACEMENT_CHORD_NORM[10]], "y": [cp.iloc[0], cp.iloc[10]], "colour": c["color"]}, + + # Draw Extrapolated Airfoil Tip + {"x": [PITOT_PLACEMENT_CHORD_NORM[9], pN[0]], "y": [cp.iloc[9], pN[1]], "colour": c["color"], "args":{"alpha":0.3}}, + {"x": [PITOT_PLACEMENT_CHORD_NORM[9], pN[0]], "y": [cp.iloc[18], pN[1]], "colour": c["color"], "args":{"alpha":0.3}}, + + # Draw Points & text + {"x":PITOT_PLACEMENT_CHORD_NORM, "y":cp, "label":f"α = {int(this_data[4]):d}°", "type":"scatter", "args":{"zorder":2}, "colour": c["color"]}, + ) + for plt in plts: + graph["plots"].append(plt) + makeGraph(graph, False, figSavePath="./images/cp/__{0}.png") + + if True: + aoa = [a[4] for a in cp_pain_data] + forces = [a[1] for a in cp_pain_data] + # Force Graphs + graph = { + "title": f"All Total, Lift & Drag Forces\nfor a Clark Y 14% Aerofoil at:\n{raw_data["rpm"]:d}rpm - {raw_data["airSpeed"]:.1f}m/s)", + "windowTitle": f"All Total, Lift and Drag Forces for a Clark Y 14 Percent Airfoil - {raw_data["rpm"]:d}rpm - {raw_data["airSpeed"]:.1f}m_s", + "xLabel": "Attack Angle [$\\alpha$]", + "yLabel": "Force [N]", + "grid": True, + "ledgLoc": 1, + "plots": [ + {"x":aoa, "y":[f[0] for f in forces], "label":"Total Force"}, + {"x":aoa, "y":[f[1] for f in forces], "label":"Lift"}, + {"x":aoa, "y":[f[2] for f in forces], "label":"Drag"}, + ] + } + + makeGraph(graph, False, figSavePath="./images/{0}.png") + + aoa = [a[4] for a in cp_pain_data][1::2] + forces = [a[1] for a in cp_pain_data][1::2] + # Force Graphs + graph = { + "title": f"All Total, Lift & Drag Forces\nfor a Clark Y 14% Aerofoil at:\n{raw_data["rpm"]:d}rpm - {raw_data["airSpeed"]:.1f}m/s)", + "windowTitle": f"All Total, Lift and Drag Forces for a Clark Y 14 Percent Airfoil - {raw_data["rpm"]:d}rpm - {raw_data["airSpeed"]:.1f}m_s", + "xLabel": "Attack Angle [$\\alpha$]", + "yLabel": "Force [N]", + "grid": True, + "ledgLoc": 1, + "plots": [ + {"x":aoa, "y":[f[0] for f in forces], "label":"Total Force"}, + {"x":aoa, "y":[f[1] for f in forces], "label":"Lift"}, + {"x":aoa, "y":[f[2] for f in forces], "label":"Drag"}, + ] + } + + makeGraph(graph, False, figSavePath="./images/{0}.png") + + + + print("Complete")