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

81 lines
3.1 KiB
Python
Raw Permalink 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.
"""
Fig 6: CPL Avalanche Loop Diagram
Shows the positive feedback mechanism in CPL discharge
"""
import os
from graphviz import Digraph
def make_figure(config):
"""Generate Fig 6: CPL Avalanche Loop"""
dot = Digraph(comment='CPL Avalanche Loop')
dot.attr(rankdir='LR', size='10,6')
dot.attr('node', fontname='Times New Roman', fontsize='11', style='filled')
dot.attr('edge', fontname='Times New Roman', fontsize='10')
# Main feedback loop nodes
dot.node('V', 'Terminal Voltage\nDecreases\n(V_term ↓)',
shape='box', fillcolor='#ffcccc', width='2')
dot.node('I', 'Current\nIncreases\n(I ↑)',
shape='box', fillcolor='#ffffcc', width='2')
dot.node('Loss', 'Joule Loss\nIncreases\n(I²R₀ ↑)',
shape='box', fillcolor='#ffddaa', width='2')
dot.node('Heat', 'Temperature\nRises\n(T_b ↑)',
shape='box', fillcolor='#ffaa99', width='2')
dot.node('R', 'Resistance\nIncreases\n(R₀ ↑)',
shape='box', fillcolor='#ff9999', width='2')
# CPL constraint node
dot.node('CPL', 'CPL Constraint\nP = I × V_term\n(constant)',
shape='ellipse', fillcolor='lightblue', width='2.5', height='1.2')
# SOC depletion
dot.node('SOC', 'SOC Depletes\n(z ↓)',
shape='box', fillcolor='#ccccff', width='2')
# Main feedback edges
dot.edge('V', 'I', label='CPL:\nP=constant', color='red', penwidth='2')
dot.edge('I', 'Loss', label='Quadratic', color='darkred', penwidth='2')
dot.edge('Loss', 'Heat', label='Thermal', color='orange', penwidth='1.5')
dot.edge('Heat', 'R', label='Arrhenius', color='orange', penwidth='1.5')
dot.edge('R', 'V', label='V_term = V_oc - IR₀', color='red', penwidth='2')
# SOC impact
dot.edge('I', 'SOC', label='Discharge\nrate', color='blue', penwidth='1.5')
dot.edge('SOC', 'V', label='V_oc(z)', color='blue', penwidth='1.5')
dot.edge('SOC', 'R', label='R₀(z)', color='blue', penwidth='1.5', style='dashed')
# CPL connection
dot.edge('CPL', 'I', style='dashed', color='gray')
dot.edge('V', 'CPL', style='dashed', color='gray')
# Add legend
with dot.subgraph(name='cluster_legend') as c:
c.attr(label='Loop Characteristics', style='dashed', fontsize='10')
c.node('L1', '• Positive Feedback (Runaway)\n' +
'• Accelerates near end of discharge\n' +
'• Non-linear TTE relationship\n' +
'• Temperature coupling critical',
shape='note', fillcolor='lightyellow', fontsize='9')
# Output directory
figure_dir = config.get('global', {}).get('figure_dir', 'figures')
os.makedirs(figure_dir, exist_ok=True)
# Render
output_base = os.path.join(figure_dir, 'Fig06_CPL_Avalanche')
dot.render(output_base, format='pdf', cleanup=True)
dot.render(output_base, format='png', cleanup=True)
return {
"output_files": [f"{output_base}.pdf", f"{output_base}.png"],
"computed_metrics": {},
"validation_flags": {},
"pass": True
}