# Converted from selectivity.m - selectivity in two-CSTR networkimportnumpyasnpfromscipy.integrateimportsolve_ivpfromscipy.optimizeimportfsolvefrommiscimportoctave_saveeps_sq=np.sqrt(np.finfo(float).eps)k1=1.;k2=2.theta1=1.;theta2=2.caf=1.;cbf=1.rhotest=1.;n=2.;alpha=0.1theta=theta1+theta2deftworeac(x,rho):ca1,cb1,ca2,cb2=xr11=k1*ca1*cb1;r21=k2*ca1**nr12=k1*ca2*cb2;r22=k2*ca2**nR=np.array([-(r11+r21)*theta1,-r11*theta1,-(r12+r22)*theta2,-r12*theta2])flow=np.array([alpha*caf-(alpha+rho)*ca1+rho*ca2,-(alpha+rho)*cb1+rho*cb2,-(1.+alpha)*ca2+(alpha+rho)*ca1-rho*ca2,cbf+(alpha+rho)*cb1-rho*cb2-(1.+alpha)*cb2])returnflow+Rdefonereac(x):ca,cb=xr1=k1*ca*cb;r2=k2*ca**nR=np.array([-(r1+r2)*theta,-r1*theta])flow=np.array([alpha*caf-(1.+alpha)*ca,cbf-(1.+alpha)*cb])returnflow+Rnpts=100rho0=0.;rhofin=1.rhovec=np.linspace(rhofin,rho0,npts)y0=np.array([0.,cbf-caf])y,_,info,_=fsolve(onereac,y0,full_output=True)[:4]conv1=(alpha*caf-(1.+alpha)*y[0])/(alpha*caf)*np.ones(npts)yield1=((cbf-(1.+alpha)*y[1])/(alpha*caf-(1.+alpha)*y[0]))*np.ones(npts)conv2=np.zeros(npts)yield2=np.zeros(npts)x0=np.array([0.,cbf-caf,0.,cbf-caf])fori,rhoinenumerate(rhovec):x,_,info,_=fsolve(lambdax:tworeac(x,rho),x0,full_output=True)[:4]ifinfo!=1:print(f'warning: fsolve failed, i={i}')x0=x.copy()conv2[i]=(alpha*caf-(1.+alpha)*x[2])/(alpha*caf)denom=alpha*caf-(1.+alpha)*x[2]yield2[i]=(cbf-(1.+alpha)*x[3])/denomifabs(denom)>0else0.table1=np.column_stack([rhovec,yield1,yield2,conv1,conv2])# step test resultsdefonestep(t,x):return[(alpha-(1.+alpha)*x[0])/(theta1+theta2)]nts=100tfin=10.*thetatimes=np.linspace(0.,tfin,nts)sol=solve_ivp(onestep,[0.,tfin],[0.],method='Radau',t_eval=times,rtol=eps_sq,atol=eps_sq)y_sol=sol.y[0]impy=np.array(onestep(0.,[y_sol]))# not used in tablerho=0.a=np.array([alpha/theta1,0.])B=np.array([[-(alpha+rho)/theta1,rho/theta1],[(alpha+rho)/theta2,-(1.+alpha+rho)/theta2]])deftwostep1(t,x):returna+B@xsol1=solve_ivp(twostep1,[0.,tfin],[0.,0.],method='Radau',t_eval=times,rtol=eps_sq,atol=eps_sq)x1=sol1.y.Trho=1.a=np.array([alpha/theta1,0.])B=np.array([[-(alpha+rho)/theta1,rho/theta1],[(alpha+rho)/theta2,-(1.+alpha+rho)/theta2]])deftwostep2(t,x):returna+B@xsol2=solve_ivp(twostep2,[0.,tfin],[0.,0.],method='Radau',t_eval=times,rtol=eps_sq,atol=eps_sq)x2=sol2.y.T# impulsive response approximation# Octave: diag(a)*ones(2,nts) + B*x' gives (2 x nts); transpose to (nts x 2)rho=0.a0=np.array([alpha/theta1,0.])B0=np.array([[-(alpha+0.)/theta1,0./theta1],[(alpha+0.)/theta2,-(1.+alpha+0.)/theta2]])impx1=(a0[:,None]+B0@x1.T).T# shape (nts, 2)rho=1.a1=np.array([alpha/theta1,0.])B1=np.array([[-(alpha+1.)/theta1,1./theta1],[(alpha+1.)/theta2,-(1.+alpha+1.)/theta2]])impx2=(a1[:,None]+B1@x2.T).T# shape (nts, 2)# Octave: [times y x1(:,2) x2(:,2) impy impx1(:,2) impx2(:,2)]impy_vec=np.array([(alpha-(1.+alpha)*yv)/(theta1+theta2)foryviny_sol])table2=np.column_stack([times,y_sol,x1[:,1],x2[:,1],impy_vec,impx1[:,1],impx2[:,1]])octave_save('selectivity.dat',('table1',table1),('table2',table2))