import importlib.util import math import os from dataclasses import dataclass from typing import Dict, List, Tuple import numpy as np from matplotlib import pyplot as plt plt.rcParams["font.sans-serif"] = ["DejaVu Sans", "Arial", "Helvetica"] plt.rcParams["axes.unicode_minus"] = False SIGMA = 5.670374419e-8 THICKNESSES = [1, 5, 10, 25, 50, 100] # µm T_AMB = 300.0 # K (≈27 ℃) T_SKY = 280.0 # Clear dry sky equivalent radiation temperature SOLAR_IRR = 900.0 # W/m^2, clear sky noon H_CONV = 8.0 # W/m^2/K, natural convection + light wind def load_emissivity_module(): here = os.path.dirname(os.path.abspath(__file__)) target = os.path.join(here, "question1_pdms_emissivity.py") spec = importlib.util.spec_from_file_location("q1", target) module = importlib.util.module_from_spec(spec) spec.loader.exec_module(module) # type: ignore[arg-type] return module def solar_absorptance(thickness_um: float) -> float: """ Empirical assumption: In PDMS silver-coated system, visible light absorption is determined by thin film scattering and internal losses. At 1 µm, α≈0.05, absorption increases by 0.01 for every 10 µm increase in thickness, capped at 0.15. """ return min(0.05 + 0.001 * thickness_um, 0.15) @dataclass class CoolingResult: thickness_um: float eps_window: float alpha_solar: float net_power_at_amb: float eq_temp_K: float @property def eq_temp_C(self) -> float: return self.eq_temp_K - 273.15 @property def delta_T(self) -> float: return self.eq_temp_K - T_AMB def net_cooling_power(temp_K: float, emissivity: float, alpha_s: float) -> float: radiative = emissivity * SIGMA * (temp_K**4 - T_SKY**4) solar_gain = alpha_s * SOLAR_IRR convective = H_CONV * (temp_K - T_AMB) return -solar_gain - convective + radiative def solve_equilibrium(emissivity: float, alpha_s: float) -> float: low, high = 250.0, 330.0 f_low = net_cooling_power(low, emissivity, alpha_s) f_high = net_cooling_power(high, emissivity, alpha_s) if f_low * f_high > 0: # No sign change, return endpoint with smaller energy consumption return low if abs(f_low) < abs(f_high) else high for _ in range(80): mid = 0.5 * (low + high) f_mid = net_cooling_power(mid, emissivity, alpha_s) if abs(f_mid) < 1e-4: return mid if f_low * f_mid <= 0: high, f_high = mid, f_mid else: low, f_low = mid, f_mid return 0.5 * (low + high) def evaluate() -> Tuple[List[CoolingResult], str]: q1 = load_emissivity_module() emissivity_data = q1.compute_emissivity(THICKNESSES) results: List[CoolingResult] = [] for d in THICKNESSES: eps_window = emissivity_data.window_avg[d] alpha_s = solar_absorptance(d) net_amb = net_cooling_power(T_AMB, eps_window, alpha_s) eq_temp = solve_equilibrium(eps_window, alpha_s) results.append( CoolingResult( thickness_um=d, eps_window=eps_window, alpha_solar=alpha_s, net_power_at_amb=net_amb, eq_temp_K=eq_temp, ) ) outdir = os.path.join(os.path.dirname(__file__), "outputs") os.makedirs(outdir, exist_ok=True) csv_path = os.path.join(outdir, "question2_cooling_summary.csv") with open(csv_path, "w", encoding="utf-8") as f: f.write("thickness_um,eps_8_13,alpha_solar,net_power_amb_Wm2,eq_temp_C,delta_T_C\n") for res in results: f.write( f"{res.thickness_um},{res.eps_window:.4f},{res.alpha_solar:.3f}," f"{res.net_power_at_amb:.2f},{res.eq_temp_C:.2f},{res.delta_T:.2f}\n" ) fig_path = os.path.join(outdir, "question2_cooling_results.png") plot_results(results, fig_path) return results, csv_path def plot_results(results: List[CoolingResult], fig_path: str) -> None: thickness = [r.thickness_um for r in results] net_power = [r.net_power_at_amb for r in results] delta_T = [r.delta_T for r in results] fig, ax1 = plt.subplots(figsize=(9, 5)) ax1.bar(thickness, net_power, width=4, alpha=0.6, label="Net Cooling Power @T_amb") ax1.set_xlabel("PDMS Film Thickness (µm)") ax1.set_ylabel("Net Cooling Power (W/m²)") ax1.axhline(0, color="black", linewidth=0.8) ax2 = ax1.twinx() ax2.plot(thickness, delta_T, color="tab:red", marker="o", label="Equilibrium Temperature Difference") ax2.set_ylabel("Equilibrium Temperature Difference (K)") lines, labels = ax1.get_legend_handles_labels() lines2, labels2 = ax2.get_legend_handles_labels() ax1.legend(lines + lines2, labels + labels2, loc="upper right") fig.tight_layout() plt.savefig(fig_path, dpi=300) plt.close(fig) def main(): results, csv_path = evaluate() print(f"Results written to: {csv_path}") for r in results: print( f"d={r.thickness_um:>3} um, eps_8_13={r.eps_window:.2f}, alpha_sol={r.alpha_solar:.2f}, " f"q_net(T_amb)={r.net_power_at_amb:.1f} W/m2, T_eq={r.eq_temp_C:.1f} °C " f"(DeltaT={r.delta_T:.1f} K)" ) if __name__ == "__main__": main()