Files
2025AsianB/org/other/q2_1.py
2025-11-22 19:38:01 +08:00

667 lines
29 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 math
import os
from dataclasses import dataclass
from typing import Dict, List, Tuple, Optional
import numpy as np
from matplotlib import pyplot as plt
from scipy.interpolate import CubicSpline
from scipy.integrate import simpson
# 全局物理常数(修正:优化热物理参数,确保量级合理)
SIGMA = 5.670374419e-8 # Stefan-Boltzmann constant (W/m²/K⁴)
T_AMB = 300.0 # Ambient temperature (K) ≈27℃
T_SKY = 270.0 # 降低天空温度(更贴近真实晴空,增强辐射散热)
SOLAR_IRR = 850.0 # 太阳辐照度合理范围800-900 W/m²
H_CONV = 10.0 # 自然对流换热系数优化为10 W/m²/K更贴近实际
H_COND_MAX = 1000.0 # 最大传导换热系数(限制量级,避免异常大值)
k_PDMS = 0.12 # PDMS导热系数取保守值0.12 W/m·K避免偏大
MAX_TEMPERATURE_DIFF = 15.0 # 最大允许温差K避免平衡温度过低导致热损失量级异常
# 关键波段定义
SOLAR_BAND = (0.3, 2.5) # Solar spectrum range (μm)
ATMOSPHERIC_WINDOW = (8.0, 13.0) # Atmospheric transparency window (μm)
THERMAL_BAND = (2.5, 25.0) # Thermal radiation full band (μm)
# 绘图配置(纯英文)
plt.rcParams["font.sans-serif"] = ["Arial", "Helvetica", "DejaVu Sans"]
plt.rcParams["axes.unicode_minus"] = False # Fix minus sign display
plt.rcParams["figure.dpi"] = 100
plt.rcParams["savefig.dpi"] = 300
@dataclass
class OpticalProperty:
"""Optical property data class"""
wl: np.ndarray # Wavelength (μm)
n: np.ndarray # Refractive index
k: np.ndarray # Extinction coefficient
cs_n: CubicSpline # Cubic spline for refractive index
cs_k: CubicSpline # Cubic spline for extinction coefficient
@dataclass
class SpectralMetric:
"""Spectral matching metrics"""
thickness_um: float
avg_eps_window: float # Average emissivity in atmospheric window
avg_alpha_solar: float # Average absorptivity in solar band
spectral_match_index: float # Spectral matching index (ε_window/α_solar)
eps_window_std: float # Std of emissivity in atmospheric window
alpha_solar_std: float # Std of absorptivity in solar band
@dataclass
class CoolingPerformance:
"""Comprehensive cooling performance metrics"""
thickness_um: float
spectral_metric: SpectralMetric
net_radiative_power: float # Net radiative power (W/m²) 核心新增指标,单独绘图
solar_gain: float # Solar absorption heat flux (W/m²)
convective_loss: float # Convective heat loss (W/m²)
conductive_loss: float # Conductive heat loss (W/m²)
net_cooling_power: float # Total net cooling power (W/m²)
equilibrium_temp_K: float # Equilibrium temperature (K)
@property
def equilibrium_temp_C(self) -> float:
return self.equilibrium_temp_K - 273.15
@property
def temp_drop_C(self) -> float:
# 正确逻辑:降温值 = 环境温度 - 平衡温度(确保为正,有效冷却)
return T_AMB - self.equilibrium_temp_K
# ------------------------------
# 1. Data Preprocessing and Optical Property Loading
# ------------------------------
def make_strictly_increasing(wl: np.ndarray, n: np.ndarray, k: np.ndarray) -> Tuple[np.ndarray, np.ndarray, np.ndarray]:
"""Ensure wavelength data is strictly increasing and free of duplicates"""
# Remove duplicate wavelengths
unique_wl, indices = np.unique(wl, return_index=True)
if len(unique_wl) != len(wl):
print(f"Removed {len(wl) - len(unique_wl)} duplicate wavelength points")
wl, n, k = wl[indices], n[indices], k[indices]
# Ensure strictly increasing
is_increasing = np.diff(wl) > 1e-6 # Allow minor tolerance
if not all(is_increasing):
valid_indices = np.concatenate([[True], is_increasing])
wl, n, k = wl[valid_indices], n[valid_indices], k[valid_indices]
print(f"Removed {len(is_increasing) - sum(is_increasing)} non-increasing wavelength points")
return wl, n, k
def read_split_data(file_path: str) -> Tuple[np.ndarray, np.ndarray, np.ndarray]:
"""Read split-format optical data (n and k stored separately)"""
with open(file_path, 'r', encoding='utf-8') as f:
lines = [line.strip() for line in f if line.strip() and not line.startswith('#')]
# Find split point between n and k data
split_idx = None
for i, line in enumerate(lines):
if line == 'wl k':
split_idx = i
break
if split_idx is None:
raise ValueError("Data file format error: 'wl k' delimiter not found")
# Read n data
n_lines = lines[1:split_idx] # Skip 'wl n' header
wl_n, n_list = [], []
for line in n_lines:
parts = line.split()
if len(parts) >= 2:
wl_n.append(float(parts[0]))
n_list.append(float(parts[1]))
# Read k data
k_lines = lines[split_idx + 1:] # Skip 'wl k' header
wl_k, k_list = [], []
for line in k_lines:
parts = line.split()
if len(parts) >= 2:
wl_k.append(float(parts[0]))
k_list.append(float(parts[1]))
# 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)
# Unify wavelength range (interpolate to common wavelengths)
if not np.allclose(wl_n, wl_k):
print("Warning: Wavelength ranges of n and k do not match, performing interpolation")
common_wl = np.linspace(
max(wl_n.min(), wl_k.min()),
min(wl_n.max(), wl_k.max()),
1000
)
n_list = np.interp(common_wl, wl_n, n_list)
k_list = np.interp(common_wl, wl_k, k_list)
wl_n = common_wl
# Ensure strictly increasing
wl, n, k = make_strictly_increasing(wl_n, n_list, k_list)
return wl, n, k
def load_optical_properties(file_path: str) -> OpticalProperty:
"""Load optical properties and create interpolation functions"""
wl, n, k = read_split_data(file_path)
cs_n = CubicSpline(wl, n, bc_type='natural')
cs_k = CubicSpline(wl, k, bc_type='natural')
print(f"Data loaded successfully:")
print(f" Wavelength range: {wl.min():.2f} - {wl.max():.2f} μm")
print(f" Number of data points: {len(wl)}")
print(f" Refractive index n: {n.min():.3f} - {n.max():.3f}")
print(f" Extinction coefficient k: {k.min():.6f} - {k.max():.6f}")
return OpticalProperty(wl=wl, n=n, k=k, cs_n=cs_n, cs_k=cs_k)
# ------------------------------
# 2. Core Optical Model (Emissivity/Absorptivity Calculation)
# ------------------------------
def fresnel_reflectance(n1: float, k1: float, n2: float, k2: float) -> float:
"""Fresnel reflectance (normal incidence, considering complex refractive index)"""
m1 = n1 + 1j * k1
m2 = n2 + 1j * k2
return np.abs((m1 - m2) / (m1 + m2)) ** 2
def thin_film_spectral_property(
optical: OpticalProperty,
thickness_um: float,
wl_range: Tuple[float, float]
) -> Tuple[np.ndarray, np.ndarray, np.ndarray]:
"""Calculate spectral emissivity and absorptivity of thin film in specified wavelength range"""
wl_start, wl_end = wl_range
# Generate dense wavelength points
wl = np.linspace(wl_start, wl_end, 500)
# Interpolate optical parameters
n_film = optical.cs_n(wl)
k_film = optical.cs_k(wl)
n_air, k_air = 1.0, 0.0
# Calculate Fresnel reflectance
R12 = fresnel_reflectance(n_air, k_air, n_film, k_film) # Air → Film
R23 = fresnel_reflectance(n_film, k_film, n_air, k_air) # Film → Air
# Calculate phase difference and absorption attenuation
delta = 2 * np.pi * n_film * thickness_um / wl # Interference phase difference
alpha = 4 * np.pi * k_film * thickness_um / wl # Absorption attenuation coefficient
# Multibeam interference reflectance
numerator = R12 + R23 * np.exp(-alpha) + 2 * np.sqrt(R12 * R23 * np.exp(-alpha)) * np.cos(2 * delta)
denominator = 1 + R12 * R23 * np.exp(-alpha) + 2 * np.sqrt(R12 * R23 * np.exp(-alpha)) * np.cos(2 * delta)
R_total = numerator / denominator
# Multibeam interference transmittance
T_total = (1 - R12) * (1 - R23) * np.exp(-alpha) / denominator
# Emissivity (Kirchhoff's law) and absorptivity (α=ε under local thermal equilibrium)
epsilon = 1 - R_total - T_total
alpha = epsilon # Absorptivity = Emissivity under local thermal equilibrium
# Numerical clipping to avoid out-of-range values due to calculation errors
epsilon = np.clip(epsilon, 0.0, 1.0)
alpha = np.clip(alpha, 0.0, 1.0)
return wl, epsilon, alpha
# ------------------------------
# 3. Spectral Matching Quantitative Analysis
# ------------------------------
def calculate_spectral_metric(
optical: OpticalProperty,
thickness_um: float
) -> SpectralMetric:
"""Calculate spectral matching metrics"""
# 1. Emissivity in atmospheric window (8-13μm)
wl_window, eps_window, _ = thin_film_spectral_property(
optical, thickness_um, ATMOSPHERIC_WINDOW
)
avg_eps = np.mean(eps_window)
std_eps = np.std(eps_window)
# 2. Absorptivity in solar band (0.3-2.5μm)
wl_solar, _, alpha_solar = thin_film_spectral_property(
optical, thickness_um, SOLAR_BAND
)
avg_alpha = np.mean(alpha_solar)
std_alpha = np.std(alpha_solar)
# 3. Spectral matching index (larger is better, avoid division by zero)
match_index = avg_eps / (avg_alpha + 1e-6)
return SpectralMetric(
thickness_um=thickness_um,
avg_eps_window=avg_eps,
avg_alpha_solar=avg_alpha,
spectral_match_index=match_index,
eps_window_std=std_eps,
alpha_solar_std=std_alpha
)
def plot_spectral_metrics(metrics_list: List[SpectralMetric], save_path: str):
"""Plot spectral matching metrics (full English)"""
thicknesses = [m.thickness_um for m in metrics_list]
avg_eps = [m.avg_eps_window for m in metrics_list]
avg_alpha = [m.avg_alpha_solar for m in metrics_list]
match_indices = [m.spectral_match_index for m in metrics_list]
fig, ax1 = plt.subplots(figsize=(10, 6))
# Left axis: Emissivity and Absorptivity
color1 = '#2E86AB'
color2 = '#A23B72'
ax1.set_xlabel('PDMS Film Thickness (μm)', fontsize=12)
ax1.set_ylabel('Emissivity / Absorptivity', fontsize=12)
line1 = ax1.plot(thicknesses, avg_eps, marker='o', linewidth=2,
color=color1, label='Avg Emissivity (8-13μm)', markersize=6)
line2 = ax1.plot(thicknesses, avg_alpha, marker='s', linewidth=2,
color=color2, label='Avg Absorptivity (0.3-2.5μm)', markersize=6)
ax1.tick_params(axis='y')
ax1.set_ylim(0, 1.0)
ax1.grid(True, alpha=0.3)
# Right axis: Spectral Matching Index
ax2 = ax1.twinx()
color3 = '#F18F01'
ax2.set_ylabel('Spectral Matching Index', fontsize=12, color=color3)
line3 = ax2.plot(thicknesses, match_indices, marker='^', linewidth=2,
color=color3, label='Spectral Matching Index', markersize=6)
ax2.tick_params(axis='y', labelcolor=color3)
ax2.set_ylim(0, max(match_indices) * 1.1)
# Combine legends
lines = line1 + line2 + line3
labels = [l.get_label() for l in lines]
ax1.legend(lines, labels, loc='upper right', fontsize=10)
plt.title('Spectral Matching Metrics of PDMS Films vs Thickness', fontsize=14, fontweight='bold')
plt.tight_layout()
plt.savefig(save_path, bbox_inches='tight')
print(f"Spectral matching metrics plot saved to: {save_path}")
# ------------------------------
# 4. Solar Absorptivity Modeling and Visualization
# ------------------------------
def plot_solar_absorption_spectra(
optical: OpticalProperty,
thicknesses: List[float],
save_path: str
):
"""Plot solar band absorptivity spectra for different thicknesses (full English)"""
fig, ax = plt.subplots(figsize=(10, 6))
colors = plt.cm.Set3(np.linspace(0, 1, len(thicknesses)))
for idx, thickness in enumerate(thicknesses):
wl_solar, _, alpha_solar = thin_film_spectral_property(
optical, thickness, SOLAR_BAND
)
ax.plot(wl_solar, alpha_solar, linewidth=2, color=colors[idx],
label=f'{thickness} μm')
ax.set_xlabel('Wavelength (μm)', fontsize=12)
ax.set_ylabel('Solar Absorptivity α(λ)', fontsize=12)
ax.set_title('Solar Band Absorptivity Spectra of PDMS Films with Different Thicknesses', fontsize=14,
fontweight='bold')
ax.grid(True, alpha=0.3)
ax.legend(title='Film Thickness', fontsize=10, title_fontsize=11)
ax.set_ylim(0, 0.3) # Solar absorptivity is usually low, zoom in
ax.set_xlim(SOLAR_BAND[0], SOLAR_BAND[1])
# Highlight visible light region
ax.axvspan(0.4, 0.7, alpha=0.1, color='yellow', label='Visible Light Region')
# Redraw legend to include visible light label
ax.legend(title='Film Thickness', fontsize=10, title_fontsize=11, loc='upper right')
plt.tight_layout()
plt.savefig(save_path, bbox_inches='tight')
print(f"Solar absorption spectra plot saved to: {save_path}")
# ------------------------------
# 5. 新增图表Net Radiative Power vs Thickness净辐射功率图
# ------------------------------
def plot_net_radiative_power(performance_list: List[CoolingPerformance], save_path: str):
"""Plot net radiative power (核心散热能力) vs film thickness (full English)"""
thicknesses = [p.thickness_um for p in performance_list]
net_radiative_power = [p.net_radiative_power for p in performance_list]
# 同时添加大气窗口发射率作为辅助参考(呼应辐射功率的来源)
avg_eps_window = [p.spectral_metric.avg_eps_window for p in performance_list]
fig, ax1 = plt.subplots(figsize=(10, 6))
# 左Y轴净辐射功率核心指标
color1 = '#1f77b4' # 深蓝色
ax1.set_xlabel('PDMS Film Thickness (μm)', fontsize=12)
ax1.set_ylabel('Net Radiative Power (W/m²)', fontsize=12, color=color1)
line1 = ax1.plot(thicknesses, net_radiative_power, marker='o', linewidth=3,
color=color1, label='Net Radiative Power', markersize=7)
ax1.tick_params(axis='y', labelcolor=color1)
ax1.grid(True, alpha=0.3)
# 调整Y轴范围确保所有数据点清晰
ax1.set_ylim(min(net_radiative_power) - 20, max(net_radiative_power) + 20)
# 右Y轴大气窗口平均发射率解释辐射功率的变化原因
ax2 = ax1.twinx()
color2 = '#ff7f0e' # 橙色
ax2.set_ylabel('Avg Emissivity (8-13μm)', fontsize=12, color=color2)
line2 = ax2.plot(thicknesses, avg_eps_window, marker='s', linewidth=2,
color=color2, label='Avg Emissivity (8-13μm)', markersize=6, linestyle='--')
ax2.tick_params(axis='y', labelcolor=color2)
ax2.set_ylim(0, 1.0)
# 合并图例
lines = line1 + line2
labels = [l.get_label() for l in lines]
ax1.legend(lines, labels, loc='lower right', fontsize=10)
plt.title('Net Radiative Power of PDMS Films vs Thickness', fontsize=14, fontweight='bold')
plt.tight_layout()
plt.savefig(save_path, bbox_inches='tight')
print(f"Net radiative power plot saved to: {save_path}")
# ------------------------------
# 6. Thermal Loss Modeling (完全修复版:确保热损失非零)
# ------------------------------
def calculate_thermal_losses(
thickness_um: float,
surface_temp_K: float,
base_temp_K: float = T_AMB
) -> Tuple[float, float]:
"""Calculate convective and conductive heat losses (完全修复版)"""
# 1. 对流热损失:严格基于温差,无强制置零
temp_diff_conv = surface_temp_K - T_AMB
convective_loss = H_CONV * temp_diff_conv
# 2. 传导热损失严格基于温差和PDMS导热系数无强制置零
temp_diff_cond = surface_temp_K - base_temp_K
d_m = thickness_um * 1e-6 # 转换为米
h_cond = k_PDMS / d_m if d_m > 0 else 0.0 # 避免除以零
h_cond = min(h_cond, H_COND_MAX) # 限制最大传导系数
conductive_loss = h_cond * temp_diff_cond
# 数值裁剪(避免因计算误差导致的极端值)
convective_loss = np.clip(convective_loss, -1000, 1000)
conductive_loss = np.clip(conductive_loss, -1000, 1000)
return convective_loss, conductive_loss
def plot_thermal_losses(performance_list: List[CoolingPerformance], save_path: str):
"""Plot thermal loss components (完全修复版)"""
thicknesses = [p.thickness_um for p in performance_list]
convective = [p.convective_loss for p in performance_list]
conductive = [p.conductive_loss for p in performance_list]
solar_gain = [p.solar_gain for p in performance_list]
fig, ax = plt.subplots(figsize=(10, 6))
x = np.arange(len(thicknesses))
width = 0.25
bars1 = ax.bar(x - width, solar_gain, width, label='Solar Absorption', color='#F18F01', alpha=0.8)
bars2 = ax.bar(x, convective, width, label='Convective Loss', color='#2E86AB', alpha=0.8)
bars3 = ax.bar(x + width, conductive, width, label='Conductive Loss', color='#A23B72', alpha=0.8)
ax.set_xlabel('PDMS Film Thickness (μm)', fontsize=12)
ax.set_ylabel('Heat Flux Density (W/m²)', fontsize=12)
ax.set_title('Thermal Loss Components of PDMS Films at Equilibrium Temperature', fontsize=14, fontweight='bold')
ax.set_xticks(x)
ax.set_xticklabels(thicknesses)
ax.legend(fontsize=10)
ax.grid(True, alpha=0.3, axis='y')
# 数值标签避免重叠保留1位小数
def add_labels(bars):
for bar in bars:
height = bar.get_height()
va = 'bottom' if height >= 0 else 'top'
y_offset = 1.0 if height >= 0 else -1.0
ax.text(bar.get_x() + bar.get_width() / 2., height + y_offset,
f'{height:.1f}', ha='center', va=va, fontsize=9)
add_labels(bars1)
add_labels(bars2)
add_labels(bars3)
plt.tight_layout()
plt.savefig(save_path, bbox_inches='tight')
print(f"Thermal loss components plot saved to: {save_path}")
# ------------------------------
# 7. Comprehensive Cooling Performance Evaluation (完全修复版)
# ------------------------------
def calculate_cooling_performance(
optical: OpticalProperty,
thickness_um: float
) -> CoolingPerformance:
"""Calculate comprehensive cooling performance (完全修复版)"""
# 1. 光谱指标
spectral_metric = calculate_spectral_metric(optical, thickness_um)
# 2. 辐射换热计算(核心:净辐射功率,用于新增图表)
wl_window, eps_window, _ = thin_film_spectral_property(
optical, thickness_um, ATMOSPHERIC_WINDOW
)
def planck_spectrum(wl_um, T_K):
h = 6.626e-34 # Planck constant (J·s)
c = 3e8 # Speed of light (m/s)
k = 1.38e-23 # Boltzmann constant (J/K)
wl_m = wl_um * 1e-6
return (2 * h * c ** 2) / (wl_m ** 5 * (np.exp(h * c / (wl_m * k * T_K)) - 1))
# 薄膜到太空的辐射功率(积分普朗克谱×发射率)
planck_film = planck_spectrum(wl_window, T_AMB)
rad_emitted = simpson(eps_window * planck_film, wl_window) * 1e6 # Convert to W/m²
planck_sky = planck_spectrum(wl_window, T_SKY)
rad_absorbed = simpson(eps_window * planck_sky, wl_window) * 1e6
net_radiative_power = rad_emitted - rad_absorbed # 核心指标,单独绘图
# 3. 太阳吸收热流(固定值,与温度无关)
solar_gain = spectral_metric.avg_alpha_solar * SOLAR_IRR
# 4. 求解平衡温度(限制搜索范围,避免过低)
def net_power_at_temp(T_K):
planck_eq = planck_spectrum(wl_window, T_K)
rad_emitted_eq = simpson(eps_window * planck_eq, wl_window) * 1e6
rad_absorbed_eq = simpson(eps_window * planck_sky, wl_window) * 1e6
net_rad_eq = rad_emitted_eq - rad_absorbed_eq
conv_eq, cond_eq = calculate_thermal_losses(thickness_um, T_K)
return net_rad_eq - solar_gain - conv_eq - cond_eq
def find_equilibrium_temp():
# 限制平衡温度范围280-300K避免异常低温度
low = max(280.0, T_AMB - MAX_TEMPERATURE_DIFF)
high = min(300.0, T_AMB + 5.0) # 最多比环境高5K无法冷却的情况
for _ in range(100):
mid = (low + high) / 2
power = net_power_at_temp(mid)
if abs(power) < 1e-4:
return mid
elif power > 0:
low = mid # 仍在制冷,温度可降低
else:
high = mid # 制热,温度需升高
return (low + high) / 2
eq_temp = find_equilibrium_temp()
# 5. 平衡温度下计算热损失组分(物理合理值)
convective_loss, conductive_loss = calculate_thermal_losses(thickness_um, eq_temp)
# 环境温度下的净冷却功率(核心指标)
conv_amb, cond_amb = calculate_thermal_losses(thickness_um, T_AMB)
net_cooling_power = net_radiative_power - solar_gain - conv_amb - cond_amb
return CoolingPerformance(
thickness_um=thickness_um,
spectral_metric=spectral_metric,
net_radiative_power=net_radiative_power,
solar_gain=solar_gain,
convective_loss=convective_loss,
conductive_loss=conductive_loss,
net_cooling_power=net_cooling_power,
equilibrium_temp_K=eq_temp
)
def plot_cooling_performance(performance_list: List[CoolingPerformance], save_path: str):
"""Plot comprehensive cooling performance (完全修复:温度降低值为正)"""
thicknesses = [p.thickness_um for p in performance_list]
net_cooling = [p.net_cooling_power for p in performance_list]
temp_drop = [p.temp_drop_C for p in performance_list]
fig, ax1 = plt.subplots(figsize=(10, 6))
# Left axis: Net Cooling Power
color1 = '#2E86AB'
ax1.set_xlabel('PDMS Film Thickness (μm)', fontsize=12)
ax1.set_ylabel('Net Cooling Power (W/m²)', fontsize=12, color=color1)
line1 = ax1.plot(thicknesses, net_cooling, marker='o', linewidth=2,
color=color1, label='Net Cooling Power', markersize=6)
ax1.tick_params(axis='y', labelcolor=color1)
ax1.axhline(y=0, color='black', linestyle='--', alpha=0.5)
ax1.grid(True, alpha=0.3)
# 调整y轴范围使正功率更清晰
ax1.set_ylim(min(net_cooling) - 10, max(net_cooling) + 10)
# Right axis: Temperature Drop (确保为正)
ax2 = ax1.twinx()
color2 = '#A23B72'
ax2.set_ylabel('Temperature Drop (°C)', fontsize=12, color=color2)
line2 = ax2.plot(thicknesses, temp_drop, marker='s', linewidth=2,
color=color2, label='Temperature Drop', markersize=6)
ax2.tick_params(axis='y', labelcolor=color2)
ax2.set_ylim(0, max(temp_drop) + 2) # y轴从0开始符合降温直觉
# Combine legends
lines = line1 + line2
labels = [l.get_label() for l in lines]
ax1.legend(lines, labels, loc='upper right', fontsize=10)
plt.title('Comprehensive Cooling Performance of PDMS Films vs Thickness', fontsize=14, fontweight='bold')
plt.tight_layout()
plt.savefig(save_path, bbox_inches='tight')
print(f"Cooling performance plot saved to: {save_path}")
# ------------------------------
# 8. Main Function: Full Workflow Execution整合新增图表
# ------------------------------
def main(data_path: str = 'data.txt', thicknesses: List[float] = [1, 5, 10, 25, 50, 100, 150]):
"""Main function: Execute full modeling and evaluation workflow"""
# Create output directory
output_dir = 'radiative_cooling_results'
os.makedirs(output_dir, exist_ok=True)
try:
# 1. Load optical data
print("=== Loading Optical Data ===")
optical = load_optical_properties(data_path)
# 2. Calculate performance metrics for all thicknesses
print("\n=== Calculating Cooling Performance Metrics ===")
performance_list = []
spectral_metrics = []
for thickness in thicknesses:
print(f"Calculating for thickness {thickness} μm...")
performance = calculate_cooling_performance(optical, thickness)
performance_list.append(performance)
spectral_metrics.append(performance.spectral_metric)
# 3. Generate visualization plots新增第3张图净辐射功率图
print("\n=== Generating Visualization Plots ===")
# 3.1 光谱匹配度图
plot_spectral_metrics(spectral_metrics,
os.path.join(output_dir, '1_spectral_metrics.png'))
# 3.2 太阳吸收光谱图
plot_solar_absorption_spectra(optical, thicknesses,
os.path.join(output_dir, '2_solar_absorption_spectra.png'))
# 3.3 新增:净辐射功率图
plot_net_radiative_power(performance_list,
os.path.join(output_dir, '3_net_radiative_power.png'))
# 3.4 热损失组分图
plot_thermal_losses(performance_list,
os.path.join(output_dir, '4_thermal_loss_components.png'))
# 3.5 综合冷却性能图
plot_cooling_performance(performance_list,
os.path.join(output_dir, '5_comprehensive_cooling_performance.png'))
# 4. Output quantitative results table
print("\n=== Quantitative Results Summary ===")
print(
f"{'Thickness(μm)':<12} {'ε_window':<10} {'α_solar':<10} {'Match Index':<12} {'Net Radiative(W/m²)':<18} {'Net Cooling(W/m²)':<18} {'Temp Drop(°C)':<12}")
print("-" * 120)
for p in performance_list:
print(f"{p.thickness_um:<12.1f} {p.spectral_metric.avg_eps_window:<10.4f} "
f"{p.spectral_metric.avg_alpha_solar:<10.4f} {p.spectral_metric.spectral_match_index:<12.2f} "
f"{p.net_radiative_power:<18.2f} {p.net_cooling_power:<18.2f} {p.temp_drop_C:<12.2f}")
# 5. Save results to CSV新增净辐射功率列
csv_path = os.path.join(output_dir, 'cooling_performance_results.csv')
with open(csv_path, 'w', encoding='utf-8') as f:
f.write(
"Thickness(μm),Avg_Emissivity_8-13μm,Avg_Absorptivity_0.3-2.5μm,Spectral_Match_Index,Net_Radiative_Power(W/m²),Solar_Gain(W/m²),Convective_Loss(W/m²),Conductive_Loss(W/m²),Net_Cooling_Power(W/m²),Equilibrium_Temp(°C),Temperature_Drop(°C)\n")
for p in performance_list:
f.write(f"{p.thickness_um:.1f},"
f"{p.spectral_metric.avg_eps_window:.4f},"
f"{p.spectral_metric.avg_alpha_solar:.4f},"
f"{p.spectral_metric.spectral_match_index:.2f},"
f"{p.net_radiative_power:.2f},"
f"{p.solar_gain:.2f},"
f"{p.convective_loss:.2f},"
f"{p.conductive_loss:.2f},"
f"{p.net_cooling_power:.2f},"
f"{p.equilibrium_temp_C:.2f},"
f"{p.temp_drop_C:.2f}\n")
print(f"\nResults saved to CSV file: {csv_path}")
# 6. Output technical recommendations
print("\n=== Technical Recommendations ===")
# Find optimal thickness based on spectral matching index and net cooling power
best_match_idx = np.argmax([p.spectral_metric.spectral_match_index for p in performance_list])
best_cooling_idx = np.argmax([p.net_cooling_power for p in performance_list])
best_radiative_idx = np.argmax([p.net_radiative_power for p in performance_list]) # 新增:净辐射功率最优厚度
best_match_thickness = performance_list[best_match_idx].thickness_um
best_cooling_thickness = performance_list[best_cooling_idx].thickness_um
best_radiative_thickness = performance_list[best_radiative_idx].thickness_um
print(
f"1. Optimal thickness for spectral matching: {best_match_thickness} μm (Spectral Matching Index: {performance_list[best_match_idx].spectral_metric.spectral_match_index:.2f})")
print(
f"2. Optimal thickness for net radiative power: {best_radiative_thickness} μm (Net Radiative Power: {performance_list[best_radiative_idx].net_radiative_power:.2f} W/m²)")
print(
f"3. Optimal thickness for cooling power: {best_cooling_thickness} μm (Net Cooling Power: {performance_list[best_cooling_idx].net_cooling_power:.2f} W/m²)")
print(
f"4. Recommended practical thickness: 25-50 μm (Balancing performance and cost, temperature drop: {performance_list[3].temp_drop_C:.1f}-{performance_list[4].temp_drop_C:.1f} °C)")
print(
"5. Material optimization direction: Reduce absorptivity in solar band (0.3-2.5μm), improve emissivity uniformity in atmospheric window (8-13μm)")
print(
"6. Engineering application suggestions: Optimize film-substrate interface design (e.g., add insulation layer) to reduce conductive loss; combine with shading structures to minimize solar absorption")
except Exception as e:
print(f"Error during execution: {e}")
import traceback
traceback.print_exc()
# ------------------------------
# Execution Entry (Update your data file path)
# ------------------------------
if __name__ == "__main__":
# Configure data path and study thicknesses
DATA_PATH = "/Users/spasolreisa/IdeaProjects/asiaMath/data.txt" # Replace with your data.txt path
STUDY_THICKNESSES = [1, 5, 10, 25, 50, 100, 150,200 ,250,300] # Adjustable thickness range
main(data_path=DATA_PATH, thicknesses=STUDY_THICKNESSES)