From 4ee60273262678ddbc094b589a30adf0866cb110 Mon Sep 17 00:00:00 2001 From: sryu Date: Tue, 1 Oct 2024 23:47:44 -0600 Subject: [PATCH] basic function to visualize single airfoil shape and polars --- .../app/pages/visualize_windio_airfoils.py | 96 +++++++++++++------ weis/visualization/utils.py | 3 +- 2 files changed, 71 insertions(+), 28 deletions(-) diff --git a/weis/visualization/appServer/app/pages/visualize_windio_airfoils.py b/weis/visualization/appServer/app/pages/visualize_windio_airfoils.py index 2eab9333f..77798f858 100644 --- a/weis/visualization/appServer/app/pages/visualize_windio_airfoils.py +++ b/weis/visualization/appServer/app/pages/visualize_windio_airfoils.py @@ -35,6 +35,7 @@ # We are using card container where we define sublayout with rows and cols. def layout(): + global airfoil_by_names # Need to exclude this later (for simplicity for now) airfoils = load_airfoils() # Data structure: [{'name': 'FB90', 'coordinates': {'x': [1.0, 0.9921, ...]}}] airfoil_by_names = {airfoil['name']: dict(list(airfoil.items())[1:]) for airfoil in airfoils} # {'FB90': {'coordinates': {'x': [1.0, 0.9921, ...]}, ...}, ...} # airfoil_names = [airfoil['name'] for airfoil in airfoils] @@ -43,14 +44,15 @@ def layout(): dbc.CardHeader("Airfoil Name: ", className='cardHeader'), dbc.CardBody([ dcc.Dropdown(id='airfoil-name', options=list(airfoil_by_names.keys()), value=None, multi=False), + dcc.Loading(html.P(id='airfoil-description')), dcc.Loading(dcc.Graph(id='airfoil-coords', figure=empty_figure())), ]) ], className='card') polars_layout = dbc.Card([ - dbc.CardHeader("Airfoil Name: ", className='cardHeader'), + dbc.CardHeader(html.P(id='airfoil-re'), className='cardHeader'), dbc.CardBody([ - dcc.Dropdown(id='airfoil-name', options=list(airfoil_by_names.keys()), value=None, multi=False), + # dcc.Dropdown(id='airfoil-name', options=list(airfoil_by_names.keys()), value=None, multi=False), dcc.Loading(dcc.Graph(id='airfoil-polars', figure=empty_figure())), ]) ], className='card') @@ -63,7 +65,7 @@ def layout(): layout = dbc.Row([ - dbc.Col(coords_layout, width=5), + dbc.Col(coords_layout, width=6), dbc.Col(polars_layout, width=6) ], className='wrapper') @@ -71,38 +73,78 @@ def layout(): @callback(Output('airfoil-coords', 'figure'), + Output('airfoil-description', 'children'), Input('airfoil-name', 'value')) -def draw_blade_shape(blade_options): - if blade_options is None: +def draw_airfoil_shape(airfoil_name): + if airfoil_name is None: raise PreventUpdate - x = blade_options['x'] - ys = blade_options['ys'] - - fig = make_subplots(rows = 2, cols = 1, shared_xaxes=True) - - for y in ys: - if y == 'rotorse.theta_deg': - fig.append_trace(go.Scatter( - x = refturb[x], - y = refturb[y], - mode = 'lines+markers', - name = y), - row = 2, + text = html.P(str(airfoil_by_names[airfoil_name]['description'])) + + x = airfoil_by_names[airfoil_name]['coordinates']['x'] + y = airfoil_by_names[airfoil_name]['coordinates']['y'] + + fig = make_subplots(rows = 1, cols = 1, shared_xaxes=True) + + fig.append_trace(go.Scatter( + x = x, + y = y, + mode = 'lines+markers'), + row = 1, col = 1) - else: - fig.append_trace(go.Scatter( - x = refturb[x], - y = refturb[y], - mode = 'lines+markers', - name = y), + + fig.update_layout(plot_bgcolor='white') + fig.update_xaxes(mirror = True, ticks='outside', showline=True, linecolor='black', gridcolor='lightgrey') + fig.update_yaxes(mirror = True, ticks='outside', showline=True, linecolor='black', gridcolor='lightgrey') + fig.update_xaxes(title_text=f'coords', row=1, col=1) + fig.update_yaxes(title_text=f'value', row=1, col=1) + + print(airfoil_by_names[airfoil_name]['polars']) + + return fig, text + + +@callback(Output('airfoil-re', 'children'), + Output('airfoil-polars', 'figure'), + Input('airfoil-name', 'value')) +def draw_airfoil_polar(airfoil_name): + if airfoil_name is None: + raise PreventUpdate + + polars_dict = airfoil_by_names[airfoil_name]['polars'][0] + airfoil_re = html.P('re: ' + str(polars_dict['re'])) + + fig = make_subplots(rows = 1, cols = 1, shared_xaxes=True) + + fig.append_trace(go.Scatter( + x = np.rad2deg(polars_dict['c_l']['grid']), + y = polars_dict['c_l']['values'], + mode = 'lines', + name = 'c_l'), + row = 1, + col = 1) + + fig.append_trace(go.Scatter( + x = np.rad2deg(polars_dict['c_d']['grid']), + y = polars_dict['c_d']['values'], + mode = 'lines', + name = 'c_d'), row = 1, col = 1) - + fig.append_trace(go.Scatter( + x = np.rad2deg(polars_dict['c_m']['grid']), + y = polars_dict['c_m']['values'], + mode = 'lines', + name = 'c_m'), + row = 1, + col = 1) + fig.update_layout(plot_bgcolor='white') fig.update_xaxes(mirror = True, ticks='outside', showline=True, linecolor='black', gridcolor='lightgrey') fig.update_yaxes(mirror = True, ticks='outside', showline=True, linecolor='black', gridcolor='lightgrey') - fig.update_xaxes(title_text=f'rotorse.rc.s', row=2, col=1) + fig.update_xaxes(title_text=f'grid', row=1, col=1) + fig.update_yaxes(title_text=f'value', row=1, col=1) + - return fig \ No newline at end of file + return airfoil_re, fig \ No newline at end of file diff --git a/weis/visualization/utils.py b/weis/visualization/utils.py index 28789517d..0bc107b92 100644 --- a/weis/visualization/utils.py +++ b/weis/visualization/utils.py @@ -882,7 +882,8 @@ def render_our_own(points): def load_airfoils(): # Read geometry input file # TODO: This is for simplicity. Need to think another way to load geometries. - wt_options = sch.load_geometry_yaml('/projects/weis/sryu/visualization_cases/1_raft_opt/IEA-22-280-RWT.yaml') + # wt_options = sch.load_geometry_yaml('/projects/weis/sryu/visualization_cases/1_raft_opt/IEA-22-280-RWT.yaml') # For HPC + wt_options = sch.load_geometry_yaml('/Users/sryu/Desktop/FY24/WEIS-Visualization/data/visualization_cases/1_raft_opt/IEA-22-280-RWT.yaml') # For Local airfoils = wt_options['airfoils'] return airfoils