Spaces:
Sleeping
Sleeping
Commit ·
de8cb80
1
Parent(s): f6ee655
Fix caching: avoid rerunning inverse design during thermoforming
Browse files- .gitignore +15 -0
- inverse_design_demo/app.py +176 -52
.gitignore
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
__pycache__/
|
| 2 |
+
*.pyc
|
| 3 |
+
*.pyo
|
| 4 |
+
*.pyd
|
| 5 |
+
.Python
|
| 6 |
+
*.egg-info/
|
| 7 |
+
.pytest_cache/
|
| 8 |
+
.ruff_cache/
|
| 9 |
+
.mypy_cache/
|
| 10 |
+
.ipynb_checkpoints/
|
| 11 |
+
|
| 12 |
+
# OS/editor
|
| 13 |
+
.DS_Store
|
| 14 |
+
.vscode/
|
| 15 |
+
.idea/
|
inverse_design_demo/app.py
CHANGED
|
@@ -200,6 +200,8 @@ if 'input_curve_button_clicked' not in st.session_state:
|
|
| 200 |
st.session_state.input_curve_button_clicked= False
|
| 201 |
def input_curve_click():
|
| 202 |
st.session_state.input_curve_button_clicked = True
|
|
|
|
|
|
|
| 203 |
|
| 204 |
if 'material_design_button_clicked' not in st.session_state:
|
| 205 |
st.session_state.material_design_button_clicked= False
|
|
@@ -217,6 +219,8 @@ if 'forming_design_button_clicked' not in st.session_state:
|
|
| 217 |
st.session_state.forming_design_button_clicked= False
|
| 218 |
def forming_design_click():
|
| 219 |
st.session_state.forming_design_button_clicked = True
|
|
|
|
|
|
|
| 220 |
|
| 221 |
|
| 222 |
|
|
@@ -236,6 +240,36 @@ angle=30
|
|
| 236 |
#######################
|
| 237 |
# Backend helpers (no UI changes)
|
| 238 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 239 |
DEFAULT_CHECKPOINT_DIR = os.environ.get(
|
| 240 |
"MG_CHECKPOINT_DIR",
|
| 241 |
os.path.join(
|
|
@@ -246,9 +280,14 @@ DEFAULT_CHECKPOINT_DIR = os.environ.get(
|
|
| 246 |
"exp_20260114_164540",
|
| 247 |
),
|
| 248 |
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 249 |
DEFAULT_DATA_DIR = os.environ.get(
|
| 250 |
"MG_DATA_DIR",
|
| 251 |
-
|
| 252 |
)
|
| 253 |
DEFAULT_CURVE_DIR = os.environ.get(
|
| 254 |
"MG_CURVE_DIR",
|
|
@@ -463,6 +502,18 @@ def _load_poly_metadata_small(data_dir: str) -> dict:
|
|
| 463 |
meta_path = os.path.join(str(data_dir), "metadata.json")
|
| 464 |
if not os.path.exists(meta_path):
|
| 465 |
raise FileNotFoundError(f"metadata.json not found in {data_dir}")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 466 |
|
| 467 |
# These keys live very early in the file (per grep): keep this small for Streamlit responsiveness.
|
| 468 |
keys = [
|
|
@@ -475,16 +526,39 @@ def _load_poly_metadata_small(data_dir: str) -> dict:
|
|
| 475 |
"angle_max",
|
| 476 |
]
|
| 477 |
|
|
|
|
|
|
|
| 478 |
prefix_bytes = 256_000
|
|
|
|
| 479 |
with open(meta_path, "r") as f:
|
| 480 |
-
|
| 481 |
-
|
| 482 |
-
|
| 483 |
-
|
| 484 |
-
|
| 485 |
-
|
| 486 |
-
|
| 487 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 488 |
|
| 489 |
|
| 490 |
@st.cache_resource(show_spinner=False)
|
|
@@ -819,43 +893,72 @@ if st.session_state.input_changed == True:
|
|
| 819 |
del st.session_state["inverse_design_result"]
|
| 820 |
if "material_design_last_run_id" in st.session_state:
|
| 821 |
del st.session_state["material_design_last_run_id"]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 822 |
st.session_state.input_changed = False
|
| 823 |
|
| 824 |
st.button("Generate required stress-strain curves", use_container_width=True, on_click=input_curve_click)
|
| 825 |
|
| 826 |
if st.session_state.input_curve_button_clicked == True:
|
| 827 |
-
#
|
| 828 |
-
#
|
| 829 |
-
|
| 830 |
-
|
| 831 |
-
|
| 832 |
-
|
| 833 |
-
|
| 834 |
-
|
| 835 |
-
|
| 836 |
-
|
| 837 |
-
|
| 838 |
-
|
| 839 |
-
|
| 840 |
-
|
| 841 |
-
|
| 842 |
-
|
| 843 |
-
|
| 844 |
-
|
| 845 |
-
|
| 846 |
-
|
| 847 |
-
|
| 848 |
-
|
| 849 |
-
|
| 850 |
-
|
| 851 |
-
|
| 852 |
-
|
| 853 |
-
|
| 854 |
-
|
| 855 |
-
|
| 856 |
-
|
| 857 |
-
|
| 858 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 859 |
|
| 860 |
|
| 861 |
#ylimit=np.max([np.max(y1),np.max(y2), np.max(y3)])
|
|
@@ -1102,19 +1205,27 @@ if st.session_state.input_curve_button_clicked == True:
|
|
| 1102 |
st.write("")
|
| 1103 |
st.button("Thermoforming Requirements", use_container_width=True, on_click=forming_input_click)
|
| 1104 |
if st.session_state.forming_input_button_clicked == True:
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1105 |
#st.write("")
|
| 1106 |
# 4th row with 3 columns
|
| 1107 |
col1_row4, col2_row4, col3_row4, col4_row4, col5_row4 = st.columns([0.16,0.16,0.2,0.24,0.24])
|
| 1108 |
with col1_row4:
|
| 1109 |
with st.container(border=False): # Container with a border
|
| 1110 |
-
|
| 1111 |
-
|
| 1112 |
-
|
| 1113 |
-
st.write("
|
|
|
|
|
|
|
|
|
|
| 1114 |
with col2_row4:
|
| 1115 |
with st.container(border=False): # Container with a border
|
| 1116 |
df = pd.DataFrame({'Ply': [], 'Orientation': []})
|
| 1117 |
-
|
|
|
|
| 1118 |
plies_df=pd.DataFrame(plies, columns=df.columns)
|
| 1119 |
df = pd.concat([df, plies_df], ignore_index=True)
|
| 1120 |
st.dataframe(df, hide_index=True)
|
|
@@ -1139,15 +1250,28 @@ if st.session_state.input_curve_button_clicked == True:
|
|
| 1139 |
|
| 1140 |
st.write("")
|
| 1141 |
if st.session_state.forming_input_changed == True:
|
| 1142 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1143 |
st.session_state.forming_input_changed = False
|
| 1144 |
st.button("Thermoforming process design", use_container_width=True, on_click=forming_design_click)
|
| 1145 |
if st.session_state.forming_design_button_clicked == True:
|
| 1146 |
-
|
| 1147 |
-
|
| 1148 |
-
|
| 1149 |
-
|
| 1150 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1151 |
# 5th row with 3 columns
|
| 1152 |
col1_row5, col2_row5,col3_row5 = st.columns([0.25,0.25,0.25])
|
| 1153 |
with col1_row5:
|
|
|
|
| 200 |
st.session_state.input_curve_button_clicked= False
|
| 201 |
def input_curve_click():
|
| 202 |
st.session_state.input_curve_button_clicked = True
|
| 203 |
+
# allow repeated attempts: each click increments run id
|
| 204 |
+
st.session_state.input_curve_run_id = int(st.session_state.get("input_curve_run_id", 0)) + 1
|
| 205 |
|
| 206 |
if 'material_design_button_clicked' not in st.session_state:
|
| 207 |
st.session_state.material_design_button_clicked= False
|
|
|
|
| 219 |
st.session_state.forming_design_button_clicked= False
|
| 220 |
def forming_design_click():
|
| 221 |
st.session_state.forming_design_button_clicked = True
|
| 222 |
+
# allow repeated attempts: each click increments run id
|
| 223 |
+
st.session_state.forming_design_run_id = int(st.session_state.get("forming_design_run_id", 0)) + 1
|
| 224 |
|
| 225 |
|
| 226 |
|
|
|
|
| 240 |
#######################
|
| 241 |
# Backend helpers (no UI changes)
|
| 242 |
|
| 243 |
+
def _is_git_lfs_pointer_file(path: str) -> bool:
|
| 244 |
+
"""
|
| 245 |
+
Hugging Face / git checkouts sometimes contain Git-LFS pointer files instead of real data.
|
| 246 |
+
Detect that case so we can fall back to a real dataset path (or raise a clearer error).
|
| 247 |
+
"""
|
| 248 |
+
try:
|
| 249 |
+
if not os.path.isfile(path):
|
| 250 |
+
return False
|
| 251 |
+
# Pointer files are tiny (a few hundred bytes).
|
| 252 |
+
if os.path.getsize(path) > 2048:
|
| 253 |
+
return False
|
| 254 |
+
with open(path, "r") as f:
|
| 255 |
+
head = f.read(256)
|
| 256 |
+
return "git-lfs.github.com/spec/v1" in head
|
| 257 |
+
except Exception:
|
| 258 |
+
return False
|
| 259 |
+
|
| 260 |
+
|
| 261 |
+
def _choose_first_real_data_dir(candidates: list[str]) -> str:
|
| 262 |
+
"""
|
| 263 |
+
Pick the first candidate that contains a non-LFS metadata.json.
|
| 264 |
+
Returns the first candidate if none match (caller may still error later with a clear message).
|
| 265 |
+
"""
|
| 266 |
+
for d in candidates:
|
| 267 |
+
meta = os.path.join(str(d), "metadata.json")
|
| 268 |
+
if os.path.exists(meta) and (not _is_git_lfs_pointer_file(meta)):
|
| 269 |
+
return str(d)
|
| 270 |
+
return str(candidates[0]) if candidates else ""
|
| 271 |
+
|
| 272 |
+
|
| 273 |
DEFAULT_CHECKPOINT_DIR = os.environ.get(
|
| 274 |
"MG_CHECKPOINT_DIR",
|
| 275 |
os.path.join(
|
|
|
|
| 280 |
"exp_20260114_164540",
|
| 281 |
),
|
| 282 |
)
|
| 283 |
+
|
| 284 |
+
# NOTE: The Space repo can contain LFS pointers for large datasets. Prefer a "real" dataset
|
| 285 |
+
# if available (commonly checked out at the MaterialGeneration root alongside this repo).
|
| 286 |
+
_default_data_dir_space = os.path.join(ROOT_DIR, "data_generation", "processed_dataset", "config_1")
|
| 287 |
+
_default_data_dir_root = os.path.abspath(os.path.join(ROOT_DIR, "..", "data_generation", "processed_dataset", "config_1"))
|
| 288 |
DEFAULT_DATA_DIR = os.environ.get(
|
| 289 |
"MG_DATA_DIR",
|
| 290 |
+
_choose_first_real_data_dir([_default_data_dir_space, _default_data_dir_root]),
|
| 291 |
)
|
| 292 |
DEFAULT_CURVE_DIR = os.environ.get(
|
| 293 |
"MG_CURVE_DIR",
|
|
|
|
| 502 |
meta_path = os.path.join(str(data_dir), "metadata.json")
|
| 503 |
if not os.path.exists(meta_path):
|
| 504 |
raise FileNotFoundError(f"metadata.json not found in {data_dir}")
|
| 505 |
+
if _is_git_lfs_pointer_file(meta_path):
|
| 506 |
+
raise RuntimeError(
|
| 507 |
+
"\n".join(
|
| 508 |
+
[
|
| 509 |
+
"metadata.json looks like a Git-LFS pointer file, not the actual dataset.",
|
| 510 |
+
f"path: {meta_path}",
|
| 511 |
+
"Fix options:",
|
| 512 |
+
" - Point MG_DATA_DIR to a real dataset folder that contains the full metadata.json, or",
|
| 513 |
+
" - If this repo was cloned with git-lfs available, run: git lfs pull",
|
| 514 |
+
]
|
| 515 |
+
)
|
| 516 |
+
)
|
| 517 |
|
| 518 |
# These keys live very early in the file (per grep): keep this small for Streamlit responsiveness.
|
| 519 |
keys = [
|
|
|
|
| 526 |
"angle_max",
|
| 527 |
]
|
| 528 |
|
| 529 |
+
# Start small for responsiveness, but grow if needed (some metadata.json variants have these keys later).
|
| 530 |
+
max_prefix_bytes = 8_000_000
|
| 531 |
prefix_bytes = 256_000
|
| 532 |
+
prefix = ""
|
| 533 |
with open(meta_path, "r") as f:
|
| 534 |
+
while True:
|
| 535 |
+
prefix = f.read(prefix_bytes)
|
| 536 |
+
try:
|
| 537 |
+
out = {}
|
| 538 |
+
for k in keys:
|
| 539 |
+
raw = _extract_json_value_prefix(prefix, k)
|
| 540 |
+
out[k] = json.loads(raw)
|
| 541 |
+
return out
|
| 542 |
+
except KeyError:
|
| 543 |
+
# Not all keys in the current prefix; try a larger read.
|
| 544 |
+
if prefix_bytes >= max_prefix_bytes:
|
| 545 |
+
break
|
| 546 |
+
prefix_bytes = min(int(prefix_bytes * 2), max_prefix_bytes)
|
| 547 |
+
f.seek(0)
|
| 548 |
+
|
| 549 |
+
# Last resort: if we still couldn't find keys in a large prefix, try loading full JSON only
|
| 550 |
+
# when it won't explode memory.
|
| 551 |
+
try:
|
| 552 |
+
size = os.path.getsize(meta_path)
|
| 553 |
+
except Exception:
|
| 554 |
+
size = None
|
| 555 |
+
if size is not None and size <= 64_000_000:
|
| 556 |
+
with open(meta_path, "r") as f:
|
| 557 |
+
full = json.load(f)
|
| 558 |
+
return {k: full[k] for k in keys}
|
| 559 |
+
raise KeyError(
|
| 560 |
+
f"Could not locate required keys {keys} in the first {prefix_bytes} bytes of metadata.json at {meta_path}"
|
| 561 |
+
)
|
| 562 |
|
| 563 |
|
| 564 |
@st.cache_resource(show_spinner=False)
|
|
|
|
| 893 |
del st.session_state["inverse_design_result"]
|
| 894 |
if "material_design_last_run_id" in st.session_state:
|
| 895 |
del st.session_state["material_design_last_run_id"]
|
| 896 |
+
if "input_curve_last_run_id" in st.session_state:
|
| 897 |
+
del st.session_state["input_curve_last_run_id"]
|
| 898 |
+
if "forming_design_result" in st.session_state:
|
| 899 |
+
del st.session_state["forming_design_result"]
|
| 900 |
+
if "forming_design_last_run_id" in st.session_state:
|
| 901 |
+
del st.session_state["forming_design_last_run_id"]
|
| 902 |
st.session_state.input_changed = False
|
| 903 |
|
| 904 |
st.button("Generate required stress-strain curves", use_container_width=True, on_click=input_curve_click)
|
| 905 |
|
| 906 |
if st.session_state.input_curve_button_clicked == True:
|
| 907 |
+
# Only (re)generate curves when the user explicitly clicks the button again,
|
| 908 |
+
# or when curves don't exist yet. Otherwise keep cached curves to avoid
|
| 909 |
+
# invalidating material inverse design on unrelated reruns (e.g. thermoforming clicks).
|
| 910 |
+
current_curve_run_id = int(st.session_state.get("input_curve_run_id", 0))
|
| 911 |
+
last_curve_run_id = int(st.session_state.get("input_curve_last_run_id", -1))
|
| 912 |
+
if ("required_curves" not in st.session_state) or (current_curve_run_id != last_curve_run_id):
|
| 913 |
+
#st.write(E1aV)
|
| 914 |
+
#st.write(E1bV)
|
| 915 |
+
n_pts = int(max(4, N_INPUT_POINTS))
|
| 916 |
+
x = np.linspace(0, 0.1, n_pts)
|
| 917 |
+
A = np.array([[0.2, 0.03], [0.01, 0.001]])
|
| 918 |
+
b = np.array([E1bV-E1aV, S1bV-E1aV*0.1])
|
| 919 |
+
a = np.linalg.solve(A, b)
|
| 920 |
+
y1= E1aV*x + a[0]*x**2 + a[1]*x**3
|
| 921 |
+
b = np.array([E2bV-E2aV, S2bV-E2aV*0.1])
|
| 922 |
+
a = np.linalg.solve(A, b)
|
| 923 |
+
y2= E2aV*x + a[0]*x**2 + a[1]*x**3
|
| 924 |
+
b = np.array([G12bV-G12aV, S12bV-G12aV*0.1])
|
| 925 |
+
a = np.linalg.solve(A, b)
|
| 926 |
+
y3= G12aV*x + a[0]*x**2 + a[1]*x**3
|
| 927 |
+
|
| 928 |
+
y4 = v12aV*x + (v12bV - v12aV)/0.2*x*x
|
| 929 |
+
y5 = v21aV*x + (v21bV - v21aV)/0.2*x*x
|
| 930 |
+
|
| 931 |
+
# Cache required curves for inverse design (model conditioning)
|
| 932 |
+
st.session_state.required_curves = {
|
| 933 |
+
"eps11": x.astype(np.float32),
|
| 934 |
+
"sig11_mpa": y1.astype(np.float32),
|
| 935 |
+
"eps22": x.astype(np.float32),
|
| 936 |
+
"sig22_mpa": y2.astype(np.float32),
|
| 937 |
+
"eps12": x.astype(np.float32),
|
| 938 |
+
"sig12_mpa": y3.astype(np.float32),
|
| 939 |
+
"eps22_from_eps11": (-y4).astype(np.float32),
|
| 940 |
+
"eps11_from_eps22": (-y5).astype(np.float32),
|
| 941 |
+
}
|
| 942 |
+
st.session_state.input_curve_last_run_id = current_curve_run_id
|
| 943 |
+
|
| 944 |
+
# New curves -> invalidate any previous inverse-design result
|
| 945 |
+
if "inverse_design_result" in st.session_state:
|
| 946 |
+
del st.session_state["inverse_design_result"]
|
| 947 |
+
if "material_design_last_run_id" in st.session_state:
|
| 948 |
+
del st.session_state["material_design_last_run_id"]
|
| 949 |
+
# ...and any downstream thermoforming process result (it depends on material design)
|
| 950 |
+
if "forming_design_result" in st.session_state:
|
| 951 |
+
del st.session_state["forming_design_result"]
|
| 952 |
+
if "forming_design_last_run_id" in st.session_state:
|
| 953 |
+
del st.session_state["forming_design_last_run_id"]
|
| 954 |
+
else:
|
| 955 |
+
curves = st.session_state.required_curves
|
| 956 |
+
x = np.asarray(curves["eps11"], dtype=np.float32)
|
| 957 |
+
y1 = np.asarray(curves["sig11_mpa"], dtype=np.float32)
|
| 958 |
+
y2 = np.asarray(curves["sig22_mpa"], dtype=np.float32)
|
| 959 |
+
y3 = np.asarray(curves["sig12_mpa"], dtype=np.float32)
|
| 960 |
+
y4 = -np.asarray(curves["eps22_from_eps11"], dtype=np.float32)
|
| 961 |
+
y5 = -np.asarray(curves["eps11_from_eps22"], dtype=np.float32)
|
| 962 |
|
| 963 |
|
| 964 |
#ylimit=np.max([np.max(y1),np.max(y2), np.max(y3)])
|
|
|
|
| 1205 |
st.write("")
|
| 1206 |
st.button("Thermoforming Requirements", use_container_width=True, on_click=forming_input_click)
|
| 1207 |
if st.session_state.forming_input_button_clicked == True:
|
| 1208 |
+
# Safety: thermoforming steps require a material inverse design result.
|
| 1209 |
+
if "inverse_design_result" not in st.session_state:
|
| 1210 |
+
st.warning("Please run 'Material Inverse Design' first. Thermoforming steps reuse that result and will not recompute it.")
|
| 1211 |
+
st.stop()
|
| 1212 |
#st.write("")
|
| 1213 |
# 4th row with 3 columns
|
| 1214 |
col1_row4, col2_row4, col3_row4, col4_row4, col5_row4 = st.columns([0.16,0.16,0.2,0.24,0.24])
|
| 1215 |
with col1_row4:
|
| 1216 |
with st.container(border=False): # Container with a border
|
| 1217 |
+
# Reuse the cached material inverse design result (do not recompute)
|
| 1218 |
+
nlayers = int(len(res["full_angles"]))
|
| 1219 |
+
vf = float(res["vf"])
|
| 1220 |
+
st.write("Matrix material = ", res["matrix"])
|
| 1221 |
+
st.write("Fiber material = ", res["fiber"])
|
| 1222 |
+
st.write("Number of layers = ", nlayers)
|
| 1223 |
+
st.write("Volume fraction = ", f"{vf:.3f}")
|
| 1224 |
with col2_row4:
|
| 1225 |
with st.container(border=False): # Container with a border
|
| 1226 |
df = pd.DataFrame({'Ply': [], 'Orientation': []})
|
| 1227 |
+
# Use the designed stacking sequence
|
| 1228 |
+
plies = np.array([[i + 1, float(a)] for i, a in enumerate(res["full_angles"])], dtype=object)
|
| 1229 |
plies_df=pd.DataFrame(plies, columns=df.columns)
|
| 1230 |
df = pd.concat([df, plies_df], ignore_index=True)
|
| 1231 |
st.dataframe(df, hide_index=True)
|
|
|
|
| 1250 |
|
| 1251 |
st.write("")
|
| 1252 |
if st.session_state.forming_input_changed == True:
|
| 1253 |
+
# Any change to thermoforming requirements invalidates cached process design result
|
| 1254 |
+
if "forming_design_result" in st.session_state:
|
| 1255 |
+
del st.session_state["forming_design_result"]
|
| 1256 |
+
if "forming_design_last_run_id" in st.session_state:
|
| 1257 |
+
del st.session_state["forming_design_last_run_id"]
|
| 1258 |
st.session_state.forming_input_changed = False
|
| 1259 |
st.button("Thermoforming process design", use_container_width=True, on_click=forming_design_click)
|
| 1260 |
if st.session_state.forming_design_button_clicked == True:
|
| 1261 |
+
# Cache thermoforming process design result so it doesn't rerun on every Streamlit rerender.
|
| 1262 |
+
current_run_id = int(st.session_state.get("forming_design_run_id", 0))
|
| 1263 |
+
last_run_id = int(st.session_state.get("forming_design_last_run_id", -1))
|
| 1264 |
+
if ("forming_design_result" not in st.session_state) or (current_run_id != last_run_id):
|
| 1265 |
+
with st.spinner("Optimizing thermoforming process parameters..."):
|
| 1266 |
+
st.session_state.forming_design_result = inverse_design(
|
| 1267 |
+
ply_number=nlayers,
|
| 1268 |
+
fiber_vf=vf,
|
| 1269 |
+
y_target=[angleA, angleB, angleC, max_stress],
|
| 1270 |
+
n_restarts=5,
|
| 1271 |
+
epochs=100,
|
| 1272 |
+
)
|
| 1273 |
+
st.session_state.forming_design_last_run_id = current_run_id
|
| 1274 |
+
best = st.session_state.forming_design_result
|
| 1275 |
# 5th row with 3 columns
|
| 1276 |
col1_row5, col2_row5,col3_row5 = st.columns([0.25,0.25,0.25])
|
| 1277 |
with col1_row5:
|