Files
2025AsianB/org/other/question2_pdms_cooling.py
2025-11-22 18:08:14 +08:00

158 lines
5.2 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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()