Spaces:
Sleeping
Sleeping
| ####################### | |
| # Import libraries | |
| import streamlit as st | |
| import pandas as pd | |
| import altair as alt | |
| import plotly.express as px | |
| from PIL import Image # Used to open and handle image files | |
| import matplotlib.pyplot as plt | |
| import numpy as np | |
| ####################### | |
| # Page configuration | |
| st.set_page_config( | |
| page_title="Inverse Design of Thermoplastic Composites for Thermoforming", | |
| # page_icon="🏂", | |
| layout="wide", | |
| initial_sidebar_state="collapsed") | |
| alt.themes.enable('default') | |
| ####################### | |
| # CSS styling | |
| st.markdown(""" | |
| <style> | |
| /* Target the input element within its container (adjust class name as needed via browser inspection) */ | |
| .stTextInput input { | |
| border: 1px solid #333333; /* Set border width, style, and color */ | |
| border-radius: 6px; /* Optional: adds rounded corners */ | |
| padding: 10px; /* Optional: adds inner spacing */ | |
| } | |
| </style> | |
| """, unsafe_allow_html=True) | |
| st.markdown(""" | |
| <style> | |
| [data-testid="block-container"] { | |
| padding-left: 2rem; | |
| padding-right: 2rem; | |
| padding-top: 1rem; | |
| padding-bottom: 0rem; | |
| margin-bottom: -7rem; | |
| } | |
| [data-testid="stVerticalBlock"] { | |
| padding-left: 0rem; | |
| padding-right: 0rem; | |
| } | |
| [data-testid="stMetric"] { | |
| background-color: #393939; | |
| text-align: center; | |
| padding: 15px 0; | |
| } | |
| [data-testid="stMetricLabel"] { | |
| display: flex; | |
| justify-content: center; | |
| align-items: center; | |
| } | |
| [data-testid="stMetricDeltaIcon-Up"] { | |
| position: relative; | |
| left: 38%; | |
| -webkit-transform: translateX(-50%); | |
| -ms-transform: translateX(-50%); | |
| transform: translateX(-50%); | |
| } | |
| [data-testid="stMetricDeltaIcon-Down"] { | |
| position: relative; | |
| left: 38%; | |
| -webkit-transform: translateX(-50%); | |
| -ms-transform: translateX(-50%); | |
| transform: translateX(-50%); | |
| } | |
| /* Main app + sidebar, target the label element itself */ | |
| [data-testid="stAppViewContainer"] label, | |
| [data-testid="stWidgetLabel"] label { | |
| font-size: 18px !important; | |
| font-weight: 600 !important; /* optional */ | |
| color: #444 !important; /* optional */ | |
| } | |
| /* Some versions wrap label text inside a <div><p> */ | |
| [data-testid="stAppViewContainer"] label > div > p, | |
| [data-testid="stWidgetLabel"] label > div > p { | |
| font-size: 18px !important; | |
| font-weight: 600 !important; | |
| } | |
| </style> | |
| """, unsafe_allow_html=True) | |
| st.markdown(""" | |
| <style> | |
| div.stButton > button:first-child { | |
| background-color: #ee7700; /* background */ | |
| color: white; /* White text */ | |
| font-size: 20px; | |
| border-radius: 10px; | |
| # display: block; # this line and the next center the button horizontally | |
| # margin: 0 auto; | |
| } | |
| </style> | |
| """, unsafe_allow_html=True) | |
| st.markdown(""" | |
| <style> | |
| div[data-testid="stVirtualDropdown"] > div { | |
| max-height: 10px !important; /* Adjust this value as needed */ | |
| overflow-y: auto; | |
| } | |
| </style> | |
| """, unsafe_allow_html=True) | |
| st.set_page_config(initial_sidebar_state="collapsed") | |
| st.markdown( | |
| """ | |
| <style> | |
| [data-testid="collapsedControl"] { | |
| display: none | |
| } | |
| </style> | |
| """, | |
| unsafe_allow_html=True, | |
| ) | |
| ####################### | |
| if 'input_changed' not in st.session_state: | |
| st.session_state.input_changed= False | |
| def input_typed_in(): | |
| st.session_state.input_changed= True | |
| if 'forming_input_changed' not in st.session_state: | |
| st.session_state.forming_input_changed= False | |
| def forming_typed_in(): | |
| st.session_state.forming_input_changed= True | |
| if 'input_curve_button_clicked' not in st.session_state: | |
| st.session_state.input_curve_button_clicked= False | |
| def input_curve_click(): | |
| st.session_state.input_curve_button_clicked = True | |
| if 'material_design_button_clicked' not in st.session_state: | |
| st.session_state.material_design_button_clicked= False | |
| def material_design_click(): | |
| st.session_state.material_design_button_clicked = True | |
| if 'forming_input_button_clicked' not in st.session_state: | |
| st.session_state.forming_input_button_clicked= False | |
| def forming_input_click(): | |
| st.session_state.forming_input_button_clicked = True | |
| if 'forming_design_button_clicked' not in st.session_state: | |
| st.session_state.forming_design_button_clicked= False | |
| def forming_design_click(): | |
| st.session_state.forming_design_button_clicked = True | |
| ####################### | |
| # Load data | |
| #df_reshaped = pd.read_csv('data/us-population-2010-2019-reshaped.csv') | |
| ######## Initialize data ############# | |
| E1aV=0 # initial longitudinal stiffness | |
| E1bV=0 # 10% strain longitudinal stiffness | |
| G12aV=0 # initial longitudinal stiffness | |
| G12bV=0 # 10% strain longitudinal stiffness | |
| nlayers=4 | |
| vf=0.5 | |
| angle=30 | |
| ####################### | |
| # Main Panel | |
| data_materials={ | |
| 'Matrix':['ABS','Polyurethane','Nylon 6','Nylon 6','Nylon 66','PE','PP'], | |
| 'Filler':['Carbon Black','Glass Fiber','Glass Fiber','Carbon Fiber','Glass Fiber','Carbon Fiber','Glass Fiber'], | |
| 'VF':['15%','20%','20%','40%','30%','20%','30%'], | |
| 'Feature':['Blend','Extruded','Molded','Molded','Molded','Molded','Molded'] | |
| } | |
| data_physical = { | |
| 'Forming T (C)': ['180', '185', '190'], | |
| 'Punch V (m/s)': ['1.05', '1.8','1.67'], | |
| 'Cooling time (s)': ['45','80','120'], | |
| 'Holding force (kN)': ['23','24','25'] | |
| } | |
| st.title("Inverse Design of Thermoplastic Composites for Thermoforming") | |
| st.write("") | |
| st.write("") | |
| st.write("") | |
| st.write(r"$\textsf{\textbf{\Large Material Design Requirements}}$") | |
| #st.text_input(r"$\textsf{\textbf{\Large Material Design Requirements}}$") | |
| # First row with 3 columns | |
| col1_row1, col2_row1, col3_row1 = st.columns([0.3,0.3,0.3]) | |
| with col1_row1: | |
| with st.container(border=False): # Container with a border | |
| E1aV= st.number_input("Initial tensile stiffness (MPa):", format="%.2f", width=250, key="E1a", on_change=input_typed_in) | |
| E1bV= st.number_input("10% tensile stiffness (MPa):", format="%.2f", width=250, key="E1b", on_change=input_typed_in) | |
| with col2_row1: | |
| with st.container(border=False): # Container with a border | |
| G12aV= st.number_input("Initial shear stiffness (MPa):", format="%.2f", width=250, key="G12a", on_change=input_typed_in) | |
| G12bV= st.number_input("0.1 shear strain stiffness (MPa):", format="%.2f", width=250, key="G12b", on_change=input_typed_in) | |
| with col3_row1: | |
| with st.container(border=False): # Container with a border | |
| EratioV= st.number_input("Anisotropicity (Ex/Ey):", format="%.2f", width=250, key="Eratio", on_change=input_typed_in) | |
| st.write("") | |
| if st.session_state.input_changed == True: | |
| st.session_state.input_curve_button_clicked = False | |
| st.session_state.material_design_button_clicked = False | |
| st.session_state.forming_input_button_clicked = False | |
| st.session_state.forming_design_button_clicked = False | |
| st.session_state.input_changed = False | |
| st.button("Generate required stress-strain curves", width=400, on_click=input_curve_click) | |
| if st.session_state.input_curve_button_clicked == True: | |
| #st.write(E1aV) | |
| #st.write(E1bV) | |
| x = np.linspace(0, 0.1, 20) | |
| y1 = E1aV*x + (E1bV-E1aV)/0.2*x*x | |
| y2 = G12aV*x + (G12bV-G12aV)/0.2*x*x | |
| y3 = y1/EratioV | |
| ylimit=np.max([np.max(y1),np.max(y2), np.max(y3)]) | |
| # 2nd row with 3 columns | |
| col1_row2, col2_row2, col3_row2, col4_row2= st.columns([0.25,0.25,0.25,0.25]) | |
| with col1_row2: | |
| with st.container(border=False): # Container with a border | |
| fig, ax = plt.subplots() | |
| ax.plot(x, y1) | |
| ax.set_ylim([0, ylimit]) | |
| ax.set_xlabel('Stress (MPa)') | |
| ax.set_ylabel('Strain') | |
| ax.set_title('Longitudinal stress-strain') | |
| st.pyplot(fig) | |
| with col2_row2: | |
| with st.container(border=False): # Container with a border | |
| fig, ax = plt.subplots() | |
| ax.plot(x, y2) | |
| ax.set_ylim([0, ylimit]) | |
| ax.set_xlabel('Stress (MPa)') | |
| ax.set_ylabel('Strain') | |
| ax.set_title('Shear stress-strain') | |
| st.pyplot(fig) | |
| with col3_row2: | |
| with st.container(border=False): # Container with a border | |
| fig, ax = plt.subplots() | |
| ax.plot(x, y3) | |
| ax.set_ylim([0, ylimit]) | |
| ax.set_xlabel('Stress (MPa)') | |
| ax.set_ylabel('Strain') | |
| ax.set_title('Shear stress-strain') | |
| st.pyplot(fig) | |
| st.write("") | |
| st.button("Material Inverse Design", width=400, on_click=material_design_click) | |
| if st.session_state.material_design_button_clicked == True: | |
| #st.write("") | |
| # 3rd row with 3 columns | |
| col1_row3, col2_row3, col3_row3, col4_row3, col5_row3= st.columns([0.15,0.15,0.23,0.23,0.23]) | |
| with col1_row3: | |
| with st.container(border=False): # Container with a border | |
| st.write("Number of layers=", nlayers) | |
| st.write("Volume fraction=", vf) | |
| with col2_row3: | |
| with st.container(border=False): # Container with a border | |
| df = pd.DataFrame({'Ply': [], 'Orientation': []}) | |
| plies = np.array([[1,90], [2,45], [3,-45], [4,-90]]) | |
| plies_df=pd.DataFrame(plies, columns=df.columns) | |
| df = pd.concat([df, plies_df], ignore_index=True) | |
| st.dataframe(df, hide_index=True) | |
| with col3_row3: | |
| with st.container(border=False): # Container with a border | |
| image = Image.open('figures/material_res3.png') | |
| new_image = image.resize((250, 200)) | |
| st.image(new_image, caption='') | |
| with col4_row3: | |
| with st.container(border=False): # Container with a border | |
| image = Image.open('figures/material_res3.png') | |
| new_image = image.resize((250, 200)) | |
| st.image(new_image, caption='') | |
| with col5_row3: | |
| with st.container(border=False): # Container with a border | |
| image = Image.open('figures/material_res3.png') | |
| new_image = image.resize((250, 200)) | |
| st.image(new_image, caption='') | |
| st.write("") | |
| st.button("Thermoforming Requirements", width=400, on_click=forming_input_click) | |
| if st.session_state.forming_input_button_clicked == True: | |
| #st.write("") | |
| # 4th row with 3 columns | |
| col1_row4, col2_row4, col3_row4, col4_row4, col5_row4 = st.columns([0.16,0.16,0.2,0.24,0.24]) | |
| with col1_row4: | |
| with st.container(border=False): # Container with a border | |
| st.write("Number of layers=", nlayers) | |
| st.write("Volume fraction=", vf) | |
| st.write("Fiber orientation=", angle) | |
| with col2_row4: | |
| with st.container(border=False): # Container with a border | |
| df = pd.DataFrame({'Ply': [], 'Orientation': []}) | |
| plies = np.array([[1,90], [2,45], [3,-45], [4,-90]]) | |
| plies_df=pd.DataFrame(plies, columns=df.columns) | |
| df = pd.concat([df, plies_df], ignore_index=True) | |
| st.dataframe(df, hide_index=True) | |
| with col3_row4: | |
| with st.container(border=False): # Container with a border | |
| image = Image.open('figures/forming_angle.png') | |
| new_image = image.resize((250, 200)) | |
| st.image(new_image, caption='') | |
| with col4_row4: | |
| with st.container(border=False): # Container with a border | |
| angleA= st.number_input("Maximum warpage angle A (degree):", format="%.2f", width=300, key="A", on_change=forming_typed_in) | |
| angleB= st.number_input("Maximum warpage angle B (degree):", format="%.2f", width=300, key="B", on_change=forming_typed_in) | |
| with col5_row4: | |
| with st.container(border=False): # Container with a border | |
| angleC= st.number_input("Maximum warpage angle C (degree):", format="%.2f", width=300, key="C", on_change=forming_typed_in) | |
| max_stress= st.number_input("Maximum residual stress (MPa):", format="%.2f", width=300, key="max_stress", on_change=forming_typed_in) | |
| st.write("") | |
| if st.session_state.forming_input_changed == True: | |
| st.session_state.forming_design_button_clicked = False | |
| st.session_state.forming_input_changed = False | |
| st.button("Thermoforming process design", width=400, on_click=forming_design_click) | |
| if st.session_state.forming_design_button_clicked == True: | |
| # 5th row with 3 columns | |
| col1_row5, col2_row5,col3_row5 = st.columns([0.25,0.25,0.25]) | |
| with col1_row5: | |
| with st.container(border=False): # Container with a border | |
| st.write("Forming temperature (C)=", nlayers) | |
| with col2_row5: | |
| with st.container(border=False): # Container with a border | |
| st.write("Punching velocity (mm/s)=", nlayers) | |
| with col3_row5: | |
| with st.container(border=False): # Container with a border | |
| st.write("Cooling time (s)=", nlayers) | |