Source code for PDSim.scroll.plots
from __future__ import print_function
fig_size = [8,10]
import math
import numpy as np
import pylab
from pylab import arange,pi,sin,cos,sqrt,tan
import threading
import wx
import os
#import scrollCalcs as Calcs
from matplotlib.figure import Figure
from matplotlib.backends.backend_wxagg import FigureCanvasWxAgg as FigureCanvas
global geo,setDiscGeo,coords_inv,circle,sortAnglesCCW,Shave,plotScrollSet
global polyarea,theta_d
import matplotlib.pyplot as pyplot
from PDSim.scroll import common_scroll_geo
from PDSim.scroll.common_scroll_geo import coords_inv, coords_norm
[docs]
class geoVals:
"""
A class which contains the fields related the
scroll compressor geometry
"""
# Default values for Sanden Compressor #
## DO NOT MODIFY THESE VALUES ##
rb=0.003522
phi_i0=0.19829
phi_is=4.7
phi_ie=15.5
phi_o0=-1.1248
phi_os=1.8
phi_oe=15.5
h=0.03289
disc_x0=-0.007
disc_y0=-0.0011
disc_R=0.0060198
def __init__(self, **kwargs):
self.Load()
[docs]
def Load(self):
# Default values for Sanden Compressor #
## DO NOT MODIFY THESE VALUES ##
self.rb=0.003522
self.phi_i0=0.19829
self.phi_is=4.7
self.phi_ie=15.5
self.phi_o0=-1.1248
self.phi_os=1.8
self.phi_oe=15.5
self.h=0.03289
# disc_x0=-0.007
# disc_y0=-0.0011
# disc_R=0.0060198
self.ro=self.rb*(pi-self.phi_i0+self.phi_o0)
#Load a default discharge geometry
setDiscGeo(self)
[docs]
def LoadGeo():
"""
Returns a class containing the default parameters for the scroll compressor
======= =========
r_b 0.003522
phi_i0 0.19829
phi_is 4.7
phi_ie 15.5
phi_o0 -1.1248
phi_os 1.8
phi_oe 15.5
h 0.03289
disc_x0 -0.007
disc_y0 -0.0011
disc_R 0.0060198
======= =========
"""
return geoVals()
[docs]
def setDiscGeo(geo,Type='Sanden',r2=0.001,**kwargs):
"""
Sets the discharge geometry for the compressor based on the arguments.
Also sets the radius of the wall that contains the scroll set
Arguments:
geo : geoVals class
class containing the scroll compressor geometry
Type : string
Type of discharge geometry, options are ['Sanden'],'2Arc','ArcLineArc'
r2 : float or string
Either the radius of the smaller arc as a float or 'PMP' for perfect meshing
If Type is 'Sanden', this value is ignored
Keyword Arguments:
======== ======================================================================
Value Description
======== ======================================================================
r1 the radius of the large arc for the arc-line-arc solution type
======== ======================================================================
"""
#Recalculate the orbiting radius
geo.ro=geo.rb*(pi-geo.phi_i0+geo.phi_o0)
if Type == 'Sanden':
geo.x0_wall=0.0
geo.y0_wall=0.0
geo.r_wall=0.065
setDiscGeo(geo,Type='ArcLineArc',r2=0.003178893902,r1=0.008796248080)
elif Type == '2Arc':
(x_is,y_is) = common_scroll_geo.coords_inv(geo.phi_is,geo,0,'fi')
(x_os,y_os) = common_scroll_geo.coords_inv(geo.phi_os,geo,0,'fo')
(nx_is,ny_is) = common_scroll_geo.coords_norm(geo.phi_is,geo,0,'fi')
(nx_os,ny_os) = common_scroll_geo.coords_norm(geo.phi_os,geo,0,'fo')
dx=x_is-x_os
dy=y_is-y_os
r2max=0
a=cos(geo.phi_os-geo.phi_is)+1.0
b=geo.ro*a-dx*(sin(geo.phi_os)-sin(geo.phi_is))+dy*(cos(geo.phi_os)-cos(geo.phi_is))
c=1.0/2.0*(2.0*dx*sin(geo.phi_is)*geo.ro-2.0*dy*cos(geo.phi_is)*geo.ro-dy**2-dx**2)
if abs((geo.phi_os+pi)-geo.phi_is) < 1e-8:
r2max=-c/b
elif geo.phi_os-(geo.phi_is-pi)>1e-12:
r2max=(-b+sqrt(b**2-4.0*a*c))/(2.0*a)
else:
print('error with starting angles phi_os %.16f phi_is-pi %.16f' %(geo.phi_os,geo.phi_is-pi))
if type(r2) is not float and r2=='PMP':
r2=r2max
if r2>r2max:
print('r2 is too large, max value is : %0.5f' %(r2max))
xarc2 = x_os+nx_os*r2
yarc2 = y_os+ny_os*r2
r1=((1.0/2*dy**2+1.0/2*dx**2+r2*dx*sin(geo.phi_os)-r2*dy*cos(geo.phi_os))
/(r2*cos(geo.phi_os-geo.phi_is)+dx*sin(geo.phi_is)-dy*cos(geo.phi_is)+r2))
## Negative sign since you want the outward pointing unit normal vector
xarc1 = x_is-nx_is*r1
yarc1 = y_is-ny_is*r1
geo.xa_arc2=xarc2
geo.ya_arc2=yarc2
geo.ra_arc2=r2
geo.t1_arc2=math.atan2(yarc1-yarc2,xarc1-xarc2)
geo.t2_arc2=math.atan2(y_os-yarc2,x_os-xarc2)
while geo.t2_arc2<geo.t1_arc2:
geo.t2_arc2=geo.t2_arc2+2.0*pi;
geo.xa_arc1=xarc1
geo.ya_arc1=yarc1
geo.ra_arc1=r1
geo.t2_arc1=math.atan2(y_is-yarc1,x_is-xarc1)
geo.t1_arc1=math.atan2(yarc2-yarc1,xarc2-xarc1)
while geo.t2_arc1<geo.t1_arc1:
geo.t2_arc1=geo.t2_arc1+2.0*pi;
"""
line given by y=m*t+b with one element at the intersection
point
with b=0, m=y/t
"""
geo.b_line=0.0
geo.t1_line=xarc2+r2*cos(geo.t1_arc2)
geo.t2_line=geo.t1_line
geo.m_line=(yarc2+r2*sin(geo.t1_arc2))/geo.t1_line
"""
Fit the wall to the chamber
"""
geo.x0_wall=geo.ro/2.0*cos(geo.phi_ie-pi/2-pi)
geo.y0_wall=geo.ro/2.0*sin(geo.phi_ie-pi/2-pi)
(x,y)=common_scroll_geo.coords_inv(geo.phi_ie,geo,pi,'fo')
geo.r_wall=1.03*sqrt((geo.x0_wall-x)**2+(geo.y0_wall-y)**2)
elif Type=='ArcLineArc':
(x_is,y_is) = common_scroll_geo.coords_inv(geo.phi_is,geo,0,'fi')
(x_os,y_os) = common_scroll_geo.coords_inv(geo.phi_os,geo,0,'fo')
(nx_is,ny_is) = common_scroll_geo.coords_norm(geo.phi_is,geo,0,'fi')
(nx_os,ny_os) = common_scroll_geo.coords_norm(geo.phi_os,geo,0,'fo')
dx=x_is-x_os
dy=y_is-y_os
r2max=0
a=cos(geo.phi_os-geo.phi_is)+1.0
b=geo.ro*a-dx*(sin(geo.phi_os)-sin(geo.phi_is))+dy*(cos(geo.phi_os)-cos(geo.phi_is))
c=1.0/2.0*(2.0*dx*sin(geo.phi_is)*geo.ro-2.0*dy*cos(geo.phi_is)*geo.ro-dy**2-dx**2)
if geo.phi_os-(geo.phi_is-pi)>1e-12:
r2max=(-b+sqrt(b**2-4.0*a*c))/(2.0*a)
elif geo.phi_os-(geo.phi_is-pi)<1e-12:
r2max=-c/b
else:
print('error with starting angles phi_os %.16f phi_is-pi %.16f' %(geo.phi_os,geo.phi_is-pi))
if type(r2) is not float and r2=='PMP':
r2=r2max
if r2>r2max:
print('r2 is too large, max value is : %0.5f' %(r2max))
xarc2 = x_os+nx_os*r2
yarc2 = y_os+ny_os*r2
if 'r1' not in kwargs:
r1=r2+geo.ro
else:
r1=kwargs['r1']
## Negative sign since you want the outward pointing unit normal vector
xarc1 = x_is-nx_is*r1
yarc1 = y_is-ny_is*r1
geo.xa_arc2=xarc2
geo.ya_arc2=yarc2
geo.ra_arc2=r2
geo.t2_arc2=math.atan2(y_os-yarc2,x_os-xarc2)
geo.xa_arc1=xarc1
geo.ya_arc1=yarc1
geo.ra_arc1=r1
geo.t2_arc1=math.atan2(y_is-yarc1,x_is-xarc1)
alpha=math.atan2(yarc2-yarc1,xarc2-xarc1)
d=sqrt((yarc2-yarc1)**2+(xarc2-xarc1)**2)
beta=math.acos((r1+r2)/d)
L=sqrt(d**2-(r1+r2)**2)
t1=alpha+beta
(xint,yint)=(xarc1+r1*cos(t1)+L*sin(t1),yarc1+r1*sin(t1)-L*cos(t1))
t2=math.atan2(yint-yarc2,xint-xarc2)
geo.t1_arc1=t1
# (geo.t1_arc1,geo.t2_arc1)=sortAnglesCW(geo.t1_arc1,geo.t2_arc1)
geo.t1_arc2=t2
# (geo.t1_arc2,geo.t2_arc2)=sortAnglesCCW(geo.t1_arc2,geo.t2_arc2)
while geo.t2_arc2<geo.t1_arc2:
geo.t2_arc2=geo.t2_arc2+2.0*pi;
while geo.t2_arc1<geo.t1_arc1:
geo.t2_arc1=geo.t2_arc1+2.0*pi;
"""
line given by y=m*t+b with one element at the intersection
point
with b=0, m=y/t
"""
geo.m_line=-1/tan(t1)
geo.t1_line=xarc1+r1*cos(geo.t1_arc1)
geo.t2_line=xarc2+r2*cos(geo.t1_arc2)
geo.b_line=yarc1+r1*sin(t1)-geo.m_line*geo.t1_line
"""
Fit the wall to the chamber
"""
geo.x0_wall=geo.ro/2.0*cos(geo.phi_ie-pi/2-pi)
geo.y0_wall=geo.ro/2.0*sin(geo.phi_ie-pi/2-pi)
(x,y)=common_scroll_geo.coords_inv(geo.phi_ie,geo,pi,'fo')
geo.r_wall=1.03*sqrt((geo.x0_wall-x)**2+(geo.y0_wall-y)**2)
# f=pylab.Figure
# pylab.plot(x_os,y_os,'o')
# x=geo.xa_arc1+geo.ra_arc1*cos(np.linspace(geo.t1_arc1,geo.t2_arc1,100))
# y=geo.ya_arc1+geo.ra_arc1*sin(np.linspace(geo.t1_arc1,geo.t2_arc1,100))
# pylab.plot(x,y)
# x=geo.xa_arc2+geo.ra_arc2*cos(np.linspace(geo.t1_arc2,geo.t2_arc2,100))
# y=geo.ya_arc2+geo.ra_arc2*sin(np.linspace(geo.t1_arc2,geo.t2_arc2,100))
# pylab.plot(x,y)
# x=np.linspace(geo.t1_line,geo.t2_line,100)
# y=geo.m_line*x+geo.b_line
# pylab.plot(x,y)
# pylab.plot(xint,yint,'^')
# pylab.show()
else:
print('Type not understood:',Type)
[docs]
def circle(xo,yo,r,N=100):
x=np.zeros(N)
y=np.zeros(N)
t=np.linspace(0,2*pi,N)
for i in arange(N):
x[i]=xo+r*cos(t[i])
y[i]=yo+r*sin(t[i])
return (x,y)
[docs]
def CMMarker(x,y,r,lw=1,fill='k',fill2='w',zorder=4):
N=25
(xc,yc)=circle(x,y,r,4*N+1)
pylab.gca().fill(xc,yc,'w',lw=lw,zorder=zorder)
pylab.gca().fill(np.r_[x,xc[N:2*N+1]],np.r_[y,yc[N:2*N+1]],fill2,zorder=zorder)
pylab.gca().fill(np.r_[x,xc[3*N:4*N+1]],np.r_[y,yc[3*N:4*N+1]],fill2,zorder=zorder)
pylab.gca().fill(np.r_[x,xc[0:N+1]],np.r_[y,yc[0:N+1]],fill,zorder=zorder)
pylab.gca().fill(np.r_[x,xc[2*N:3*N+1]],np.r_[y,yc[2*N:3*N+1]],fill,zorder=zorder)
[docs]
def Shave(geo,theta,shaveDelta):
from PDSim.scroll import scroll_geo
phi=np.linspace(geo.phi_ooe-shaveDelta,geo.phi_ooe,200)
(xo,yo)=scroll_geo.coords_inv(phi,geo,theta,"oo")
(xi,yi)=scroll_geo.coords_inv(phi,geo,theta,"oi")
z=(1-0.8*(phi-(geo.phi_ooe-shaveDelta))/(shaveDelta))
xnew=z*xo+(1-z)*xi
ynew=z*yo+(1-z)*yi
return (xnew,ynew)
[docs]
def OverlayCVLabels(theta,**kwargs):
fs=0
if 'fs' in kwargs:
fs=kwargs['fs']
else:
fs=12
if 'CVList' in kwargs:
CVList=kwargs['CVList']
else:
CVList=['s1','s2','c1','c2','d1','d2']
if 'CVNames' in kwargs:
CVNames=kwargs['CVNames']
axis=kwargs['axis']
geo=LoadGeo()
if 's1' in CVList:
if not 'CVNames' in kwargs:
label='$s_1$'
else:
label=CVNames[CVList.index('s1')]
phi=np.linspace(geo.phi_ie,geo.phi_ie-theta,100)
(x_fi,y_fi)=coords_inv(phi,geo,theta,flag="fi")
phi=np.linspace(geo.phi_oe-pi,geo.phi_ie-pi-theta,100)
(x_oo,y_oo)=coords_inv(phi,geo,theta,flag="oo")
x=np.r_[x_fi,x_oo[::-1],(x_fi[0]+x_oo[0])/2.0]
y=np.r_[y_fi,y_oo[::-1],(y_fi[0]+y_oo[0])/2.0]
(xc,yc)=MaxIncircle(x,y,100)
axis.text(xc,yc,label,ha='center',va='center',size=fs)
if 's2' in CVList:
if not 'CVNames' in kwargs:
label='$s_2$'
else:
label=CVNames[CVList.index('s2')]
phi=np.linspace(geo.phi_ie,geo.phi_ie-theta,100)
(x_fi,y_fi)=coords_inv(phi,geo,theta,flag="oi")
phi=np.linspace(geo.phi_oe-pi,geo.phi_ie-pi-theta,100)
(x_oo,y_oo)=coords_inv(phi,geo,theta,flag="fo")
x=np.r_[x_fi,x_oo[::-1],(x_fi[0]+x_oo[0])/2.0]
y=np.r_[y_fi,y_oo[::-1],(y_fi[0]+y_oo[0])/2.0]
(xc,yc)=MaxIncircle(x,y,100)
axis.text(xc,yc,label,ha='center',va='center',size=fs)
if theta<theta_d():
if 'c2' in CVList:
if not 'CVNames' in kwargs:
label='$c_2$'
else:
label=CVNames[CVList.index('c2')]
phi=np.linspace(geo.phi_oe-(theta),geo.phi_oe-theta-2*pi,100)
(x_oi,y_oi)=coords_inv(phi,geo,theta,flag="oi")
phi=np.linspace(geo.phi_oe-(theta)-pi,geo.phi_oe-pi-theta-2*pi,100)
(x_fo,y_fo)=coords_inv(phi,geo,theta,flag="fo")
x=np.r_[x_oi,x_fo[::-1]]
y=np.r_[y_oi,y_fo[::-1]]
(xc,yc)=MaxIncircle(x,y,100)
axis.text(xc,yc,label,ha='center',va='center',size=fs)
if 'c1' in CVList:
if not 'CVNames' in kwargs:
label='$c_1$'
else:
label=CVNames[CVList.index('c1')]
phi=np.linspace(geo.phi_oe-(theta),geo.phi_oe-theta-2*pi,100)
(x_oi,y_oi)=coords_inv(phi,geo,theta,flag="fi")
phi=np.linspace(geo.phi_oe-(theta)-pi,geo.phi_oe-pi-theta-2*pi,100)
(x_fo,y_fo)=coords_inv(phi,geo,theta,flag="oo")
x=np.r_[x_oi,x_fo[::-1]]
y=np.r_[y_oi,y_fo[::-1]]
(xc,yc)=MaxIncircle(x,y,100)
axis.text(xc,yc,label,ha='center',va='center',size=fs)
else:
if 'd2' in CVList:
if not 'CVNames' in kwargs:
label='$d_2$'
else:
label=CVNames[CVList.index('d2')]
phi=np.linspace(geo.phi_oe-(theta),geo.phi_oe-theta-2*pi,100)
(x_oi,y_oi)=coords_inv(phi,geo,theta,flag="oi")
phi=np.linspace(geo.phi_oe-(theta)-pi,geo.phi_oe-pi-theta-2*pi,100)
(x_fo,y_fo)=coords_inv(phi,geo,theta,flag="fo")
x=np.r_[x_oi,x_fo[::-1]]
y=np.r_[y_oi,y_fo[::-1]]
(xc,yc)=MaxIncircle(x,y,100)
axis.text(xc,yc,label,ha='center',va='center',size=fs)
if 'd1' in CVList:
if not 'CVNames' in kwargs:
label='$d_1$'
else:
label=CVNames[CVList.index('d1')]
phi=np.linspace(geo.phi_oe-(theta),geo.phi_oe-theta-2*pi,100)
(x_oi,y_oi)=coords_inv(phi,geo,theta,flag="fi")
phi=np.linspace(geo.phi_oe-(theta)-pi,geo.phi_oe-pi-theta-2*pi,100)
(x_fo,y_fo)=coords_inv(phi,geo,theta,flag="oo")
x=np.r_[x_oi,x_fo[::-1]]
y=np.r_[y_oi,y_fo[::-1]]
(xc,yc)=MaxIncircle(x,y,100)
axis.text(xc,yc,label,ha='center',va='center',size=fs)
if 'dd' in CVList:
if not 'CVNames' in kwargs:
label='$dd$'
else:
label=CVNames[CVList.index('dd')]
(x1,y1)=(geo.t2_line,geo.m_line*geo.t2_line+geo.b_line)
(x2,y2)=(-geo.t2_line+geo.ro*cos(geo.phi_ie-pi/2-theta),-(geo.m_line*geo.t2_line+geo.b_line)+geo.ro*sin(geo.phi_ie-pi/2-theta))
axis.text(0.5*x1+0.5*x2,0.5*y1+0.5*y2,label,ha='center',va='center',size=fs)
if 'ddd' in CVList:
if not 'CVNames' in kwargs:
label='$ddd$'
else:
label=CVNames[CVList.index('ddd')]
(x1,y1)=(geo.t2_line,geo.m_line*geo.t2_line+geo.b_line)
(x2,y2)=(-geo.t2_line+geo.ro*cos(geo.phi_ie-pi/2-theta),-(geo.m_line*geo.t2_line+geo.b_line)+geo.ro*sin(geo.phi_ie-pi/2-theta))
axis.text(0.5*x1+0.5*x2,0.5*y1+0.5*y2,label,ha='center',va='center',size=fs,color='k',bbox=dict(facecolor='white', alpha=0.5,boxstyle="round"))
[docs]
def fillS1(theta,**kwargs):
if 'axis' in kwargs:
axis=kwargs['axis']
else:
axis=pylab.gca()
if 'color' in kwargs:
color=kwargs['color']
else:
color='b'
geo=LoadGeo()
phi=np.linspace(geo.phi_oe,geo.phi_oe-theta,500)
(x_oi,y_oi)=coords_inv(phi,geo,theta,flag="oi")
phi=np.linspace(geo.phi_oe-pi,geo.phi_oe-pi-theta,500)
(x_fo,y_fo)=coords_inv(phi,geo,theta,flag="fo")
x=np.r_[x_oi,x_fo[::-1]]
y=np.r_[y_oi,y_fo[::-1]]
axis.fill(x,y,color=color)
return polyarea(x,y)*geo.h
[docs]
def fillC1(theta,**kwargs):
if 'axis' in kwargs:
axis=kwargs['axis']
else:
axis=pylab.gca()
if 'color' in kwargs:
color=kwargs['color']
else:
color='b'
geo=LoadGeo()
phi=np.linspace(geo.phi_oe-(theta-2*pi),geo.phi_oe-theta,500)
(x_oi,y_oi)=coords_inv(phi,geo,theta,flag="oi")
phi=np.linspace(geo.phi_oe-(theta-2*pi)-pi,geo.phi_oe-pi-theta,500)
(x_fo,y_fo)=coords_inv(phi,geo,theta,flag="fo")
x=np.r_[x_oi,x_fo[::-1]]
y=np.r_[y_oi,y_fo[::-1]]
axis.fill(x,y,color=color)
return polyarea(x,y)*geo.h
[docs]
def fillD1(theta,**kwargs):
if 'axis' in kwargs:
axis=kwargs['axis']
else:
axis=pylab.gca()
if 'color' in kwargs:
color=kwargs['color']
else:
color='b'
geo=LoadGeo()
phi=np.linspace(geo.phi_oe-(theta-2*pi),geo.phi_is,500)
(x_oi,y_oi)=coords_inv(phi,geo,theta,flag="oi")
phi=np.linspace(geo.phi_oe-(theta-2*pi)-pi,geo.phi_os,500)
(x_fo,y_fo)=coords_inv(phi,geo,theta,flag="fo")
x=np.r_[x_oi,x_fo[::-1]]
y=np.r_[y_oi,y_fo[::-1]]
axis.fill(x,y,color=color)
return polyarea(x,y)*geo.h
[docs]
def polyarea(x,y):
N=len(x)
area = 0.0
for i in range(N):
j = (i+1) % N
area = area + x[i]*y[j] - y[i]*x[j]
return area/2.0
[docs]
def polycentroid(xi,yi):
# Add additional element if needed to close polygon
if not xi[0]==xi[-1] or not yi[0]==yi[-1]:
x=np.r_[xi,xi[-1]]
y=np.r_[yi,yi[-1]]
else:
x=xi
y=yi
sumx=0.0
sumy=0.0
for i in range(len(x)-1):
sumx=sumx+(x[i]+x[i+1])*(x[i]*y[i+1]-x[i+1]*y[i])
sumy=sumy+(y[i]+y[i+1])*(x[i]*y[i+1]-x[i+1]*y[i])
return sumx/(6*polyarea(x,y)),sumy/(6*polyarea(x,y))
[docs]
def CoordsOrbScroll(theta,geo,shaveOn=True, just_involutes = False, Ndict = {}):
from PDSim.scroll import scroll_geo
shaveDelta=None
if shaveOn==True:
shaveDelta = pi/2
else:
shaveDelta = 1e-16
(xshave, yshave) = Shave(geo, theta, shaveDelta)
Nphi = Ndict.get('phi',500)
Narc1 = Ndict.get('arc1',100)
Nline = Ndict.get('line',100)
Narc2 = Ndict.get('arc2',100)
phi = np.linspace(geo.phi_ois, geo.phi_oie, Nphi)
(x_oi,y_oi) = scroll_geo.coords_inv(phi,geo,theta,flag="oi")
phi = np.linspace(geo.phi_oos, geo.phi_ooe - shaveDelta, Nphi)
(x_oo,y_oo) = scroll_geo.coords_inv(phi,geo,theta,flag="oo")
xarc1=geo.xa_arc1+geo.ra_arc1*cos(np.linspace(geo.t2_arc1,geo.t1_arc1,Narc1))
yarc1=geo.ya_arc1+geo.ra_arc1*sin(np.linspace(geo.t2_arc1,geo.t1_arc1,Narc1))
xline=np.linspace(geo.t1_line,geo.t2_line,Nline)
yline=geo.m_line*xline+geo.b_line
xarc2=geo.xa_arc2+geo.ra_arc2*cos(np.linspace(geo.t1_arc2,geo.t2_arc2,Narc2))
yarc2=geo.ya_arc2+geo.ra_arc2*sin(np.linspace(geo.t1_arc2,geo.t2_arc2,Narc2))
ro = geo.rb*(pi-geo.phi_fi0+geo.phi_fo0)
om = geo.phi_fie-theta+3.0*pi/2.0
xarc1_o=-xarc1+ro*cos(om)
yarc1_o=-yarc1+ro*sin(om)
xline_o=-xline+ro*cos(om)
yline_o=-yline+ro*sin(om)
xarc2_o=-xarc2+ro*cos(om)
yarc2_o=-yarc2+ro*sin(om)
if just_involutes:
x=np.r_[x_oo,x_oi[::-1]]
y=np.r_[y_oo,y_oi[::-1]]
else:
if shaveOn:
x=np.r_[x_oo,xshave,x_oi[::-1],xarc1_o,xline_o,xarc2_o]
y=np.r_[y_oo,yshave,y_oi[::-1],yarc1_o,yline_o,yarc2_o]
else:
x=np.r_[x_oo,x_oi[::-1],xarc1_o,xline_o,xarc2_o]
y=np.r_[y_oo,y_oi[::-1],yarc1_o,yline_o,yarc2_o]
#Output as a column vector
x=x.reshape(len(x),1)
y=y.reshape(len(y),1)
return x,y
[docs]
def plotScrollSet(theta,geo = None,axis = None, fig = None, lw = None, OSColor = None, show = False, offsetScroll = False, **kwargs):
r"""
The function that plots the scroll sets
Arguments:
theta : float
Crank angle in radians in the range 0 to :math:`2\pi`
Returns:
OS : matplotlib polygon object for the orbiting scroll
Optional Parameters
============= =====================================================
Variable Description
============= =====================================================
fig figure to plot on : default, make new figure
axis axis to plot on : default pylab.gca()
geo geoVals class with geometric parameters
discOn plot the discharge port: True/[False]
OSColor color of orbiting scroll: default 'r'
lw line width : default 1.0
discCurves plot the discharge curves : True/[False]
shaveOn shave the end of orb. scroll : True/[False]
saveCoords save the coord. of the orb. scroll to file True/[False]
wallOn plot the outer wall : [True] /False
offsetScroll If true, scrolls are offset : True/[False]
============= =====================================================
"""
from PDSim.scroll import scroll_geo
if axis is None:
if fig is None:
fig=pylab.figure(figsize=(5,5))
axis=fig.add_axes((0,0,1,1))
if geo is None:
geo=geoVals(rb=0.003522,phi_i0=0.19829,phi_is=4.7,phi_ie=15.5,phi_o0=-1.1248,phi_os=1.8,phi_oe=15.5,h=0.03289)
setDiscGeo(geo)
if OSColor is not None:
OSColor=kwargs['OSColor']
else:
OSColor='r'
if lw is None:
lw=1.0
if offsetScroll:
#Turn off the conventional wall
kwargs['wallOn'] = False
#Turn off shaving of the orbiting scroll
kwargs['shaveOn'] = False
# # This is the part of the fixed scroll forming the extension for
# # the offset scroll pocket
# phi = np.linspace(geo.phi_fie, geo.phi_fie+geo.phi_ie_offset,1000)
# x,y = scroll_geo.coords_inv(phi, geo, 0.0, 'fi')
# axis.plot(x,y,'k')
# phi = np.linspace(geo.phi_ie,geo.phi_ie+1.02*pi,1000)
# x,y = coords_inv(phi,geo,theta,'oo')
# axis.plot(x,y,'r--')
# pitch (involute-involute distance for a given involute)
# for 2*pi radians or one rotation is equal to 2*pi*rb, subtract
# thickness of scroll to get diameter
# and divide by two to get radius of closing arc for offset region
r = (2*pi*geo.rb-geo.t)/2.0
xee,yee = scroll_geo.coords_inv(geo.phi_fie,geo,0.0,'fi')
xse,yse = scroll_geo.coords_inv(geo.phi_foe-2*pi,geo,0.0,'fo')
x0,y0 = (xee+xse)/2,(yee+yse)/2
beta = math.atan2(yee-y0,xee-x0)
t = np.linspace(beta,beta+pi,1000)
x,y = x0+r*np.cos(t),y0+r*np.sin(t)
axis.plot(x,y,'k',lw=lw)
axis.plot([x[0],x[-1]],[y[0],y[-1]],'b-')
xarc1=geo.xa_arc1+geo.ra_arc1*cos(np.linspace(geo.t2_arc1,geo.t1_arc1,100))
yarc1=geo.ya_arc1+geo.ra_arc1*sin(np.linspace(geo.t2_arc1,geo.t1_arc1,100))
xline=np.linspace(geo.t1_line,geo.t2_line,100)
yline=geo.m_line*xline+geo.b_line
xarc2=geo.xa_arc2+geo.ra_arc2*cos(np.linspace(geo.t1_arc2,geo.t2_arc2,100))
yarc2=geo.ya_arc2+geo.ra_arc2*sin(np.linspace(geo.t1_arc2,geo.t2_arc2,100))
##Fixed Scroll
phi=np.linspace(geo.phi_fis,geo.phi_fie,500)
(x_fi,y_fi)=scroll_geo.coords_inv(phi,geo,theta,flag="fi")
phi=np.linspace(geo.phi_fos,geo.phi_foe,500)
(x_fo,y_fo)=scroll_geo.coords_inv(phi,geo,theta,flag="fo")
## Discharge port
if 'discOn' in kwargs and kwargs['discOn']==True:
t=np.linspace(0,2*pi,100)
x=geo.disc_x0+geo.disc_R*cos(t)
y=geo.disc_y0+geo.disc_R*sin(t)
axis.plot(x,y,'k--',lw=lw,zorder=0)
if 'discCurves' in kwargs and kwargs['discCurves']==True:
(x_fis,y_fis)=coords_inv(geo.phi_os+pi,geo,theta,flag="fi")
(nx_fis,ny_fis)=coords_norm(geo.phi_os+pi,geo,theta,flag="fi")
x0=x_fis-nx_fis*geo.ro
y0=y_fis-ny_fis*geo.ro
axis.plot(x0,y0,'o')
axis.plot(x_fis,y_fis,'s')
t=np.linspace(0,2*pi,200)
axis.plot(x0+geo.ro*cos(t),y0+geo.ro*sin(t),'-')
axis.plot(geo.xa_arc1,geo.ya_arc1,'^')
axis.plot(geo.xa_arc1+geo.ra_arc1*cos(t),geo.ya_arc1+geo.ra_arc1*sin(t),'k--')
if 'wallOn' not in kwargs or kwargs['wallOn']:
## Outer Wall
(x_wall,y_wall)=circle(geo.x0_wall,geo.y0_wall,geo.r_wall,N=200)
axis.plot(x_wall,y_wall,'k',lw=lw)
axis.set_xlim([min(x_wall)-0.001,max(x_wall)+0.001])
axis.set_ylim([min(y_wall)-0.001,max(y_wall)+0.001])
axis.plot(np.r_[xarc1,xline,xarc2],np.r_[yarc1,yline,yarc2],'k',lw=lw)
axis.plot(x_fi,y_fi,'k',lw=lw)
axis.plot(x_fo,y_fo,'k',lw=lw)
axis.plot(np.r_[x_fo[-1],x_fi[-1]],np.r_[y_fo[-1],y_fi[-1]],'k',lw=lw)
shaveOn=None
if 'shaveOn' in kwargs and kwargs['shaveOn']==False:
shaveOn=False
else:
shaveOn=True
##Orbiting Scroll
(XOS,YOS)=CoordsOrbScroll(theta,geo,shaveOn)
xy=np.hstack((XOS,YOS))
OrbScroll=pyplot.Polygon(xy,color=OSColor,lw=lw,fill=True,closed=True,ec='k')
axis.add_patch(OrbScroll)
axis.set_aspect(1.0)
axis.axis('off')
if 'saveCoords' in kwargs:
np.savetxt('xos.csv',XOS,delimiter=',')
np.savetxt('yos.csv',YOS,delimiter=',')
if show:
pylab.show()
return OrbScroll
[docs]
def overlay_injection_port(theta, geo, phi, ax, inner_outer, rport = None, offset = None):
r"""
Plot the injection ports on an axis - no scroll wrap plot is generated. Also see
plot_injection_ports()
Parameters
----------
theta : float
crank angle in the range [0, :math:`2\pi`]
geo : geoVals instance
phi : float
Involute angle in radians
ax : matplotlib axis instance
inner_outer : string
If ``'i'``, phi is along the inner involute of the fixed scroll
If ``'o'``, phi is along the outer involute of the fixed scroll
Notes
-----
If you want symmetric injection ports, the ones on the inner involute
should have a value of phi that is pi radians greater than those on the
outer involute
"""
#Common terms
if rport is None:
rport = geo.t/2.0
if offset is None:
offset = rport/2.0
t = np.linspace(0,2*pi,100)
if inner_outer == 'o':
#Involute angle along the outer involute of the scroll wrap
x, y = common_scroll_geo.coords_inv(phi, geo, theta, 'fo')
nx, ny = common_scroll_geo.coords_norm(phi, geo, theta, 'fo')
xc,yc = x-nx*offset,y-ny*offset
ax.plot(xc + rport*np.cos(t),yc+rport*np.sin(t),'k')
elif inner_outer == 'i':
x, y = common_scroll_geo.coords_inv(phi, geo, theta, 'fi')
nx, ny = common_scroll_geo.coords_norm(phi, geo, theta, 'fi')
xc,yc = x-nx*offset,y-ny*offset
ax.plot(xc + rport*np.cos(t),yc+rport*np.sin(t),'k')
else:
raise KeyError
[docs]
def plot_injection_ports(theta, geo, phi, ax, inner_outer):
r"""
Plot the injection ports
Parameters
----------
theta : float
crank angle in the range [0, :math:`2\pi`]
geo : geoVals instance
phi : float
Involute angle in radians
ax : matplotlib axis instance
inner_outer : string
If ``'i'``, phi is along the inner involute of the fixed scroll
If ``'o'``, phi is along the outer involute of the fixed scroll
Notes
-----
If you want symmetric injection ports, the ones on the inner involute
should have a value of phi that is pi radians greater than those on the
outer involute
"""
#Plot the scrolls (symmetric)
plotScrollSet(theta, geo, axis = ax)
#Plot the port
core_scroll_geo.overlay_injection_port(theta, geo, phi, ax, inner_outer)
[docs]
class PlotPanel(wx.Panel):
def __init__(self, *args, **kwds):
kwds["style"] = wx.TAB_TRAVERSAL
wx.Panel.__init__(self, *args,**kwds)
size = kwds.pop('size',(400,400))
self.figure=Figure(figsize=(size[0]/100,size[1]/100),dpi=100)
self.axes=self.figure.add_subplot(111)
self.canvas=FigureCanvas(self,wx.ID_ANY,self.figure)
[docs]
class TaskThread(threading.Thread):
"""Thread that executes a task every N seconds"""
def __init__(self):
threading.Thread.__init__(self)
self._finished = threading.Event()
self._interval = 15.0
[docs]
def setInterval(self, interval):
"""Set the number of seconds we sleep between executing our task"""
self._interval = interval
[docs]
def run(self):
while 1:
if self._finished.isSet(): return
self.task()
# sleep for interval or until shutdown
self._finished.wait(self._interval)
[docs]
class OSCrossSectionPanel(wx.Panel):
"""
A figure with the cross-section of the scroll wrap
"""
def __init__(self, parent, dictionary, phiv, h, w):
wx.Panel.__init__(self, parent)
self.pltpanel = PlotPanel(self, size = (300,300))
# Get the axes
ax = self.pltpanel.axes
D = dictionary['scroll_plate_diameter']
ro = dictionary['ro']
tplate = dictionary['scroll_plate_thickness']
thrust_ID = dictionary['thrust_ID']
Ljournal = dictionary['L_crank_bearing']
journal_IR = dictionary['D_crank_bearing']/2.0
thrust_IR = thrust_ID/2.0
tthrust = tplate
ax.fill([-D/2, D/2, D/2, -D/2, -D/2], [-tplate, -tplate, 0, 0, -tplate],'grey')
# The thrust bearing
ax.fill([-1.5*thrust_IR,-thrust_IR,-thrust_IR,-1.5*thrust_IR,-1.5*thrust_IR],[-tplate-tthrust,-tplate-tthrust,-tplate,-tplate,-tplate-tthrust],'red')
ax.fill([1.5*thrust_IR,thrust_IR,thrust_IR,1.5*thrust_IR,1.5*thrust_IR],[-tplate-tthrust,-tplate-tthrust,-tplate,-tplate,-tplate-tthrust],'red')
# The journal housing
ax.fill([-1.5*journal_IR,-journal_IR,-journal_IR,-1.5*journal_IR,-1.5*journal_IR],[-tplate-Ljournal,-tplate-Ljournal,-tplate,-tplate,-tplate-Ljournal],'blue')
ax.fill([1.5*journal_IR,journal_IR,journal_IR,1.5*journal_IR,1.5*journal_IR],[-tplate-Ljournal,-tplate-Ljournal,-tplate,-tplate,-tplate-Ljournal],'blue')
for phi in phiv:
phi0 = 0
rb = 0.003
y = rb*(sin(phi) - (phi - phi0)*cos(phi))
ax.fill([y-w/2,y+w/2,y+w/2,y-w/2,y-w/2],[0,0,h,h,0],'grey')
ax.plot([1.5*journal_IR + ro,1.5*journal_IR + ro],[-tplate-Ljournal, -tplate],'b:')
ax.plot([-1.5*journal_IR + ro, -1.5*journal_IR + ro],[-tplate-Ljournal, -tplate],'b:')
ax.set_aspect('equal')
ax.axis('off')
# Layout
sizer = wx.BoxSizer(wx.VERTICAL)
sizer.Add(self.pltpanel)
self.SetSizer(sizer)
sizer.Layout()
[docs]
class ScrollAnimForm(wx.Frame):
#----------------------------------------------------------------------
def __init__(self, geo = None, start = True, size = (400, 400), param_dict = {}, disc_xy_coords = None):
wx.Frame.__init__(self, None, wx.ID_ANY, "Scroll Model GUI")
# Add a panel so it looks the correct on all platforms
panel = wx.Panel(self, wx.ID_ANY)
import wx.lib.agw.flatmenu as FM
self._mb = FM.FlatMenuBar(panel, wx.ID_ANY, 32, 5)
layersMenu = FM.FlatMenu()
self.LayerCoordinateAxes = FM.FlatMenuItem(layersMenu, -1, "Show coordinate axes", "Tooltip", wx.ITEM_CHECK)
self.LayerCoordinateAxes.Check(False)
self.Bind(FM.EVT_FLAT_MENU_SELECTED, self.OnApplyLayers,id = self.LayerCoordinateAxes.GetId())
layersMenu.AppendItem(self.LayerCoordinateAxes)
self.LayerOldham = FM.FlatMenuItem(layersMenu, -1, "Oldham ring", "Tooltip", wx.ITEM_CHECK)
self.LayerOldham.Check(False)
self.Bind(FM.EVT_FLAT_MENU_SELECTED, self.OnApplyLayers,id = self.LayerOldham.GetId())
layersMenu.AppendItem(self.LayerOldham)
self.LayerOrbitingScroll = FM.FlatMenuItem(layersMenu, -1, "Orbiting scroll", "Tooltip", wx.ITEM_CHECK)
self.LayerOrbitingScroll.Check(False)
self.Bind(FM.EVT_FLAT_MENU_SELECTED, self.OnApplyLayers,id = self.LayerOrbitingScroll.GetId())
layersMenu.AppendItem(self.LayerOrbitingScroll)
self._mb.Append(layersMenu, "&Layers")
animMenu = FM.FlatMenu()
self.SaveAnimation = FM.FlatMenuItem(layersMenu, -1, "Save animation", "Tooltip", wx.ITEM_NORMAL)
self.Bind(FM.EVT_FLAT_MENU_SELECTED, self.OnSaveAnimation,id = self.SaveAnimation.GetId())
animMenu.AppendItem(self.SaveAnimation)
self._mb.Append(animMenu, "&Animation")
# Create the items
self.btn = btn = wx.ToggleButton(panel, -1, "Start")
self.pltpanel = PlotPanel(panel, -1, size=size)
# Do the layout
sizer = wx.BoxSizer(wx.VERTICAL)
sizer.Add(self._mb,0,wx.EXPAND)
sizer.Add(self.btn, 0, wx.ALL|wx.CENTER, 5)
sizer.Add(self.pltpanel, 0, wx.ALL|wx.CENTER, 5)
panel.SetSizer(sizer)
# Bind the events
btn.Bind(wx.EVT_TOGGLEBUTTON,self.onButton)
self.Bind(wx.EVT_CLOSE,self.preClose)
self.theta = 0
self.N = 100
self.geo = geo
self.OS = plotScrollSet(0,
axis = self.pltpanel.axes,
geo = self.geo,
lw = 1,
discOn = False,
offsetScroll = self.geo.phi_ie_offset>0)
self.ax = self.pltpanel.axes
if disc_xy_coords is not None:
self.ax.plot(disc_xy_coords[0], disc_xy_coords[1])
sizer.Layout()
self.SetSize(sizer.GetMinSize())
self.writing_animation = False
self.param_dict = param_dict
self.orbiting_layers = []
if start:
self.start()
[docs]
def OnSaveAnimation(self, event):
self.SaveAnimation.Enable(False)
self.writing_animation = True
[docs]
def OnDoneSavingAnimation(self):
self.SaveAnimation.Enable(True)
self.writing_animation = False
import subprocess
subprocess.call('convert frame_*.png frames.gif',shell = True)
import glob
for file in glob.glob('frame_*.png'):
os.remove(file)
print('all done - saved to frames.gif')
[docs]
def OnApplyLayers(self, event):
self.remove_orbiting_layers()
self.ax.cla()
self.OS = plotScrollSet(self.theta,
axis=self.pltpanel.axes,
geo=self.geo,
lw=1,
discOn=False,
offsetScroll = self.geo.phi_ie_offset>0)
self.apply_stationary_layers()
self.apply_orbiting_layers(self.theta)
self.ax.figure.canvas.draw() #Annoyingly this draw is required to flush the ghost orbiting scroll
[docs]
def apply_stationary_layers(self):
if self.LayerCoordinateAxes.IsChecked():
self.ax.plot(0, 0, 'k+')
self.ax.plot([0, 0.01], [0,0], 'k')
self.ax.plot([0,0], [0.01, 0], 'k')
self.ax.text(0.01,0,'$x$')
self.ax.text(0,0.01,'$y$')
def _proj_onto_xd(self, x, y, beta):
# unit vector pointing in the +xbeta direction
ubeta = np.array([cos(beta),sin(beta)])
r = np.array([x,y])
proj = np.dot(r,ubeta)*ubeta
return proj
def _proj_onto_yd(self, x, y, beta):
# unit vector pointing in the +xbeta direction
ubeta = np.array([-cos(beta),sin(beta)])
r = np.array([x,y])
proj = np.dot(r,ubeta)*ubeta
return proj
[docs]
def apply_orbiting_layers(self, theta = 0):
self.remove_orbiting_layers()
def rotated_rectangle(x0,y0,w,h,rot):
x = np.array([-w/2,w/2,w/2,-w/2,-w/2])
y = np.array([-h/2,-h/2,h/2,h/2,-h/2])
xrot = x*cos(rot)-y*sin(rot)
yrot = x*sin(rot)+y*cos(rot)
return xrot+x0, yrot+y0
if self.LayerCoordinateAxes.IsChecked():
om = self.geo.phi_ie-theta-pi/2.0
xo = self.geo.ro*cos(om)
yo = self.geo.ro*sin(om)
self.orbiting_layers.append(self.ax.plot(xo, yo, 'ko')[0])
beta = self.param_dict.get('beta', pi/6)
rring = self.param_dict.get('oldham_ring_radius', 0.04)
lkey = wkey = self.param_dict.get('oldham_key_width', 0.005)
if self.LayerOldham.IsChecked():
om = self.geo.phi_ie-theta-pi/2.0
xo = self.geo.ro*cos(om)
yo = self.geo.ro*sin(om)
OSkeys = [dict(r = rring, width = wkey, length = lkey, xbeta_offset = self.param_dict['pin3_xbeta_offset']),
dict(r = rring, width = wkey, length = lkey, betaplus = pi, xbeta_offset = self.param_dict['pin4_xbeta_offset'])]
FSkeys = [dict(r = rring, width = wkey, length = lkey, ybeta_offset = self.param_dict['pin1_ybeta_offset']),
dict(r = rring, width = wkey, length = lkey, betaplus = pi, ybeta_offset = self.param_dict['pin2_ybeta_offset'])]
for key in OSkeys:
r = key['r']
width = key['width']
length = key['length']
xbeta_offset = key['xbeta_offset']
betaplus = key.get('betaplus',0)
betakey = beta + betaplus + pi/2
xo = self.geo.ro*cos(om)
yo = self.geo.ro*sin(om)
xbeta = self.geo.ro*cos(om)*cos(beta)+self.geo.ro*sin(om)*sin(beta) + xbeta_offset
ybeta = 0
xoffset = xbeta*cos(beta)+ybeta*sin(beta)
yoffset = xbeta*sin(beta)-ybeta*cos(beta)
xoffset_slot = xbeta_offset*cos(beta) #ybeta_offset is zero
yoffset_slot = xbeta_offset*sin(beta)
x,y = rotated_rectangle(r*cos(betakey),r*sin(betakey),length+3*self.geo.ro,width,beta+pi/2)
self.orbiting_layers.append(self.ax.fill(x+xo+xoffset_slot, y+yo+yoffset_slot, 'green', alpha = 0.5)[0])
x,y = rotated_rectangle(r*cos(betakey),r*sin(betakey),width,length,beta)
self.orbiting_layers.append(self.ax.fill(x+xoffset,y+yoffset,'k')[0])
for key in FSkeys:
r = key['r']
width = key['width']
length = key['length']
ybeta_offset = key['ybeta_offset']
betaplus = key.get('betaplus',0)
betakey = beta + betaplus
xbeta = self.geo.ro*cos(om)*cos(beta)+self.geo.ro*sin(om)*sin(beta)
ybeta = ybeta_offset
xoffset = xbeta*cos(beta)+ybeta*sin(beta)
yoffset = xbeta*sin(beta)-ybeta*cos(beta)
xoffset_slot = ybeta_offset*sin(beta) # xbeta offset is zero
yoffset_slot = -ybeta_offset*cos(beta) # ybeta_offset is zero
# The slot
x,y = rotated_rectangle(r*cos(betakey),r*sin(betakey),length+3*self.geo.ro,width,beta)
self.orbiting_layers.append(self.ax.fill(x+xoffset_slot, y+yoffset_slot, 'yellow', alpha = 0.5)[0])
# The key
x,y = rotated_rectangle(r*cos(betakey),r*sin(betakey),width,length,beta)
self.orbiting_layers.append(self.ax.fill(x+xoffset, y+yoffset, 'k')[0])
if self.LayerOrbitingScroll.IsChecked():
om = self.geo.phi_ie-theta-pi/2.0
xo = self.geo.ro*cos(om)
yo = self.geo.ro*sin(om)
OSkeys = [dict(r = rring, width = wkey, length = lkey),
dict(r = rring, width = wkey, length = lkey, betaplus = pi)]
FSkeys = [dict(r = rring, width = wkey, length = lkey),
dict(r = rring, width = wkey, length = lkey, betaplus = pi)]
for key in OSkeys:
r = key['r']
width = key['width']
length = key['length']
betaplus = key.get('betaplus',0)
betakey = beta + betaplus + pi/2
xo = self.geo.ro*cos(om)
yo = self.geo.ro*sin(om)
xbeta = self.geo.ro*cos(om)*cos(beta)+self.geo.ro*sin(om)*sin(beta)
ybeta = 0
xoffset = xbeta*cos(beta)+ybeta*sin(beta)
yoffset = xbeta*sin(beta)-ybeta*cos(beta)
x,y = rotated_rectangle(r*cos(betakey),r*sin(betakey),length+3*self.geo.ro,width,beta+pi/2)
self.orbiting_layers.append(self.ax.fill(x+xo,y+yo,'green', alpha = 0.5)[0])
x,y = rotated_rectangle(r*cos(betakey),r*sin(betakey),width,length,beta)
self.orbiting_layers.append(self.ax.fill(x+xoffset,y+yoffset,'k')[0])
self.ax.set_autoscale_on(True)
[docs]
def remove_orbiting_layers(self):
#Clean out all the items from the orbiting layers
for item in self.orbiting_layers:
item.remove() # Remove from the GUI
self.orbiting_layers = []
[docs]
def start(self):
"""
Start the plotting machinery
"""
self.PT=PlotThread()
self.PT.setDaemon(True)
self.PT.setGUI(self) #pass it an instance of the frame (by reference)
self.PT.setInterval(0.05) #delay between plot events
self.PT.start()
[docs]
def onButton(self, event):
"""
Runs the thread
"""
btn = event.GetEventObject()
if btn.GetValue()==True:
btn.SetLabel("Stop")
else:
btn.SetLabel("Start")
def _updateDisplay(self):
"""
Updates the animation
"""
if self.Animate==True:
wx.CallAfter(self.plotStep)
self.plotThread=threading.Timer(0.001, self.updateDisplay)
self.plotThread.daemon=True
self.plotThread.start()
[docs]
def plotStep(self):
self.remove_orbiting_layers()
self.theta += 2*np.pi/(self.N-1)
# Plot the orbiting layers
self.apply_orbiting_layers(self.theta)
#If offset scroll, don't shave the orbiting scroll
(x,y)=CoordsOrbScroll(self.theta,
self.geo,
shaveOn = self.geo.phi_ie_offset < 1e-12
)
#Create the data for the orbiting scroll
self.OS.set_xy(np.hstack((x,y)))
self.ax.figure.canvas.draw() #Annoyingly this draw is required to flush the ghost orbiting scroll
self.SetTitle('theta = '+str(self.theta)+' radians')
if self.writing_animation:
if not hasattr(self,'frame_counter_start'):
self.frame_counter = self.frame_counter_start = 0
fName = 'frame_{i:04d}.png'.format(i=self.frame_counter)
self.ax.figure.savefig(fName)
print('saving', fName)
self.frame_counter += 1
if self.frame_counter == self.N-1:
self.OnDoneSavingAnimation()
[docs]
def preClose(self,event):
"""
This runs at the beginning of the closing event to deal with cleanup
of threads and the GUI
"""
self.PT.shutdown()
self.Destroy()
if __name__== "__main__":
from PDSim.scroll.core import Scroll
ScrollComp = Scroll()
ScrollComp.set_scroll_geo(83e-6, 3.3, 0.005, 0.006) #Set the scroll wrap geometry
ScrollComp.set_disc_geo('2Arc',r2 = 0)
ScrollComp.geo.phi_ie_offset = 0
app = wx.App()
frame = ScrollAnimForm(ScrollComp.geo)
frame.Show()
app.MainLoop()
# pylab.fill(x,y)
# pylab.show()
## pylab.show()
pass