| from __future__ import annotations |
|
|
| import importlib.util |
| import os |
| import sys |
| from pathlib import Path |
| from typing import Dict, List |
|
|
| import numpy as np |
|
|
|
|
| def _default_data_generation_dir() -> Path: |
| env = os.environ.get("MG_QUARTER_DATA_GEN_DIR") |
| if env: |
| return Path(env).resolve() |
| return (Path(__file__).resolve().parent.parent / "assets" / "quarter_sim").resolve() |
|
|
|
|
| def _import_module_from_path(module_name: str, path: Path): |
| spec = importlib.util.spec_from_file_location(module_name, path) |
| module = importlib.util.module_from_spec(spec) |
| assert spec and spec.loader |
| spec.loader.exec_module(module) |
| return module |
|
|
|
|
| def format_vol_fraction(vf: float) -> str: |
| return f"{float(vf):.4f}" |
|
|
|
|
| def simulate_instances( |
| *, |
| curve_dir: str, |
| mat_type: str, |
| vf: float, |
| quarter_angles: List[float], |
| instances: List[int], |
| num_output_points: int = 20, |
| ) -> Dict[int, Dict[str, Dict[str, np.ndarray]]]: |
| data_gen_dir = _default_data_generation_dir() |
| if not data_gen_dir.exists(): |
| raise FileNotFoundError(f"Quarter data-generation directory not found: {data_gen_dir}") |
|
|
| if str(data_gen_dir) not in sys.path: |
| sys.path.insert(0, str(data_gen_dir)) |
|
|
| gen_mod = _import_module_from_path("quarter_gen_v2", data_gen_dir / "generate_data_mp_version_2.py") |
| lam2 = _import_module_from_path("quarter_lam2", data_gen_dir / "lam2.py") |
|
|
| curve_dir_path = Path(curve_dir).resolve() |
| if not curve_dir_path.exists(): |
| raise FileNotFoundError(f"curve_dir does not exist: {curve_dir_path}") |
|
|
| vf_str = format_vol_fraction(vf) |
| prefix = f"{mat_type}_{vf_str}" |
|
|
| original_curve_dir = lam2.CURVE_DIR |
| lam2.CURVE_DIR = curve_dir_path |
| try: |
| mat = lam2.load_ud_material_from_files(prefix) |
| finally: |
| lam2.CURVE_DIR = original_curve_dir |
|
|
| full_angles = list(gen_mod.build_full_from_quarter_angles([float(a) for a in quarter_angles])) |
|
|
| out: Dict[int, Dict[str, Dict[str, np.ndarray]]] = {} |
| for inst in instances: |
| sim_modes: Dict[str, Dict[str, np.ndarray]] = {} |
| for mode in ("11", "22", "12"): |
| try: |
| ex, sx, ey, _gxy, ezz, _g23, _g13, e11 = gen_mod.run_simulation_with_mat(prefix, full_angles, mode, mat) |
| if len(ex) < 2: |
| continue |
| x_out = np.linspace(float(ex[0]), float(ex[-1]), int(num_output_points), dtype=np.float32) |
| sx_out = np.interp(x_out, ex, sx / 1e6).astype(np.float32) |
| if mode == "11": |
| lateral = np.interp(x_out, ex, ey).astype(np.float32) |
| eps33 = np.interp(x_out, ex, ezz).astype(np.float32) |
| elif mode == "22": |
| lateral = np.interp(x_out, ex, e11).astype(np.float32) |
| eps33 = np.interp(x_out, ex, ezz).astype(np.float32) |
| else: |
| lateral = None |
| eps33 = None |
|
|
| sim_modes[mode] = { |
| "strain": x_out, |
| "stress": sx_out, |
| "lateral": lateral, |
| "eps33": eps33, |
| } |
| except Exception: |
| continue |
| if sim_modes: |
| out[int(inst)] = sim_modes |
|
|
| if not out: |
| raise RuntimeError(f"No simulations succeeded for {mat_type} vf={vf_str} angles={quarter_angles}") |
| return out |
|
|