def threebody(id, r, v, t): # Eqns of motion for 3-body if (id==0): return v # return velocity array else: # calc acceleration r12, r13, r23 = r[0]-r[1], r[0]-r[2], r[1]-r[2] s12, s13, s23 = vp.mag(r12), vp.mag(r13), vp.mag(r23) a = [-m2*r12/s12**3 - m3*r13/s13**3, # $\frac{d\vec{v}_i}{dt}$, m1*r12/s12**3 - m3*r23/s23**3, m1*r13/s13**3 + m2*r23/s23**3] return np.array(a) # return accel array
def threebody(id, r, v, t): # Eqns of motion for 3-body if (id == 0): return v # return velocity array else: # calc acceleration r12, r13, r23 = r[0] - r[1], r[0] - r[2], r[1] - r[2] s12, s13, s23 = vp.mag(r12), vp.mag(r13), vp.mag(r23) a = [ -m2 * r12 / s12**3 - m3 * r13 / s13**3, # $\frac{d\vec{v}_i}{dt}$, m1 * r12 / s12**3 - m3 * r23 / s23**3, m1 * r13 / s13**3 + m2 * r23 / s23**3 ] return np.array(a) # return accel array
def c_acel(self, xm, obj): acel = v.vector(0, 0, 0) for i in obj: if i.id != self.id: acel += (i.mass * (v.norm(i.pos - xm) * G) / (v.mag(i.pos - xm)**2)) return acel
def calculateVelocities(k1, k2): a=vs.mag((k1.vel-k2.vel)**2.0) b=-2.*np.dot((k1.pos-k2.pos),(k1.vel-k2.vel)) c=vs.mag(np.power(k1.pos-k2.pos,2.)-np.power(k1.radius+k2.radius,2.)) delta=b**2.0-4.0*a*c if a == 0. or delta < 0.: return dtp=(-1.0*b+np.sqrt(delta))/(2.*a) k1.pos-=k1.vel*dtp k2.pos-=k2.vel*dtp wsp=(k1.pos-k2.pos)/(np.abs(vs.mag(k1.pos-k2.pos))) k1.vel=k1.vel-2.0* k2.m /(k1.m+k2.m)*np.dot(k1.vel-k2.vel,wsp)*wsp k2.vel=k2.vel+2.0* k2.m /(k1.m+k2.m)*np.dot(k1.vel-k2.vel,wsp)*wsp k1.pos+=k1.vel*dtp k2.pos+=k2.vel*dtp print("hura")
def reDrawLines(): global fwd_line, mouse_line, cam_dist, ray, scene_size, linelen linelen = scene_size + vs.mag(cam_frame.axis.norm() * cam_dist + cam_frame.pos) reDrawLine(fwd_line, vs.vector(cam_dist, 0, 0), linelen, vs.vector(-1, 0, 0)) reDrawLine(mouse_line, vs.vector(cam_dist, 0, 0), linelen, ray)
def getfield(posn): """ Get the field at a given point.""" fld = vp.vector(0, 0, 0) for chrg in CHARGES: fld = fld + (posn - chrg.pos) * 8.988e9 * chrg.Q / vp.mag(posn - chrg.pos)**3 return fld
def drawCameraFrame(): # create frame and draw its contents global cam_box, cent_plane, cam_lab, cam_tri, range_lab, linelen, fwd_line global fwd_arrow, mouse_line, mouse_arrow, mouse_lab, fov, range_x, cam_dist, cam_frame global ray cam_frame = vs.frame( pos = vs.vector(0,2,2,), axis = (0,0,1)) # NB: contents are rel to this frame. start with camera looking "forward" # origin is at simulated scene.center fov = vs.pi/3.0 # 60 deg range_x = 6 # simulates scene.range.x cam_dist = range_x / vs.tan(fov/2.0) # distance between camera and center. ray = vs.vector(-20.0, 2.5, 3.0).norm() # (unit) direction of ray vector (arbitrary) # REL TO CAMERA FRAME cam_box = vs.box(frame=cam_frame, length=1.5, height=1, width=1.0, color=clr.blue, pos=(cam_dist,0,0)) # camera-box cent_plane = vs.box(frame=cam_frame, length=0.01, height=range_x*1.3, width=range_x*2, pos=(0,0,0), opacity=0.5 ) # central plane cam_lab = vs.label(frame=cam_frame, text= 'U', pos= (cam_dist,0,0), height= 9, xoffset= 6) cam_tri = vs.faces( frame=cam_frame, pos=[(0,0,0), (0,0,-range_x), (cam_dist,0,0)]) cam_tri.make_normals() cam_tri.make_twosided() range_lab = vs.label(frame=cam_frame, text= 'R', pos= (0, 0, -range_x), height= 9, xoffset= 6) linelen = scene_size + vs.mag( cam_frame.axis.norm()*cam_dist + cam_frame.pos) # len of lines from camera fwd_line = drawLine( vs.vector(cam_dist,0,0), linelen, vs.vector(-1,0,0)) fwd_arrow = vs.arrow(frame=cam_frame, axis=(-2,0,0), pos=(cam_dist, 0, 0), shaftwidth=0.08, color=clr.yellow) vs.label(frame=cam_frame, text='C', pos=(0,0,0), height=9, xoffset=6, color=clr.yellow) mouse_line = drawLine ( vs.vector(cam_dist,0,0), linelen, ray ) mouse_arrow = vs.arrow(frame=cam_frame, axis=ray*2, pos=(cam_dist,0,0), shaftwidth=0.08, color=clr.red) mouse_lab = vs.label(frame=cam_frame, text= 'M', height= 9, xoffset= 10, color=clr.red, pos= -ray*(cam_dist/vs.dot(ray,(1,0,0))) + (cam_dist,0,0))
def calculateVelocities(k1, k2): a = vs.mag((k1.vel - k2.vel)**2.0) b = -2. * np.dot((k1.pos - k2.pos), (k1.vel - k2.vel)) c = vs.mag( np.power(k1.pos - k2.pos, 2.) - np.power(k1.radius + k2.radius, 2.)) delta = b**2.0 - 4.0 * a * c if a == 0. or delta < 0.: return dtp = (-1.0 * b + np.sqrt(delta)) / (2. * a) k1.pos -= k1.vel * dtp k2.pos -= k2.vel * dtp wsp = (k1.pos - k2.pos) / (np.abs(vs.mag(k1.pos - k2.pos))) k1.vel = k1.vel - 2.0 * k2.m / (k1.m + k2.m) * np.dot( k1.vel - k2.vel, wsp) * wsp k2.vel = k2.vel + 2.0 * k2.m / (k1.m + k2.m) * np.dot( k1.vel - k2.vel, wsp) * wsp k1.pos += k1.vel * dtp k2.pos += k2.vel * dtp print("hura")
def rotation_matrix(omega): theta = mag(omega) if theta == 0: return np.matrix(np.identity(3)) axis = norm(omega) a = cos(theta / 2) b, c, d = -axis * sin(theta / 2) aa, bb, cc, dd = a * a, b * b, c * c, d * d bc, ad, ac, ab, bd, cd = b * c, a * d, a * c, a * b, b * d, c * d return np.matrix([[aa+bb-cc-dd, 2*(bc+ad), 2*(bd-ac)], [2*(bc-ad), aa+cc-bb-dd, 2*(cd+ab)], [2*(bd+ac), 2*(cd-ab), aa+dd-bb-cc]])
def go(animate=True): # default: True r, v = np.array([0.4667, 0.0]), np.array([0.0, 8.198]) # init r, v t, h, ta, angle = 0.0, 0.002, [], [] w = 1.0 / vp.mag(r) # $W_0=\Omega(r)$ if (animate): planet, info, RLvec = set_scene(r) while t < 100: # run for 100 years L = vp.cross(r, v) # $\vec{L}/m=\vec{r}\times \vec{v}$ A = vp.cross(v, L) - GM * r / vp.mag(r) # scaled RL vec, ta.append(t) angle.append(np.arctan(A.y / A.x) * 180 * 3600 / np.pi) # arcseconds if (animate): vp.rate(100) planet.pos = r # move planet RLvec.axis, RLvec.length = A, .25 # update RL vec info.text = 'Angle": %8.2f' % (angle[-1]) # angle info r, v, t, w = ode.leapfrog_tt(mercury, r, v, t, w, h) plt.figure() # make plot plt.plot(ta, angle) plt.xlabel('Time (year)'), plt.ylabel('Precession (arcsec)') plt.show()
def mag_gravity(a, b): '''Magnitude of gravity between a and b. Since gravity is always attractive we can easily calculuate the force on a with norm(b - a) and symmetrically for b ''' G = -6.67 * 1e-11 dist = mag(a.pos - b.pos)**2 if dist == 0: return 0 # The objects were the same else: return (G * a.mass * b.mass) / (1.0 * dist)
def go(animate = True): # default: True r, v = np.array([0.4667, 0.0]), np.array([0.0, 8.198]) # init r, v t, h, ta, angle = 0.0, 0.002, [], [] w = 1.0/vp.mag(r) # $W_0=\Omega(r)$ if (animate): planet, info, RLvec = set_scene(r) while t<100: # run for 100 years L = vp.cross(r, v) # $\vec{L}/m=\vec{r}\times \vec{v}$ A = vp.cross(v, L) - GM*r/vp.mag(r) # scaled RL vec, ta.append(t) angle.append(np.arctan(A.y/A.x)*180*3600/np.pi) # arcseconds if (animate): vp.rate(100) planet.pos = r # move planet RLvec.axis, RLvec.length = A, .25 # update RL vec info.text='Angle": %8.2f' %(angle[-1]) # angle info r, v, t, w = ode.leapfrog_tt(mercury, r, v, t, w, h) plt.figure() # make plot plt.plot(ta, angle) plt.xlabel('Time (year)'), plt.ylabel('Precession (arcsec)') plt.show()
def run_3body(scale): t, h, ic, cycle, R = 0.0, 0.001, 0, 20, 0.1 # anim cycle, R=obj size r, v = init_cond(scale) body, vel, line = set_scene(R, r) # create objects while True: vp.rate(1000) r, v = ode.leapfrog(threebody, r, v, t, h) ic = ic + 1 if (ic % cycle == 0): # animate once per 'cycle' for i in range(3): # move bodies, draw vel, path, lines body[i].pos = r[i] # bodies vel[i].pos, vel[i].axis = body[i].pos, v[i] vel[i].length = R * (1 + 2 * vp.mag(v[i])) # scale vel vector line.pos = [body[i].pos for i in [0, 1, 2]] # lines
def run_3body(scale): t, h, ic, cycle, R = 0.0, 0.001, 0, 20, 0.1 # anim cycle, R=obj size r, v = init_cond(scale) body, vel, line = set_scene(R, r) # create objects while True: vp.rate(1000) r, v = ode.leapfrog(threebody, r, v, t, h) ic = ic + 1 if (ic % cycle == 0): # animate once per 'cycle' for i in range(3): # move bodies, draw vel, path, lines body[i].pos = r[i] # bodies vel[i].pos, vel[i].axis = body[i].pos, v[i] vel[i].length = R*(1+2*vp.mag(v[i])) # scale vel vector line.pos = [body[i].pos for i in [0,1,2]] # lines
def __compute_sin_cos_beta(self): ''' find cos_beta and sin_beta from velocity vector where beta is the angle between x plane and velocity vector ''' v0_length = mag(self.velocities[-1]) eps = 0.00001 if(v0_length<=eps): cos_beta=0.0 sin_beta=1.0 else: cos_beta = self.velocities[-1][0]/v0_length sin_beta = self.velocities[-1][1]/v0_length return sin_beta, cos_beta
def solver(t, x0, v0, sin_beta, cos_beta, alfa, mi, k1, k2, m, sign_omega, kappa=1/20.0, B=4): ''' Solves the move equation. Move happens on an inclined plane with rules of uniformly accelerated motion. Air resistance force is dependent with velocity, friction is constant. Arguments: x0: initial position - vector v0: initial velocity in m/s - vector cos_beta,sin_beta - beta is the angle between x plane and velocity vector t: time - list of discrete time samples to be considered e.g. np.linspace(0, 5, 21) alfa: slope degree (degree between B and C) |\ | \ A | \ C | alfa \ |________\ B mi: coefficient of friction k1: air drag factor k2: air drag m : skier mass in kg kappa: curvature - reciprocal of the radius (positive makes right turn) B : boundary value (in m/s) from with air drag becomes proportional to the square of the velocity. ''' ''' Air drag is proportional to the square of velocity when the velocity is grater than some boundary value: B. k1 and k2 factors control whether we take square or linear proportion ''' v0_length = mag(v0) if v0_length <= B: k2 = 0 else: k1 = 0 params = [alfa, mi, k1, k2, m, kappa, cos_beta, sin_beta, sign_omega] w = odeint(_vectorfield, [x0[0], x0[1], v0[0], v0[1]], t, args=(params,) ) #print w,"\t" #,t,"\t" wlist = w.tolist() y = [wlist[1][1],wlist[1][3]] x = [wlist[1][0],wlist[1][2]] return x,y
def tagToggle2(self): # Selecting arrows, and other objects for which "pick" does not work closest = 1e9 closestObj = None # Iterate through all objects, and select the closest arrow object. for obj in self._otherObjects: # only select arrows - other objects can be directly selected. if not isinstance(obj, visual.primitives.arrow): continue # If this object is closest to pointer, save it for later. displacement = visual.mag(self.scene.mouse.pickpos - obj.pos) if displacement < closest: closest = displacement closestObj = obj # Now set the tags like normal obj = closestObj if obj == None: return self.tagToggle(obj=obj)
def handleCollision(self, other): difference = other.p - self.p if mag(difference) < self.radius + other.radius: vrelative = other.v - self.v normal = norm(difference) vrn = dot(vrelative, normal) if vrn < 0: #Collision Detected! difference = norm(difference) #Compute magnitude of Impulse Imag = -(1 + restitution) * vrn / (1.0 / self.mass + 1.0 / other.mass) I = Imag * normal # convert to a vector #Apply impulse to both affected balls self.v -= I / self.mass other.v += I / other.mass
def _vectorfield(w, t, params): ''' Right hand side of the differential equation in x plane. d2x/dt2 = v**2*sinus(beta)*kappa - ( mi*g*cos(alfa) + k1*(dx/dt)/m - k2*(dx/dt)^2/m )*cos(beta) ''' _,_, vx, vy = w alfa, mi, k1, k2, m, kappa, cosinus, sinus, sign_omega = params vl = mag((vx,vy)) f_R = vl**2*abs(kappa) # it's not the valu of the force -> no mass in eq f_r = f_R + sign_omega*g*sin(alfa)*cosinus ''' f_r can't be negative because it has to have the same sense (colloquially direction) as the f_R. If it is negative we decided to zero the F_R value so the skier goes straight. ''' if f_r < 0: f_r = sign_omega*g*sin(alfa)*cosinus f_R = 0 ''' The pressing force is the composition of the centripetal force and component of the gravity force. ''' N = sqrt ( (g*cos(alfa))**2 + (f_R)**2 ) f = [vx, vy, # dx/dt f_r*sinus*sign_omega - (mi*N + k1/m*vl + k2/m*vl**2)*cosinus , g*sin(alfa) - f_r*cosinus*sign_omega - (mi*N + k1/m*vl + k2/m*vl**2)*sinus # dx/dt ] # dv/dt return f
def draw_camera_frame(): """Create frame and draw its contents.""" global CAM_BOX, CENT_PLANE, CAM_LAB, CAN_TRI, RANGE_LAB, LINELEN, FWD_LINE global FWR_ARROW, MOUSE_LINE, MOUSE_ARROW, MOUSE_LAB, FOV, RANGE_X, CAM_DIST, CAM_FRAME global RAY CAM_FRAME = vs.frame(pos=vs.vector(0, 2, 2, ), axis=(0, 0, 1)) # NB: contents are rel to this frame. start with camera looking "forward" # origin is at simulated scene.center FOV = vs.pi/3.0 # 60 deg RANGE_X = 6 # simulates scene.range.x CAM_DIST = RANGE_X / vs.tan(FOV/2.0) # distance between camera and center. RAY = vs.vector(-20.0, 2.5, 3.0).norm() # (unit) direction of ray vector (arbitrary) # REL TO CAMERA FRAME CAM_BOX = vs.box(frame=CAM_FRAME, length=1.5, height=1, width=1.0, color=CLR.blue, pos=(CAM_DIST, 0, 0)) # camera-box CENT_PLANE = vs.box(frame=CAM_FRAME, length=0.01, height=RANGE_X*1.3, width=RANGE_X*2, pos=(0, 0, 0), opacity=0.5) # central plane CAM_LAB = vs.label(frame=CAM_FRAME, text='U', pos=(CAM_DIST, 0, 0), height=9, xoffset=6) CAN_TRI = vs.faces(frame=CAM_FRAME, pos=[ (0, 0, 0), (0, 0, -RANGE_X), (CAM_DIST, 0, 0)]) CAN_TRI.make_normals() CAN_TRI.make_twosided() RANGE_LAB = vs.label(frame=CAM_FRAME, text='R', pos=(0, 0, -RANGE_X), height=9, xoffset=6) LINELEN = SCENE_SIZE + vs.mag( CAM_FRAME.axis.norm()*CAM_DIST + CAM_FRAME.pos) # len of lines from camera FWD_LINE = draw_line(vs.vector(CAM_DIST, 0, 0), LINELEN, vs.vector(-1, 0, 0)) FWR_ARROW = vs.arrow(frame=CAM_FRAME, axis=(-2, 0, 0), pos=(CAM_DIST, 0, 0), shaftwidth=0.08, color=CLR.yellow) vs.label(frame=CAM_FRAME, text='C', pos=(0, 0, 0), height=9, xoffset=6, color=CLR.yellow) MOUSE_LINE = draw_line(vs.vector(CAM_DIST, 0, 0), LINELEN, RAY) MOUSE_ARROW = vs.arrow(frame=CAM_FRAME, axis=RAY*2, pos=(CAM_DIST, 0, 0), shaftwidth=0.08, color=CLR.red) MOUSE_LAB = vs.label( frame=CAM_FRAME, text='M', height=9, xoffset=10, color=CLR.red, pos=-RAY*(CAM_DIST/vs.dot(RAY, (1, 0, 0))) + (CAM_DIST, 0, 0))
def all_sums_comb(vecs): vecs_segs = [] res = 2 for v in vecs: norm = visual.mag(v) v1 = v*(res/norm) segs = [] nn = int(norm/res) start = 0 if not is_span_positive: start = -nn for i in range(start,nn): segs += [v1*i] vecs_segs += [segs] cartecians = ordered_cartesian(vecs_segs) sums = [] for c in cartecians: sum = visual.vector(orig) for v in c: sum += v sums += [sum] return sums
def all_sums_comb(vecs): vecs_segs = [] res = 2 for v in vecs: norm = visual.mag(v) v1 = v * (res / norm) segs = [] nn = int(norm / res) start = 0 if not is_span_positive: start = -nn for i in range(start, nn): segs += [v1 * i] vecs_segs += [segs] cartecians = ordered_cartesian(vecs_segs) sums = [] for c in cartecians: sum = visual.vector(orig) for v in c: sum += v sums += [sum] return sums
trail = vp.curve(pos=(0,0,0), radius=0.04) ideal = vp.curve(pos=(0,0,0), radius=0.04, color=vp.color.green) spin = vp.arrow(axis=omega,pos=(0,0,0),length=1) # omega dir info = vp.label(pos=(1.1*R,2,-2),text='Any key=repeat') return scene, ball, trail, ideal, spin def go(x, y, vx, vy): # motion with full drag and spin effects h, t, Y = 0.01, 0., np.array([[x,y,0.], [vx,vy,0.]]) # initialize while (Y[0,0]<R and Y[0,1]>0.2): # before homeplate&above ground vp.rate(40) t, Y = t+h, ode.RK4(baseball, Y, t, h) # integrate ball.pos, spin.pos = Y[0], Y[0]-offset # move ball, arrow spin.rotate(angle=phi), ball.rotate(angle=phi,axis=omega) #spin trail.append(pos=ball.pos) ideal.append(pos=(x+vx*t, y+vy*t-0.5*g*t*t, 0.)) # ideal case while (not scene.kb.keys): # check for key press vp.rate(40) spin.rotate(angle=phi), ball.rotate(angle=phi,axis=omega) scene.kb.getkey() # clear key trail.append(pos=(0,0,0), retain=0) # reset trails ideal.append(pos=(0,0,0), retain=0) g, b2, alpha, mass = 9.8, .0013, 5e-5, .15 # parameters R, omega = 18.4, 200.*np.array([0,1,1]) # range, angular velocity phi, offset = np.pi/16., 0.4*omega/vp.mag(omega) scene, ball, trail, ideal, spin = set_scene(R) while (1): go(x=0., y=2., vx=30., vy=0.) # initially z=0, vz=0
PS = 5.5 DLT = 0.05 THK = 5.04 nl = 1 # nl = 100 CF = vp.frame(frame=ROTOR_FRAME, pos=(0, 0, THK / 2.0 + C1 / 2.0)) for i in range(nl): # Extrude rotor core profile to get the full core body GE3 = vp.extrusion( pos=[(0, 0, i * DLT), (0, 0, i * DLT + THK)], shape=G3, color=(0.7, 0.7, 0.705), twist=0.0, frame=CF ) # Do the core wire windings # Here is a trick to build a saw-teeth profile, to represent many single windings N = 20 # coils VRIGHT = vp.vector(0.3, 1.3) R = vp.mag(VRIGHT) / (2 * N) VRIGHT = vp.norm(VRIGHT) # S is the cross sectional profile of "winding block" S = vp.Polygon([(-0.1, -0.65), (0, -0.65), (0.3, 0.65), (-0.1, 0.65)]) for n in range(N): RIGHT = vp.vector(0, -0.65) + (R + n * 2 * R) * VRIGHT # Add saw-teeth on the block to represent wires S += vp.shapes.circle(pos=(RIGHT.x, RIGHT.y), radius=R, np=4) # Define the winding path as a rounded rectangle P = vp.shapes.rectangle(width=0.5, height=THK) P += vp.shapes.circle(pos=(0, -THK / 2), radius=0.25, np=10) P += vp.shapes.circle(pos=(0, +THK / 2), radius=0.25, np=10) WRFS = [] for i in range(NS): # We need a separate frame for individiual winding section
target = V.sphere(pos=(D, H, 0), radius=1, color=V.color.yellow) target.velocity = V.vector(0, 0, 0) # The 'dart gun' is just a cylinder. gun = V.cylinder(pos=(0, 0, 0), axis=gun_len * sight, radius=1, color=V.color.green) # Run simulation print 'Starting simulation...' # Put a little delay to give all the OpenGL stuff time to initialize nicely. time.sleep(1) while (arrow.y >= 0 and target.y >=0) and \ V.mag(arrow.pos-target.pos) > impact_distance: V.rate(75) for obj in (arrow, target): obj.pos += obj.velocity * dt obj.velocity += dv # Report to user. if V.mag(arrow.pos - target.pos) <= impact_distance: print 'Hit!' else: print 'Miss...'
k1.pos+=k1.vel*dtp k2.pos+=k2.vel*dtp print("hura") n = 20 r = 1. dt = 0.1 kule = [] scena = vs.display(width=550,height=550) vs.sphere(pos=(0, 0, 0), radius=20,opacity=0.1) for x in range(n): kula = vs.sphere(pos=np.random.randint(-5,5,3), radius=r) kula.m=1. kula.vel = np.random.randint(-5,5,3) kule.append(kula) while True: vs.rate(10) for k1 in kule: for k2 in kule: k1.pos += k1.vel * dt if np.abs(vs.mag(k1.pos - k2.pos)) <= 3.0 * r: calculateVelocities(k1, k2) if np.abs(vs.mag(k1.pos)) > 20.: k1.vel = -k1.vel
BAND.p[:, 1] = BAND.p[:, 1] - M * G * DT # force[n] is the force on point n from point n+1 (to the right): LENGTH = (BAND.pos[1:] - BAND.pos[:-1]) DIST = vp.sqrt(vp.sum(LENGTH*LENGTH, -1)) FORCE = K * (DIST - RESTLENGTH) FORCE = LENGTH/DIST[:, vp.newaxis] * FORCE[:, vp.newaxis] BAND.p[:-1] = BAND.p[:-1] + FORCE*DT BAND.p[1:] = BAND.p[1:] - FORCE*DT # color based on "stretch": blue -> white -> red C = vp.clip(DIST/RESTLENGTH * 0.5, 0, 2) # blue (compressed) -> white (relaxed) -> red (tension) BAND.red[1:] = vp.where(vp.less(C, 1), C, 1) BAND.green[1:] = vp.where(vp.less(C, 1), C, 2-C) BAND.blue[1:] = vp.where(vp.less(C, 1), 1, 2-C) for S in SPHERES: DIST = vp.mag(BAND.pos - S.pos)[:, vp.newaxis] inside = vp.less(DIST, S.radius) if vp.sometrue(inside): R = (BAND.pos - S.pos) / DIST surface = S.pos + (S.radius)*R BAND.pos = surface*inside + BAND.pos*(1-inside) pdotR = vp.sum(vp.asarray(BAND.p)*vp.asarray(R), -1) BAND.p = BAND.p - R*pdotR[:, vp.newaxis]*inside
def moment(point, end1, end2=vector(0, 0, 0)): '''Returns the moment defined as the distance between a point and a line formed by two endpoints, end1 and end2. All points must be given as 3d vectors''' return mag(cross(point - end2, point - end1)) / \ mag(end1 - end2)
def hockey(Y, t): # return eqn of motion accel = 0. for i in range(len(loc)): accel += Q[i]*(Y[0]-loc[i])/(vp.mag(Y[0]-loc[i]))**3 return [Y[1], q*accel] # list for non-vectorized solver
def earth(id, r, v, t): # return the eqns of motion if (id == 0): return v # velocity, dr/dt s = vp.mag(r) # $s=|\vec{r}|$ return -GM*r/(s*s*s) # accel dv/dt, faster than s**3
def reDrawLines(): global fwd_line, mouse_line, cam_dist, ray, scene_size, linelen linelen = scene_size + vs.mag( cam_frame.axis.norm()*cam_dist + cam_frame.pos) reDrawLine( fwd_line, vs.vector(cam_dist,0,0), linelen, vs.vector(-1,0,0)) reDrawLine( mouse_line, vs.vector(cam_dist,0,0), linelen, ray )
Planet = sphere(pos=initpos, radius=0.02, color=color.blue, make_trail=True) #Graphic visualisation of Planet 1 Planet.trail_object.color = color.white # make Planet 1's trail white SecondPlanet = sphere(pos=Sinitpos, radius=0.05, color=color.cyan, make_trail=True) #Graphic visualisation of Planet 2 SecondPlanet.trail_object.color = color.red # make Planet 2's trail red Star = sphere(pos=(0, 0, 0), radius=0.08, color=color.yellow) #Graphic visualisation of Star vel = vector(-15, 0, 0) # initial velocity of planet 1 Svel = vector(-60, 0, 0) # initial velocity of planet 1 r = initpos #Position vector for Planet 1 r2 = Sinitpos #Position vector for Planet 2 while step <= maxstep: #Run simulation in time limit defined by maximum step Planet.pos = r #Set the 3D objects' location according to position vectors SecondPlanet.pos = r2 vel = vel - (M * mass1 / (mag(r)**3)) * r * dt + (mass1 * mass2 / (mag(r2 - r)**3)) * ( r2 - r) * dt #Velocity variation according to Newton's laws #Radially inwards interaction from star, outwards from second planet Svel = Svel - (M * mass2 / (mag(r2)**3)) * r2 * dt + (mass1 * mass2 / (mag(r2 - r)**3)) * (r2 - r) * dt #Radially inwards interaction from star and first planet r += dt * vel #Update position vectors r2 += dt * Svel step += 1 #Update step rate(75) #Fast animation print("end of program")
def r3body(y, t): # equations of motion for restricted 3body r, v = y[0], y[1] r1, r2 = r - [-a, 0], r - [b, 0] # rel pos vectors acc = -GM * (b * r1 / vp.mag(r1)**3 + a * r2 / vp.mag(r2)**3) # acc += omega**2 * r + 2 * omega * np.array([v[1], -v[0]]) # Coriolis term return np.array([v, acc])
k1.vel - k2.vel, wsp) * wsp k2.vel = k2.vel + 2.0 * k2.m / (k1.m + k2.m) * np.dot( k1.vel - k2.vel, wsp) * wsp k1.pos += k1.vel * dtp k2.pos += k2.vel * dtp print("hura") n = 20 r = 1. dt = 0.1 kule = [] scena = vs.display(width=550, height=550) vs.sphere(pos=(0, 0, 0), radius=20, opacity=0.1) for x in range(n): kula = vs.sphere(pos=np.random.randint(-5, 5, 3), radius=r) kula.m = 1. kula.vel = np.random.randint(-5, 5, 3) kule.append(kula) while True: vs.rate(10) for k1 in kule: for k2 in kule: k1.pos += k1.vel * dt if np.abs(vs.mag(k1.pos - k2.pos)) <= 3.0 * r: calculateVelocities(k1, k2) if np.abs(vs.mag(k1.pos)) > 20.: k1.vel = -k1.vel
#V is the potential. This next line puts in zero for every value. V=X*0 #In order to have a well behaved plot, Vmax sets the upper and lower limit Vmax=4e6 #This double loop goes through all the values in the mesh for i in range(len(X[:,0])): for j in range(len(Y[0,:])): #r_loc is the vector observation location based on x,y r_loc=vector(X[i,j],Y[i,j],0) #r1 is the vector from charge 1 to observation location r1=r_loc-q1 #r2 is the vector from charge 2 to observation location r2=r_loc-q2 #if the observation location is on either of the charge charges #do not computer V (it would be a division by zero) if mag(r1) !=0 and mag(r2)!=0: #calculate V V[i,j]=k*q1q/mag(r1) + k*q2q/mag(r2) #if V is too high, limit it if V[i,j]>=Vmax: V[i,j]=Vmax if V[i,j]<=-Vmax: V[i,j]=-Vmax #the plotting part data=[{'x':x, 'y':y, 'z':V, 'type':'contour'}] plot_url = py.plot(data, filename='electric potential_v2')
def dist(a,b): '''Returns the linear distance between a and b, i.e. the magnitude of the vector a - b.''' return( mag(a.pos - b.pos) )
def get_e_field2(pos, *pos_charge_tuples): f = vector(0, 0, 0) kel = 9e9 # Coulomb constant for c in pos_charge_tuples: f = f + (pos - c[0]) * kel * c[1] / mag(pos - c[0])**3 return f
def get_e_field(p, *charges): f = vector(0, 0, 0) kel = 9e9 # Coulomb constant for c in charges: f = f + (p.pos - c.pos) * kel * c.q / mag(p.pos - c.pos)**3 return f
q2q = -1e-6 #V is the potential. This next line puts in zero for every value. V = X * 0 #In order to have a well behaved plot, Vmax sets the upper and lower limit Vmax = 4e6 #This double loop goes through all the values in the mesh for i in range(len(X[:, 0])): for j in range(len(Y[0, :])): #r_loc is the vector observation location based on x,y r_loc = vector(X[i, j], Y[i, j], 0) #r1 is the vector from charge 1 to observation location r1 = r_loc - q1 #r2 is the vector from charge 2 to observation location r2 = r_loc - q2 #if the observation location is on either of the charge charges #do not computer V (it would be a division by zero) if mag(r1) != 0 and mag(r2) != 0: #calculate V V[i, j] = k * q1q / mag(r1) + k * q2q / mag(r2) #if V is too high, limit it if V[i, j] >= Vmax: V[i, j] = Vmax if V[i, j] <= -Vmax: V[i, j] = -Vmax #the plotting part data = [{'x': x, 'y': y, 'z': V, 'type': 'contour'}] plot_url = py.plot(data, filename='electric potential_v2')
# The target is a sphere target = V.sphere(pos=(D,H,0), radius=1, color=V.color.yellow) target.velocity = V.vector(0,0,0) # The 'dart gun' is just a cylinder. gun = V.cylinder(pos=(0,0,0), axis=gun_len*sight, radius=1, color = V.color.green) # Run simulation print 'Starting simulation...' # Put a little delay to give all the OpenGL stuff time to initialize nicely. time.sleep(1) while (arrow.y >= 0 and target.y >=0) and \ V.mag(arrow.pos-target.pos) > impact_distance: V.rate(75) for obj in (arrow,target): obj.pos += obj.velocity*dt obj.velocity += dv # Report to user. if V.mag(arrow.pos-target.pos) <= impact_distance: print 'Hit!' else: print 'Miss...'
def getfield(posn): """ Get the field at a given point.""" fld = vp.vector(0, 0, 0) for chrg in CHARGES: fld = fld + (posn-chrg.pos) * 8.988e9 * chrg.Q / vp.mag(posn-chrg.pos)**3 return fld
def r3body(y, t): # equations of motion for restricted 3body r, v = y[0], y[1] r1, r2 = r - [-a,0], r - [b,0] # rel pos vectors acc = -GM*(b*r1/vp.mag(r1)**3 + a*r2/vp.mag(r2)**3) # acc += omega**2*r + 2*omega*np.array([v[1], -v[0]]) # Coriolis term return np.array([v, acc])
def redraw_lines(): """ Re-Draw the lines.""" global LINELEN LINELEN = SCENE_SIZE + vs.mag(CAM_FRAME.axis.norm()*CAM_DIST + CAM_FRAME.pos) redraw_line(FWD_LINE, vs.vector(CAM_DIST, 0, 0), LINELEN, vs.vector(-1, 0, 0)) redraw_line(MOUSE_LINE, vs.vector(CAM_DIST, 0, 0), LINELEN, RAY)
T_step = step_interval s = sphere(make_trail=True, pos=[ride_radius + ride_radius2, 0, 0], radius=0.1) s.trail_object.color = color.yellow a_tangential = arrow(pos=[1, 0, 0], axis=[0, 1, 0], color=color.red) a_inward = arrow(pos=[1, 0, 0], axis=[-1, 0, 0], color=color.blue) for theta in arange(0, 100 * pi, T_step): rate(60) r = vector(ride_radius*cos(theta) + ride_radius2*cos(p*theta), \ ride_radius*sin(theta) + ride_radius2*sin(p*theta), 0) velocity = vector(-ride_radius*sin(theta)-ride_radius2*p*sin(p*theta), \ ride_radius*cos(theta)+ride_radius2*p*cos(p*theta),0) vel = str(velocity).strip('[]') acceleration = vector(-ride_radius*cos(theta) - ride_radius2*p**2*cos(p*theta), \ -ride_radius*sin(theta) - ride_radius2*p**2*sin(p*theta), 0) tangential_acceleration = (dot(velocity, acceleration) / mag(velocity)) * norm(velocity) tang_accel = str(tangential_acceleration).strip('[]') inward_acceleration = acceleration - tangential_acceleration in_accel = str(inward_acceleration).strip('[]') s.pos = r a_tangential.pos = r a_inward.pos = r a_tangential.axis = tangential_acceleration a_inward.axis = inward_acceleration data.append([theta, vel, tang_accel, in_accel]) for row in data: ws.append(row) ws.append(["Major Radius: ", r1]) ws.append(["Minor Radius: ", r2])
vel_bird = vector(v0 * np.cos(theta), v0 * np.sin(theta), 0) # initial velocity of Bird criticalspeed = 10 # Minimum speed of impact between Olaf and Bird for Olaf to be destroyed dt = 0.001 # timestep in seconds step = 1 # loop counter maxstep = 500 # maximum number of calculation steps to include #!@!@### TEMPLATE HEADER ENDS ###@!@!# while step <= maxstep: # While loop rate(80) #Setting rate of animation to a suitable level #Calculating position and velocity of bird due to gravitational forces from Death Star and Death Snowball vel_bird = vel_bird - G * M * ( (Bird.pos - DeathSnowball.pos) / (mag(Bird.pos - DeathSnowball.pos)**3)) * dt - G * M2 * ( (Bird.pos - DeathStar.pos) / (mag(Bird.pos - DeathStar.pos)**3)) * dt Bird.pos = Bird.pos + vel_bird * dt #Calculating position and velocity of Death Snowball due to gravitational forces bird vel_DS = vel_DS - G * mbird * ((DeathSnowball.pos - Bird.pos) / (mag(DeathSnowball.pos - Bird.pos)**3)) * dt DeathSnowball.pos = DeathSnowball.pos + vel_DS * dt #Calculating position and velocity of Death Star due to gravitational forces bird vel_DS2 = vel_DS2 - G * mbird * ((DeathStar.pos - Bird.pos) / (mag(DeathStar.pos - Bird.pos)**3)) * dt DeathStar.pos = DeathStar.pos + vel_DS2 * dt #Keeping Olaf in position on Death Snowball
def ug_energy(self, objects): ug = 0 for o in objects: if self.pos != o.pos: ug += -g * self.mass * o.mass / mag(self.pos - o.pos) return ug
spin = vp.arrow(axis=omega, pos=(0, 0, 0), length=1) # omega dir info = vp.label(pos=(1.1 * R, 2, -2), text='Any key=repeat') return scene, ball, trail, ideal, spin def go(x, y, vx, vy): # motion with full drag and spin effects h, t, Y = 0.01, 0., np.array([[x, y, 0.], [vx, vy, 0.]]) # initialize while (Y[0, 0] < R and Y[0, 1] > 0.2): # before homeplate&above ground vp.rate(40) t, Y = t + h, ode.RK4(baseball, Y, t, h) # integrate ball.pos, spin.pos = Y[0], Y[0] - offset # move ball, arrow spin.rotate(angle=phi), ball.rotate(angle=phi, axis=omega) #spin trail.append(pos=ball.pos) ideal.append(pos=(x + vx * t, y + vy * t - 0.5 * g * t * t, 0.)) # ideal case while (not scene.kb.keys): # check for key press vp.rate(40) spin.rotate(angle=phi), ball.rotate(angle=phi, axis=omega) scene.kb.getkey() # clear key trail.append(pos=(0, 0, 0), retain=0) # reset trails ideal.append(pos=(0, 0, 0), retain=0) g, b2, alpha, mass = 9.8, .0013, 5e-5, .15 # parameters R, omega = 18.4, 200. * np.array([0, 1, 1]) # range, angular velocity phi, offset = np.pi / 16., 0.4 * omega / vp.mag(omega) scene, ball, trail, ideal, spin = set_scene(R) while (1): go(x=0., y=2., vx=30., vy=0.) # initially z=0, vz=0
def hockey(Y, t): # return eqn of motion accel = 0. for i in range(len(loc)): accel += Q[i] * (Y[0] - loc[i]) / (vp.mag(Y[0] - loc[i]))**3 return [Y[1], q * accel] # list for non-vectorized solver
def baseball(Y, t): # Y = [r, v] assumed v = Y[1] fm = alpha * vp.cross(omega, v) # Magnus force a = (fm - b2 * vp.mag(v) * v) / mass - [0, g, 0] # minus g-vec return np.array([v, a]) # np array
mass2 = 0.1 # mass of planet 2 pos2 = vector(0, 5.1, 0.1) # initial position vector of planet 2 Planet2 = sphere(pos=pos2, radius=1 * mass2, color=color.white, make_trail=True) Planet2.trail_object.color = color.white # make the trail white vel2 = vector(35, 0, 0) # initial velocity of planet 2 #Making a loop while step <= maxstep: #I have added another term to the velocity equation so that the velocity of the body is affected by BOTH other bodies #Velocity and position calculations of planet 1 based on force from other two bodies vel1 = vel1 - dt * (G * M * pos1) / (mag(pos1)**3) - dt * ( G * mass2 * pos1) / (mag(pos1)**3) pos1 = pos1 + vel1 * dt #Velocity and position calculations of planet 2 based on force from other two bodies vel2 = vel2 - dt * (G * M * pos2) / (mag(pos2)**3) - dt * ( G * mass1 * (pos2 - pos1)) / (mag(pos2 - pos1)**3) pos2 = pos2 + vel2 * dt #time step t = t + dt #displayin planet and moon Planet1.pos = pos1 Planet2.pos = pos2
vp.sphere(pos=(-1e-13, 0, 0), Q=EC, color=vp.color.red, radius=6e-15), vp.sphere(pos=(1e-13, 0, 0), Q=-EC, color=vp.color.blue, radius=6e-15), ] def getfield(posn): """ Get the field at a given point.""" fld = vp.vector(0, 0, 0) for chrg in CHARGES: fld = fld + (posn - chrg.pos) * 8.988e9 * chrg.Q / vp.mag(posn - chrg.pos)**3 return fld while True: POSN = vp.scene.mouse.getclick().pos FLD = getfield(POSN) MAG = vp.mag(FLD) RED = vp.maximum(1 - 1e17 / MAG, 0) BLUE = vp.minimum(1e17 / MAG, 1) if RED >= BLUE: BLUE = BLUE / RED RED = 1.0 else: RED = RED / BLUE BLUE = 1.0 vp.arrow(pos=POSN, axis=FLD * (4e-14 / 1e17), shaftwidth=6e-15, color=(RED, 0, BLUE))
def baseball(Y, t): # Y = [r, v] assumed v = Y[1] fm = alpha*vp.cross(omega, v) # Magnus force a = (fm - b2*vp.mag(v)*v)/mass - [0,g,0] # minus g-vec return np.array([v, a]) # np array
vp.scene.title = "Electric Field Vectors" vp.scene.range = 2e-13 CHARGES = [ vp.sphere(pos=(-1e-13, 0, 0), Q=EC, color=vp.color.red, radius=6e-15), vp.sphere(pos=(1e-13, 0, 0), Q=-EC, color=vp.color.blue, radius=6e-15), ] def getfield(posn): """ Get the field at a given point.""" fld = vp.vector(0, 0, 0) for chrg in CHARGES: fld = fld + (posn-chrg.pos) * 8.988e9 * chrg.Q / vp.mag(posn-chrg.pos)**3 return fld while True: POSN = vp.scene.mouse.getclick().pos FLD = getfield(POSN) MAG = vp.mag(FLD) RED = vp.maximum(1-1e17/MAG, 0) BLUE = vp.minimum(1e17/MAG, 1) if RED >= BLUE: BLUE = BLUE/RED RED = 1.0 else: RED = RED/BLUE BLUE = 1.0 vp.arrow(pos=POSN, axis=FLD * (4e-14/1e17), shaftwidth=6e-15, color=(RED, 0, BLUE))
def get_g_field(p, *sources): f = vector(0, 0, 0) G = 6.674e-11 for s in sources: f = f + (p.pos - s.pos) * G * s.m / mag(p.pos - s.pos)**3 return f
scene = vp.display(title='Electric dipole', background=(.2,.5,1), forward=(0,-1,-.5), up=(0,0,1)) zaxis = vp.curve(pos=[(0,0,-r),(0,0,r)]) qpos = vp.sphere(pos=(0,0,.02), radius=0.01, color=(1,0,0)) qneg = vp.sphere(pos=(0,0,-.02), radius=0.01, color=(0,0,1)) c1 = vp.ring(pos=(0,0,0), radius=r, axis=(0,0,1), thickness=0.002) c2 = vp.ring(pos=(0,0,0), radius=r, axis=(0,1,0), thickness=0.002) theta, phi = np.linspace(0, np.pi, m), np.linspace(0, 2*np.pi, n) # grid phi, theta = vp.meshgrid(phi, theta) rs = r*np.sin(theta) x, y, z = rs*np.cos(phi), rs*np.sin(phi), r*np.cos(theta) # coord. for i in range(m): for j in range(n): rvec = vp.vector(x[i,j], y[i,j], z[i,j]) B = scale*vp.cross(rvec, vp.vector(0,0,1))/(r*r) # $\vec{r}\times \hat z/r^2$ E = vp.cross(B, rvec)/r # $\vec{B}\times \vec{r}/r$ vp.arrow(pos=rvec, axis=E, length=vp.mag(E), color=(1,1,0)) vp.arrow(pos=rvec, axis=B, length=vp.mag(B), color=(0,1,1))
def drawCameraFrame(): # create frame and draw its contents global cam_box, cent_plane, cam_lab, cam_tri, range_lab, linelen, fwd_line global fwd_arrow, mouse_line, mouse_arrow, mouse_lab, fov, range_x, cam_dist, cam_frame global ray cam_frame = vs.frame(pos=vs.vector( 0, 2, 2, ), axis=(0, 0, 1)) # NB: contents are rel to this frame. start with camera looking "forward" # origin is at simulated scene.center fov = vs.pi / 3.0 # 60 deg range_x = 6 # simulates scene.range.x cam_dist = range_x / vs.tan( fov / 2.0) # distance between camera and center. ray = vs.vector(-20.0, 2.5, 3.0).norm() # (unit) direction of ray vector (arbitrary) # REL TO CAMERA FRAME cam_box = vs.box(frame=cam_frame, length=1.5, height=1, width=1.0, color=clr.blue, pos=(cam_dist, 0, 0)) # camera-box cent_plane = vs.box(frame=cam_frame, length=0.01, height=range_x * 1.3, width=range_x * 2, pos=(0, 0, 0), opacity=0.5) # central plane cam_lab = vs.label(frame=cam_frame, text='U', pos=(cam_dist, 0, 0), height=9, xoffset=6) cam_tri = vs.faces(frame=cam_frame, pos=[(0, 0, 0), (0, 0, -range_x), (cam_dist, 0, 0)]) cam_tri.make_normals() cam_tri.make_twosided() range_lab = vs.label(frame=cam_frame, text='R', pos=(0, 0, -range_x), height=9, xoffset=6) linelen = scene_size + vs.mag(cam_frame.axis.norm() * cam_dist + cam_frame.pos) # len of lines from camera fwd_line = drawLine(vs.vector(cam_dist, 0, 0), linelen, vs.vector(-1, 0, 0)) fwd_arrow = vs.arrow(frame=cam_frame, axis=(-2, 0, 0), pos=(cam_dist, 0, 0), shaftwidth=0.08, color=clr.yellow) vs.label(frame=cam_frame, text='C', pos=(0, 0, 0), height=9, xoffset=6, color=clr.yellow) mouse_line = drawLine(vs.vector(cam_dist, 0, 0), linelen, ray) mouse_arrow = vs.arrow(frame=cam_frame, axis=ray * 2, pos=(cam_dist, 0, 0), shaftwidth=0.08, color=clr.red) mouse_lab = vs.label(frame=cam_frame, text='M', height=9, xoffset=10, color=clr.red, pos=-ray * (cam_dist / vs.dot(ray, (1, 0, 0))) + (cam_dist, 0, 0))
def mercury(id, r, v, t): # eqns of motion for mercury if (id == 0): return v # velocity, dr/dt s = vp.mag(r) return -GM * r * (1.0 + lamb / (s * s)) / (s * s * s) # acceleration, dv/dt