Files
2025AsianB/org/chatgpt2/q2_2.py
2025-11-20 20:27:39 +08:00

321 lines
14 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 numpy as np
import matplotlib.pyplot as plt
from scipy.interpolate import CubicSpline
from scipy.integrate import simpson
import os
# -----------------------------
# Configuration (Update File Path!)
# -----------------------------
DATA_FILE_PATH = "/Users/spasolreisa/IdeaProjects/asiaMath/data.txt" # Replace with your data.txt absolute path
THICKNESSES = [0.5, 1.0, 1.5, 2.0, 2.5, 3.0] # Expand thickness range for evaluation
T_AMBIENT = 300 # Ambient temperature (K)
SOLAR_IRRADIANCE = 1000 # AM1.5 solar irradiance (W/m²)
CONVECTION_COEFF = 10 # Convection coefficient (W/(m²K))
SIGMA = 5.67e-8 # Stefan-Boltzmann constant (W/(m²K⁴))
# -----------------------------
# 1. Fixed Data Parsing Function (Critical Fix for "wl" String Error)
# -----------------------------
def read_split_data(file_path):
"""Read and parse split-format data (wl+n followed by wl+k)"""
if not os.path.exists(file_path):
raise FileNotFoundError(f"File not found: {file_path}")
# Read all lines, skip empty lines and comments
with open(file_path, 'r', encoding='utf-8') as f:
lines = []
for line in f:
stripped = line.strip()
if stripped and not stripped.startswith('#'):
lines.append(stripped)
# Step 1: Identify all headers (lines containing "wl" and either "n" or "k")
header_indices = []
for i, line in enumerate(lines):
parts = line.split()
# Header must be exactly 2 parts: ["wl", "n"] or ["wl", "k"] (case-insensitive)
if len(parts) == 2 and parts[0].lower() == "wl" and parts[1].lower() in ["n", "k"]:
header_indices.append(i)
# Validate: Must have exactly 2 headers (one for n, one for k)
if len(header_indices) != 2:
raise ValueError(
f"Invalid number of headers! Expected 2 (wl+n and wl+k), found {len(header_indices)}.\nCheck data.txt format.")
# Step 2: Split data into n-block and k-block
n_header_idx = header_indices[0]
k_header_idx = header_indices[1]
# Ensure n-header comes before k-header
if n_header_idx > k_header_idx:
n_header_idx, k_header_idx = k_header_idx, n_header_idx
# Extract n data (between n-header and k-header)
n_lines = lines[n_header_idx + 1: k_header_idx]
# Extract k data (after k-header)
k_lines = lines[k_header_idx + 1:]
# Step 3: Parse n data (skip any invalid lines)
wl_n, n_list = [], []
for line in n_lines:
parts = line.split()
# Data line must have exactly 2 numeric parts
if len(parts) != 2:
continue # Skip lines with wrong column count
try:
wl_val = float(parts[0])
n_val = float(parts[1])
wl_n.append(wl_val)
n_list.append(n_val)
except ValueError:
continue # Skip non-numeric lines
# Step 4: Parse k data (skip any invalid lines)
wl_k, k_list = [], []
for line in k_lines:
parts = line.split()
if len(parts) != 2:
continue
try:
wl_val = float(parts[0])
k_val = float(parts[1])
wl_k.append(wl_val)
k_list.append(k_val)
except ValueError:
continue
# Validate: Must have at least 1 data point for n and k
if len(wl_n) == 0:
raise ValueError("No valid n data found! Check the format between wl+n and wl+k headers.")
if len(wl_k) == 0:
raise ValueError("No valid k data found! Check the format after wl+k header.")
# Convert to numpy arrays
wl_n, n_list = np.array(wl_n), np.array(n_list)
wl_k, k_list = np.array(wl_k), np.array(k_list)
# Align wavelengths (if n and k have different wavelength points)
if not np.allclose(wl_n, wl_k, rtol=1e-6):
print("Warning: Wavelengths for n and k do not match. Automatically aligning...")
# Use n's wavelengths as reference, interpolate k to match
k_list = np.interp(wl_n, np.sort(wl_k), k_list[np.argsort(wl_k)])
wl_k = wl_n # Sync k's wavelengths to n's
# Sort by wavelength (ascending) to avoid interpolation errors
sorted_idx = np.argsort(wl_n)
sorted_wl = wl_n[sorted_idx]
sorted_n = n_list[sorted_idx]
sorted_k = k_list[sorted_idx]
print(f"Data loaded successfully: {len(sorted_wl)} valid wavelength points")
print(f"Wavelength range: {sorted_wl.min():.2f}{sorted_wl.max():.2f} μm")
return sorted_wl, sorted_n, sorted_k
# -----------------------------
# 2. Core Functions (Unchanged)
# -----------------------------
def planck_function(wl, T):
"""Planck's law: Blackbody radiation (W/(m³sr))"""
wl_m = wl * 1e-6 # Convert μm to m
c1 = 3.7418e8 # First radiation constant (Wμm⁴/m²)
c2 = 14388 # Second radiation constant (μmK)
return c1 / (wl_m ** 5 * (np.exp(c2 / (wl * T)) - 1))
def solar_spectrum_am15(wl):
"""AM1.5 global solar irradiance (W/(m²μm))"""
spectrum = np.zeros_like(wl)
mask = (wl >= 0.3) & (wl <= 2.5)
wl_masked = wl[mask]
# Empirical fit to AM1.5 data (valid for 0.32.5 μm)
spectrum[mask] = np.where(
wl_masked < 0.5, 800 + 400 * wl_masked,
np.where(wl_masked < 1.0, 1000 - 200 * (wl_masked - 0.5),
np.where(wl_masked < 1.5, 900 - 100 * (wl_masked - 1.0),
750 - 200 * (wl_masked - 1.5)))
)
return spectrum
def fresnel_reflectance(n1, k1, n2, k2):
"""Fresnel reflectance (normal incidence, complex refractive index)"""
m1, m2 = n1 + 1j * k1, n2 + 1j * k2
return np.abs((m1 - m2) / (m1 + m2)) ** 2
def thin_film_optical_properties(n_film, k_film, d, wl):
"""Calculate emissivity (ε), absorptivity (α), transmissivity (T) of thin film"""
R12 = fresnel_reflectance(1.0, 0.0, n_film, k_film) # Air→Film
R23 = fresnel_reflectance(n_film, k_film, 1.0, 0.0) # Film→Air
delta = 2 * np.pi * n_film * d / wl # Phase difference
alpha_abs = 4 * np.pi * k_film * d / wl # Absorption attenuation
# Total reflectance and transmissivity (multiple-beam interference)
R_total = (R12 + R23 * np.exp(-alpha_abs) + 2 * np.sqrt(R12 * R23 * np.exp(-alpha_abs)) * np.cos(2 * delta)) / \
(1 + R12 * R23 * np.exp(-alpha_abs) + 2 * np.sqrt(R12 * R23 * np.exp(-alpha_abs)) * np.cos(2 * delta))
T_total = (1 - R12) * (1 - R23) * np.exp(-alpha_abs) / \
(1 + R12 * R23 * np.exp(-alpha_abs) + 2 * np.sqrt(R12 * R23 * np.exp(-alpha_abs)) * np.cos(2 * delta))
alpha_total = 1 - R_total - T_total # Kirchhoff's law (α=ε for thermal equilibrium)
return alpha_total, R_total, T_total # α=ε for emissivity
# -----------------------------
# 3. Evaluation Model (Unchanged)
# -----------------------------
def evaluate_radiative_cooling(wl_all, n_all, k_all, thickness):
"""Calculate KPIs and comprehensive score for a given PDMS thickness"""
cs_n = CubicSpline(wl_all, n_all)
cs_k = CubicSpline(wl_all, k_all)
# KPI 1: Average Emissivity in 813 μm (weighted by Planck function)
wl_window = np.linspace(8, 13, 500)
# Check if data covers the window (otherwise use nearest values)
if wl_all.min() > 8 or wl_all.max() < 13:
print(f"Warning: Data does not fully cover 813 μm window. Extrapolating...")
n_window = cs_n(wl_window, extrapolate=True)
k_window = cs_k(wl_window, extrapolate=True)
else:
n_window = cs_n(wl_window)
k_window = cs_k(wl_window)
eps_window, _, _ = thin_film_optical_properties(n_window, k_window, thickness, wl_window)
planck = planck_function(wl_window, T_AMBIENT)
eps_avg = simpson(eps_window * planck, wl_window) / simpson(planck, wl_window)
# KPI 2: Average Solar Absorptivity in 0.32.5 μm (weighted by AM1.5)
wl_solar = np.linspace(0.3, 2.5, 500)
if wl_all.min() > 2.5 or wl_all.max() < 0.3:
print(f"Warning: Data does not cover solar spectrum (0.32.5 μm). Using default PDMS properties...")
n_solar = np.ones_like(wl_solar) * 1.4 # Typical PDMS n in solar range
k_solar = np.ones_like(wl_solar) * 1e-6 # Typical PDMS k in solar range
else:
n_solar = cs_n(wl_solar, extrapolate=True)
k_solar = cs_k(wl_solar, extrapolate=True)
alpha_solar, _, _ = thin_film_optical_properties(n_solar, k_solar, thickness, wl_solar)
solar_irr = solar_spectrum_am15(wl_solar)
alpha_avg = simpson(alpha_solar * solar_irr, wl_solar) / simpson(solar_irr, wl_solar)
# KPI 3: Maximum Cooling Temperature (ΔT_max)
def heat_flux(T_film):
planck_film = planck_function(wl_window, T_film)
eps_eff = simpson(eps_window * planck_film, wl_window) / simpson(planck_film, wl_window)
return SIGMA * eps_eff * T_film ** 4 - alpha_avg * SOLAR_IRRADIANCE - CONVECTION_COEFF * (T_film - T_AMBIENT)
# Newton-Raphson iteration (stable convergence)
T_film = T_AMBIENT - 10 # Initial guess
for _ in range(50):
q = heat_flux(T_film)
if abs(q) < 1e-3:
break
# Numerical derivative (more stable than analytical)
dq_dT = (heat_flux(T_film + 1e-4) - heat_flux(T_film - 1e-4)) / (2e-4)
T_film -= q / dq_dT
# Prevent unrealistic temperatures
if T_film < 200 or T_film > T_AMBIENT:
T_film = max(200, min(T_AMBIENT - 5, T_film))
delta_T = T_AMBIENT - T_film
# KPI 4: Cooling Efficiency Ratio (η_CR)
eta_cr = eps_avg / (alpha_avg + 0.01) # +0.01 to avoid division by zero
# Comprehensive Score (0100)
score = 0.0
score += 40 * min(eps_avg, 1.0) # Cap at 1.0 (ideal emissivity)
score += 35 * (1 - min(alpha_avg, 1.0)) # Lower absorption = higher score
score += 15 * min(delta_T / 40, 1.0) # ΔT theoretical upper limit = 40K
score += 10 * min(eta_cr / 100, 1.0) # Cap at 100 (ideal ratio)
return {
"thickness": thickness,
"eps_8-13": eps_avg,
"alpha_0.3-2.5": alpha_avg,
"delta_T_max": delta_T,
"eta_cr": eta_cr,
"comprehensive_score": score
}
# -----------------------------
# 4. Main Execution (Unchanged)
# -----------------------------
if __name__ == "__main__":
try:
# Read data (fixed parsing logic)
wl_all, n_all, k_all = read_split_data(DATA_FILE_PATH)
print("\n" + "-" * 50 + "\n")
# Evaluate each thickness
results = []
for d in THICKNESSES:
res = evaluate_radiative_cooling(wl_all, n_all, k_all, d)
results.append(res)
print(f"Thickness: {d} μm")
print(f" - Avg Emissivity (813 μm): {res['eps_8-13']:.4f}")
print(f" - Avg Solar Absorptivity (0.32.5 μm): {res['alpha_0.3-2.5']:.4f}")
print(f" - Max Cooling Temperature: {res['delta_T_max']:.2f} K")
print(f" - Cooling Efficiency Ratio: {res['eta_cr']:.2f}")
print(f" - Comprehensive Score: {res['comprehensive_score']:.1f}/100\n")
# Convert results to numpy array for plotting
results_arr = np.array([[
res["thickness"], res["eps_8-13"], res["alpha_0.3-2.5"],
res["delta_T_max"], res["comprehensive_score"]
] for res in results])
# Plot KPIs vs Thickness
fig, axes = plt.subplots(2, 2, figsize=(14, 10))
fig.suptitle("PDMS Thin Film Radiative Cooling Performance vs Thickness", fontsize=16, fontweight='bold')
# Emissivity (813 μm)
axes[0, 0].plot(results_arr[:, 0], results_arr[:, 1], 'o-', color='darkred', linewidth=2, markersize=6)
axes[0, 0].set_xlabel("Thickness (μm)", fontsize=12), axes[0, 0].set_ylabel("Avg Emissivity (813 μm)",
fontsize=12)
axes[0, 0].grid(True, alpha=0.3), axes[0, 0].set_ylim(0, 1.05)
# Solar Absorptivity (0.32.5 μm)
axes[0, 1].plot(results_arr[:, 0], results_arr[:, 2], 's-', color='darkblue', linewidth=2, markersize=6)
axes[0, 1].set_xlabel("Thickness (μm)", fontsize=12), axes[0, 1].set_ylabel(
"Avg Solar Absorptivity (0.32.5 μm)", fontsize=12)
axes[0, 1].grid(True, alpha=0.3), axes[0, 1].set_ylim(0, 0.5)
# Max Cooling Temperature
axes[1, 0].plot(results_arr[:, 0], results_arr[:, 3], '^-', color='darkgreen', linewidth=2, markersize=6)
axes[1, 0].set_xlabel("Thickness (μm)", fontsize=12), axes[1, 0].set_ylabel("Max Cooling Temperature (K)",
fontsize=12)
axes[1, 0].grid(True, alpha=0.3)
# Comprehensive Score
axes[1, 1].plot(results_arr[:, 0], results_arr[:, 4], 'd-', color='darkorange', linewidth=2, markersize=6)
axes[1, 1].set_xlabel("Thickness (μm)", fontsize=12), axes[1, 1].set_ylabel("Comprehensive Score (0100)",
fontsize=12)
axes[1, 1].grid(True, alpha=0.3), axes[1, 1].set_ylim(0, 100)
plt.tight_layout()
plt.savefig("PDMS_radiative_cooling_evaluation.png", dpi=300, bbox_inches='tight')
plt.show()
# Highlight optimal thickness
optimal = max(results, key=lambda x: x["comprehensive_score"])
print("=" * 50)
print(f"Optimal PDMS Thickness: {optimal['thickness']} μm")
print(f"Best Comprehensive Score: {optimal['comprehensive_score']:.1f}/100")
print(
f"Key Performance: ε(8-13μm)={optimal['eps_8-13']:.4f}, α(0.3-2.5μm)={optimal['alpha_0.3-2.5']:.4f}, ΔT={optimal['delta_T_max']:.2f}K")
print("=" * 50)
except Exception as e:
print(f"\nError: {e}")
print("\nTroubleshooting Steps:")
print("1. Check data.txt format: Ensure it has exactly two headers (e.g., 'wl n' and 'wl k')")
print("2. Example valid format:")
print(" wl n")
print(" 0.40 1.41491")
print(" 0.41 1.41403")
print(" ...")
print(" wl k")
print(" 0.40 1.40E-06")
print(" 0.41 1.38E-06")
print("3. Ensure no extra 'wl' strings in data lines (only numbers)")
print("4. Use space or tab as separator (avoid commas)")