def get_merge_profile(self, factor): factor = max(0, min(len(self.profiles) - 1, factor)) k = factor % 1 i = int(factor // 1) first = self.profiles[i].copy() if k > 0: second = self.profiles[i + 1] airfoil = first * (1 - k) + second * k else: airfoil = first return Profile2D(airfoil.data)
def plot_test(): arf = Profile2D() arf.importdat("../../tests/testprofile.dat") arf.numpoints = 100 pan = panel_methode_2d(arf.data, aoa=5 * numpy.pi / 180, wake_length=5, wake_numpoints=10) print(pan.mat_douplet_cooef) from matplotlib import pyplot pyplot.plot(pan.douplet, marker="o") pyplot.plot(pan.velocity, marker="x") # pyplot.plot(pan.pressure, marker="x") pyplot.show()
def test(): p1 = numpy.array([0, 0]) p2 = numpy.array([1, 0]) pj = numpy.array([5, 5]) arf = Profile2D() # arf.importdat("../../tests/testprofile.dat") arf.compute_naca(2400) arf.numpoints = 30 pan = panel_methode_2d([p1, p2, pj, p1], aoa=2 * numpy.pi / 180.) print(pan._douplet_const(pj, [p1, p2])) print(pan._douplet_lin(pj, [p1, p2])) print(pan._source_const(pj, [p1, p2]))
def __init__(self, obj): self.prof = Profile2D() self.prof.compute_naca(2422, numpoints=120) obj.addProperty("App::PropertyInteger", "Numpoints", "airfoil", "Number of points").Numpoints = self.prof.numpoints obj.addProperty( "App::PropertyFloat", "Thickness", "airfoil", "Thickness of airfoil").Thickness = self.prof.thickness * 1000 #obj.addProperty("App::PropertyFloat", "Camber", "airfoil", "Camber of airfoil").Camber = max(self.prof.Camber[:,1]) * 1000 obj.addProperty("App::PropertyString", "Name", "airfoil", "Name of airfoil").Name = self.prof.name obj.addProperty("App::PropertyVectorList", "coords", "airfoil", "profilcoords") obj.addProperty("App::PropertyPath", "FilePath", "airfoil", "Name of airfoil").FilePath = "" obj.Proxy = self
def visual_test_airfoil(): arf = Profile2D() arf.importdat("../../tests/testprofile.dat") arf.numpoints = 30 pan = panel_methode_2d(arf.data, aoa=10 * numpy.pi / 180, wake_length=5, wake_numpoints=10) x = numpy.linspace(-0.3, 1.3, 30) y = numpy.linspace(-0.2, 0.2, 30) X, Y = meshgrid(x, y) z = numpy.zeros([len(x), len(y)]) for i in range(len(z)): for j in range(len(z[0])): for k in range(len(pan.douplet)): z[i][j] += -dot([x[j], y[i]], pan.v_inf) + 100 * pan.douplet[k] * _douplet_const([x[j], y[i]], pan.panel[k]) contourf(X, Y, z, levels = linspace(z.min(), z.max(), len(x)), ls = '-', cmap=cm.winter, origin="lower") show()
def graphics_test(): from openglider.graphics import Graphics2D, Line arf = Profile2D() #arf.importdat("../../tests/testprofile.dat") #arf.numpoints = 100 arf.compute_naca(2420, numpoints=120) arf.close() arf.normalize() pan = panel_methode_2d(arf.data, aoa=10 * numpy.pi / 180, wake_length=5, wake_numpoints=10) arrows = [] for i in range(pan.length): mid = pan.panel_mids[i] normal = pan.panel_normals[i] cp = pan.pressure[i] arrows.append([mid, mid + normal * cp * pan.half_lenghts[i] * 10]) arrows = numpy.array(arrows) Graphics2D([Line(pan.airfoil), Line(arrows[:, 1])] + map(Line, arrows))
def profileimp(sheet): num = sheet.row_len(1) / 2 profiles = [] for i in range(num): prof = Profile2D() j = 0 if isinstance(sheet.cell(0, 2 * i).value, str): prof.name = sheet.cell(0, 2 * i).value j += 1 temp = [] while j < sheet.nrows and isinstance( sheet.cell(j, 2 * i).value, float): #print(sheet.cell(j,2*i).value) temp += [[ sheet.cell(j, 2 * i).value, sheet.cell(j, 2 * i + 1).value ]] j += 1 prof.data = temp profiles += [prof] return profiles
import numpy from openglider.glider.cell import Cell from openglider.glider.rib import Rib, MiniRib try: import openglider except ImportError: sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(sys.argv[0])))) from openglider.airfoil import Profile2D import openglider.graphics as Graph from openglider.glider.ballooning import BallooningBezier a = Profile2D() a.importdat(os.path.dirname(os.path.abspath(__file__)) + "/testprofile.dat") #a.Numpoints = 40 midribs = [ #MiniRib(0.2, 0.8, 1), MiniRib(0.5, 0.7, 1), #MiniRib(0.8, 0.8, 1), ] b1 = BallooningBezier() b2 = BallooningBezier() b2.Amount *= 0.8 r2 = Rib(a, b1, [0, 0.12, 0], 1., 20 * math.pi / 180, 2 * math.pi / 180, 0, 7) r1 = r2.copy()
def import_ods(filename, glider=None): ods = ezodf.opendoc(filename) sheets = ods.sheets # Profiles -> map xvalues profiles = [Profile2D(profile) for profile in transpose_columns(sheets[3])] xvalues = sorted(profiles, key=lambda prof: prof.numpoints)[0].x_values # Use airfoil with maximum profilepoints for profile in profiles: profile.x_values = xvalues # Ballooning old : 1-8 > upper (prepend/append (0,0),(1,0)), 9-16 > lower (same + * (1,-1)) balloonings_temp = transpose_columns(sheets[4]) balloonings = [] for baloon in balloonings_temp: upper = [[0, 0]] + baloon[:7] + [[1, 0]] lower = [[0, 0]] + [[i[0], -1 * i[1]] for i in baloon[8:15]] + [[1, 0]] balloonings.append(BallooningBezier([upper, lower])) # Data data = {} datasheet = sheets[-1] assert isinstance(datasheet, ezodf.Sheet) for i in range(datasheet.nrows()): data[datasheet.get_cell([i, 0]).value] = datasheet.get_cell([i, 1]).value #print(data["GLEITZAHL"]) glider.data = data cells = [] main = sheets[0] x = y = z = span_last = 0. alpha2 = 0. thisrib = None # TODO: Glide -> DATAIMPORT for i in range(1, main.nrows()): line = [main.get_cell([i, j]).value for j in range(main.ncols())] if not line[0]: #print("leere zeile:", i, main.nrows()) break chord = line[1] # Rib-Chord span = line[2] # spanwise-length (flat) alpha1 = alpha2 # angle before the rib alpha2 += line[4] * numpy.pi / 180 # angle after the rib alpha = (span > 0) * (alpha1 + alpha2) * 0.5 + line[6] * numpy.pi / 180 # rib's angle x = line[3] # x-value -> front/back (ribwise) y += numpy.cos(alpha1) * (span - span_last) # y-value -> spanwise z -= numpy.sin(alpha1) * (span - span_last) # z-axis -> up/down aoa = line[5] * numpy.pi / 180 zrot = line[7] * numpy.pi / 180 span_last = span profile = merge(line[8], profiles) ballooning = merge(line[9], balloonings) lastrib = thisrib thisrib = Rib(profile, ballooning, numpy.array([x, y, z]), chord, alpha, aoa, zrot, data["GLEITZAHL"]) if i == 1 and y != 0: # Middle-cell #print("midrib!", y) lastrib = thisrib.copy() lastrib.mirror() if lastrib: cell = Cell(lastrib, thisrib, []) cell.name = "Cell_no"+str(i) cells.append(cell) if glider: glider.cells = cells glider.close_rib() glider.attachment_points = read_elements(sheets[2], "AHP", AttachmentPoint) glider.attachment_points_lower = get_lower_aufhaengepunkte(glider.data) for p in glider.attachment_points: p.force = numpy.array([0, 0, 1]) p.get_position(glider) glider.lines = tolist_lines(sheets[6], glider.attachment_points_lower, glider.attachment_points) glider.lines.calc_geo() glider.lines.calc_sag() return return cells
def import_ods(filename, glider): ods = ezodf.opendoc(filename) sheets = ods.sheets # Profiles -> map xvalues profiles = [Profile2D(profile) for profile in transpose_columns(sheets[3])] xvalues = sorted(profiles, key=lambda prof: prof.numpoints)[0].x_values # Use airfoil with maximum profilepoints for profile in profiles: profile.x_values = xvalues # Ballooning old : 1-8 > upper (prepend/append (0,0),(1,0)), 9-16 > lower (same + * (1,-1)) balloonings_temp = transpose_columns(sheets[4]) balloonings = [] for baloon in balloonings_temp: upper = [[0, 0]] + baloon[:7] + [[1, 0]] lower = [[0, 0]] + [[i[0], -1 * i[1]] for i in baloon[8:15]] + [[1, 0]] balloonings.append(BallooningBezier(upper, lower)) # Data data = {} datasheet = sheets[-1] assert isinstance(datasheet, ezodf.Sheet) for i in range(datasheet.nrows()): data[datasheet.get_cell([i, 0]).value] = datasheet.get_cell([i, 1]).value #print(data["GLEITZAHL"]) glider.data = data cells = [] main = sheets[0] x = y = z = span_last = 0. alpha2 = 0. thisrib = None for i in range(1, main.nrows()): line = [main.get_cell([i, j]).value for j in range(main.ncols())] if not line[0]: break # skip empty line chord = line[1] # Rib-Chord span = line[2] # spanwise-length (flat) alpha1 = alpha2 # angle before the rib alpha2 += line[4] * np.pi / 180 # angle after the rib alpha = (span > 0) * (alpha1 + alpha2) * 0.5 + line[6] * np.pi / 180 # rib's angle x = line[3] # x-value -> front/back (ribwise) y += np.cos(alpha1) * (span - span_last) # y-value -> spanwise z -= np.sin(alpha1) * (span - span_last) # z-axis -> up/down aoa = line[5] * np.pi / 180 zrot = line[7] * np.pi / 180 span_last = span profile = merge(line[8], profiles) ballooning = merge(line[9], balloonings) lastrib = thisrib thisrib = Rib(profile, np.array([x, y, z]), chord, alpha, aoa, zrot, data["GLIDE"], name="Rib ({})".format(i)) if i == 1 and y != 0: # Middle-cell #print("midrib!", y) lastrib = thisrib.copy() lastrib.mirror() if lastrib: cell = Cell(lastrib, thisrib, ballooning) cell.name = "Cell_no"+str(i) cells.append(cell) glider.cells = cells glider.close_rib() ######################################LINESET###################################################### attachment_points = [AttachmentPoint(glider.ribs[args[0]], args[1], args[2]) for args in read_elements(sheets[2], "AHP", len_data=2)] attachment_points.sort(key=lambda element: element.name) attachment_points_lower = get_lower_aufhaengepunkte(glider.data) for p in attachment_points: p.force = np.array([0, 0, 10]) p.get_position() glider.lineset = tolist_lines(sheets[6], attachment_points_lower, attachment_points) glider.lineset.recalc() ####################################PANELS########################################################## cuts = [cut+[1, glider.data["Designzugabe"]] for cut in read_elements(sheets[1], "DESIGNO")] cuts += [cut+[1, glider.data["Designzugabe"]] for cut in read_elements(sheets[1], "DESIGNM")] cuts += [cut+[2, glider.data["EKzugabe"]] for cut in read_elements(sheets[1], "EKV")] cuts += [cut+[2, glider.data["EKzugabe"]] for cut in read_elements(sheets[1], "EKH")] for i, cell in enumerate(glider.cells): # cut = [cell_no, x_left, x_right, cut_type, amount_add] cuts_this = [cut for cut in cuts if cut[0] == i] cuts_this.sort(key=lambda cut: cut[1]) cuts_this.sort(key=lambda cut: cut[2]) # Insert leading-/trailing-edge cuts_this.insert(0, [i, -1, -1, 3, glider.data["HKzugabe"]]) cuts_this.append([i, 1, 1, 3, glider.data["HKzugabe"]]) cell.panels = [] for j in range(len(cuts_this)-1): if cuts_this[j][3] != 2 or cuts_this[j+1][3] != 2: # skip entry cell.panels.append(Panel(cuts_this[j][1:], cuts_this[j+1][1:])) return glider
def flatten(self): """Flatten the airfoil and return a 2d-Representative""" layer = self.projection_layer return Profile2D([layer.projection(p) for p in self.data], name=self.name or 'profile' + "_flattened")
def setUp(self): self.profile = Profile2D() prof = random.randint(1, 9999) self.profile.compute_naca(prof, 200)
def import_ods_2d(Glider2D, filename, numpoints=4, calc_lineset_nodes=False): ods = ezodf.opendoc(filename) sheets = ods.sheets cell_sheet = sheets[1] rib_sheet = sheets[2] # file-version if cell_sheet[0, 0].value == "V2" or cell_sheet[0, 0].value == "V2": file_version = 2 else: file_version = 1 # ------------ # profiles = [BezierProfile2D(profile) for profile in transpose_columns(sheets[3])] profiles = [ Profile2D(profile, name) for name, profile in transpose_columns(sheets[3]) ] for foil in profiles: foil.normalize() try: geometry = get_geometry_parametric(sheets[5]) except Exception: geometry = get_geometry_explicit(sheets[0]) balloonings = [] for i, (name, baloon) in enumerate(transpose_columns(sheets[4])): ballooning_type = str(sheets[4][0, 2 * i + 1].value).upper() if baloon: if ballooning_type == "V1": i = 0 while baloon[i + 1][0] > baloon[i][0]: i += 1 upper = baloon[:i + 1] lower = [(x, -y) for x, y in baloon[i + 1:]] balloonings.append(BallooningBezier(upper, lower, name=name)) elif ballooning_type == "V2": i = 0 while baloon[i + 1][0] > baloon[i][0]: i += 1 upper = baloon[:i + 1] lower = baloon[i + 1:] balloonings.append(BallooningBezier(upper, lower, name=name)) elif ballooning_type == "V3": balloonings.append(BallooningBezierNeu(baloon)) else: raise ValueError("No ballooning type specified") data = {} datasheet = sheets[-1] assert isinstance(datasheet, ezodf.Sheet) for row in datasheet.rows(): if len(row) > 1: data[row[0].value] = row[1].value # Attachment points: rib_no, id, pos, force attachment_points = get_attachment_points(rib_sheet, cell_sheet) attachment_points_lower = get_lower_aufhaengepunkte(data) # RIB HOLES rib_hole_keywords = ["ribs", "pos", "size"] rib_holes = read_elements(rib_sheet, "QUERLOCH", len_data=2) rib_holes = to_dct(rib_holes, rib_hole_keywords) rib_holes = group(rib_holes, "ribs") rigidfoil_keywords = ["ribs", "start", "end", "distance"] rigidfoils = read_elements(rib_sheet, "RIGIDFOIL", len_data=3) rigidfoils = to_dct(rigidfoils, rigidfoil_keywords) rigidfoils = group(rigidfoils, "ribs") # CUTS def get_cuts(names, target_name): objs = [] for name_src in names: objs += read_elements(cell_sheet, name_src, len_data=2) cuts_this = [{ "cells": cut[0], "left": float(cut[1]), "right": float(cut[2]), "type": target_name } for cut in objs] return group(cuts_this, "cells") cuts = get_cuts(["EKV", "EKH", "folded"], "folded") cuts += get_cuts(["DESIGNM", "DESIGNO", "orthogonal"], "orthogonal") cuts += get_cuts(["singleskin"], "singleskin") # Diagonals: center_left, center_right, width_l, width_r, height_l, height_r diagonals = [] for res in read_elements(cell_sheet, "QR", len_data=6): height1 = res[5] height2 = res[6] # migration if file_version == 1: # height (0,1) -> (-1,1) height1 = height1 * 2 - 1 height2 = height2 * 2 - 1 # --------- diagonals.append({ "left_front": (res[1] - res[3] / 2, height1), "left_back": (res[1] + res[3] / 2, height1), "right_front": (res[2] - res[4] / 2, height2), "right_back": (res[2] + res[4] / 2, height2), "cells": res[0] }) diagonals = group(diagonals, "cells") straps = [] straps_keywords = ["cells", "left", "right"] for res in read_elements(cell_sheet, "VEKTLAENGE", len_data=2): straps.append({ "left_front": (res[1] - 0.02, -1), "left_back": (res[1] + 0.02, -1), "right_front": (res[1] - 0.02, -1), "right_back": (res[1] - 0.02, -1), "cells": res[0] }) for res in read_elements(cell_sheet, "STRAP", len_data=3): # [cell_no, x_left, x_right, width] straps.append({ "left_front": (res[1] - res[3] / 2, -1), "left_back": (res[1] + res[3] / 2, -1), "right_front": (res[2] - res[3] / 2, -1), "right_back": (res[2] + res[3] / 2, -1), "cells": res[0] }) straps = group(straps, "cells") materials = get_material_codes(cell_sheet) # minirib -> y, start (x) miniribs = [] for minirib in read_elements(cell_sheet, "MINIRIB", len_data=2): miniribs.append({ "yvalue": minirib[1], "front_cut": minirib[2], "cells": minirib[0] }) miniribs = group(miniribs, "cells") lineset_table = Table.from_ods_sheet(sheets[6]) lineset = LineSet2D.read_input_table(lineset_table, attachment_points_lower, attachment_points) glider_2d = Glider2D(elements={ "cuts": cuts, "holes": rib_holes, "diagonals": diagonals, "rigidfoils": rigidfoils, "straps": straps, "materials": materials, "miniribs": miniribs }, profiles=profiles, balloonings=balloonings, lineset=lineset, speed=data["SPEED"], glide=data["GLIDE"], **geometry) if calc_lineset_nodes: glider_3d = glider_2d.get_glider_3d() glider_2d.lineset.set_default_nodes2d_pos(glider_3d) return glider_2d