Files
MCM/A题/ZJ_v2/fig04_internal_resistance.py
2026-02-16 21:52:26 +08:00

103 lines
3.4 KiB
Python

"""
Fig 4: Internal Resistance 3D Surface
Shows R0(T, z) dependency on temperature and SOC
"""
import os
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
from plot_style import set_oprice_style, save_figure
def compute_internal_resistance(T_b, z, R_ref, E_a, T_ref):
"""
Compute internal resistance with temperature and SOC dependence
R0 = R_ref * exp(E_a/R * (1/T - 1/T_ref)) * (1 + k_z * (1-z))
"""
R_gas = 8.314 # J/(mol·K)
k_z = 0.5 # SOC dependence coefficient
temp_factor = np.exp(E_a / R_gas * (1/T_b - 1/T_ref))
soc_factor = 1 + k_z * (1 - z)
return R_ref * temp_factor * soc_factor
def make_figure(config):
"""Generate Fig 4: Internal Resistance 3D Surface"""
set_oprice_style()
# Get parameters
params = config.get('battery_params', {})
R_ref = params.get('R_ref', 0.1)
E_a = params.get('E_a', 20000)
T_ref = params.get('T_ref', 298.15)
# Create grid
T_celsius = np.linspace(-10, 40, 50)
T_kelvin = T_celsius + 273.15
z_values = np.linspace(0.05, 0.95, 50)
T_grid, z_grid = np.meshgrid(T_kelvin, z_values)
# Compute resistance surface
R0_grid = compute_internal_resistance(T_grid, z_grid, R_ref, E_a, T_ref)
# Create figure
fig = plt.figure(figsize=(12, 9))
ax = fig.add_subplot(111, projection='3d')
# Plot surface
surf = ax.plot_surface(T_celsius, z_grid, R0_grid,
cmap='coolwarm', alpha=0.9,
edgecolor='none', antialiased=True)
# Add contour lines on bottom
ax.contour(T_celsius, z_values, R0_grid,
levels=10, offset=0, cmap='coolwarm', alpha=0.5)
# Labels and title
ax.set_xlabel('Temperature (°C)', fontsize=11, labelpad=10)
ax.set_ylabel('State of Charge (SOC)', fontsize=11, labelpad=10)
ax.set_zlabel('Internal Resistance (Ω)', fontsize=11, labelpad=10)
ax.set_title('Internal Resistance Dependence on Temperature and SOC',
fontsize=12, fontweight='bold', pad=20)
# Set viewing angle
ax.view_init(elev=20, azim=135)
# Colorbar
cbar = fig.colorbar(surf, ax=ax, shrink=0.6, aspect=15, pad=0.1)
cbar.set_label('R₀ (Ω)', fontsize=10)
# Add annotation for key regions
ax.text2D(0.02, 0.95, 'Key Observations:\n' +
'• Low temp → High resistance\n' +
'• Low SOC → High resistance\n' +
'• Coupled effect at extremes',
transform=ax.transAxes, fontsize=9,
verticalalignment='top',
bbox=dict(boxstyle='round', facecolor='wheat', alpha=0.8))
# Save
figure_dir = config.get('global', {}).get('figure_dir', 'figures')
os.makedirs(figure_dir, exist_ok=True)
output_base = os.path.join(figure_dir, 'Fig04_Internal_Resistance')
save_figure(fig, output_base, dpi=config.get('global', {}).get('dpi', 300))
plt.close()
# Compute some statistics
R0_min = float(np.min(R0_grid))
R0_max = float(np.max(R0_grid))
R0_ratio = R0_max / R0_min
return {
"output_files": [f"{output_base}.pdf", f"{output_base}.png"],
"computed_metrics": {
"R0_min_ohm": R0_min,
"R0_max_ohm": R0_max,
"ratio": R0_ratio
},
"validation_flags": {},
"pass": True
}