codex/sun-valve-thermal-lag-and-switching.py

sun-valve-thermal-lag-and-switching.py
"""Chosen matched-rod thermal model, no historical data; PNG to CWD."""
from pathlib import Path
import matplotlib
matplotlib.use('Agg')
import matplotlib.pyplot as plt
import numpy as np


def main():
    plt.rcParams.update({'font.size':12,'font.family':'DejaVu Sans'})
    length,alpha,area,ab,ar,capacity,conductance,irradiance=.2,20e-6,.002,.9,.1,5.,.2,600.
    tau=capacity/conductance
    steady=alpha*length*area*(ab-ar)*irradiance/conductance
    threshold=10e-6; stop=180.
    close=-tau*np.log1p(-threshold/steady)
    at_stop=steady*(-np.expm1(-stop/tau))
    reopen=stop+tau*np.log(at_stop/threshold)
    t=np.linspace(0,300,2001)
    displacement=np.where(t<=stop,steady*(-np.expm1(-t/tau)),at_stop*np.exp(-(t-stop)/tau))
    permission=(displacement<threshold).astype(float)
    fig,(ax,bx)=plt.subplots(2,1,figsize=(13,6.5),dpi=120,sharex=True,facecolor='white',gridspec_kw={'height_ratios':[2.2,1]})
    fig.subplots_adjust(left=.085,right=.98,bottom=.18,top=.87,hspace=.27)
    for panel in [ax,bx]:
        panel.axvspan(0,stop,color='#f5e4ab',alpha=.5)
        panel.grid(alpha=.2)
    ax.plot(t,displacement*1e6,color='#246898',linewidth=2.5,label='Relative rod extension')
    ax.axhline(threshold*1e6,color='#a44737',linestyle='--',label='Chosen 10 µm switching threshold')
    ax.set(ylabel='Relative extension (µm)',ylim=(0,22),xlim=(0,300))
    ax.legend(loc='lower right',fontsize=11)
    ax.text(90,20.5,'Illuminated',ha='center',fontsize=12)
    ax.text(240,20.5,'Dark',ha='center',fontsize=12)
    bx.step(t,permission,where='post',color='#397c50',linewidth=2.5)
    bx.set(yticks=[0,1],yticklabels=['Closed','Open'],ylim=(-.2,1.25),xlabel='Time (s)',ylabel='Main supply\npermission')
    for when,label in [(close,f'Closes at {close:.1f} s'),(reopen,f'Reopens at {reopen:.1f} s')]:
        ax.axvline(when,color='#777',linestyle=':',linewidth=1)
        bx.axvline(when,color='#777',linestyle=':',linewidth=1)
        bx.annotate(label,xy=(when,.5),xytext=(when+12,.8),fontsize=11,arrowprops={'arrowstyle':'->','color':'#555'})
    fig.suptitle('Differential heating gives a delayed mechanical switching signal',fontsize=17,y=.97)
    fig.text(.5,.07,'Chosen illumination: 600 W/m² for 180 s; matched thermal time constant: 25 s; steady extension: 19.2 µm.',ha='center',fontsize=11)
    fig.text(.5,.025,'Model calculation, not historical measurements. The lower trace gives permission, not a measured gas-flow rate.',ha='center',fontsize=11)
    fig.savefig(Path.cwd()/(Path(__file__).stem+'.png'),facecolor='white')
    plt.close(fig)


if __name__=='__main__':
    main()