def simulate(self): """ Runs the particle simulation. Simulates one time step, dt, of the particle motion. Calculates the force between each pair of particles and updates particles' motion accordingly """ # Main simulation loop for i in range(self.iterations): for a in self.particles: if a.fixed: continue ftot = vector(0,0,0) # total force acting on particle a for b in self.particles: if a.negligible and b.negligible or a==b: continue ab = a.pos - b.pos ftot += ((K_COULOMB * a.charge * b.charge) / mag2(ab)) * norm(ab) a.vel += ftot / a.mass * self.dt # update velocity and position of a a.pos += a.vel * self.dt a.vtk_actor.pos(a.pos) if vp: vp.render(zoom=1.2) vp.camera.Azimuth(0.1) # rotate camera
def reflection(p, pos): n = norm(pos) return np.dot(np.identity(3)-2*n*n[:,np.newaxis], p)
vj = p[j]/mj ri = Ratom rj = Ratom a = mag(vj-vi)**2 if a == 0: continue # exactly same velocities b = 2*np.dot(pos[i]-pos[j], vj-vi) c = mag(pos[i]-pos[j])**2-(ri+rj)**2 d = b**2-4.*a*c if d < 0: continue # something wrong; ignore this rare case deltat = (-b+np.sqrt(d))/(2.*a) # t-deltat is when they made contact pos[i] = pos[i]-(p[i]/mi)*deltat # back up to contact configuration pos[j] = pos[j]-(p[j]/mj)*deltat mtot = mi+mj pcmi = p[i]-ptot*mi/mtot # transform momenta to cm frame pcmj = p[j]-ptot*mj/mtot rrel = norm(pos[j]-pos[i]) pcmi = pcmi-2*np.dot(pcmi,rrel)*rrel # bounce in cm frame pcmj = pcmj-2*np.dot(pcmj,rrel)*rrel p[i] = pcmi+ptot*mi/mtot # transform momenta back to lab frame p[j] = pcmj+ptot*mj/mtot pos[i] = pos[i]+(p[i]/mi)*deltat # move forward deltat in time pos[j] = pos[j]+(p[j]/mj)*deltat # Bounce off the boundary of the torus for j in range(Natoms): poscircle[j] = norm(pos[j])*RingRadius*[1,1,0] outside = np.greater_equal(mag(poscircle-pos),RingThickness-2*Ratom) for k in range(len(outside)): if outside[k]==1 and np.dot(p[k], pos[k]-poscircle[k])>0: p[k] = reflection(p[k],pos[k]-poscircle[k])
# ############################################################ parameters dt = 0.005 # time step ks = 15 # spring stiffness Lrest = 1 # unstretched length of spring Ls = 1 # length of gyroscope shaft M = 1 # mass of gyroscope (massless shaft) R = 0.4 # radius of gyroscope rotor omega = 50 # angular velocity of rotor (rad/s, not shown) gpos = vector(0, 0, 0) # initial position of spring free end # ############################################################ inits top = vector(0, 2, 0) # where top of spring is held precess = vector(0, 0, 0) # initial momentum of center of mass Fgrav = vector(0, -M*9.81, 0) gaxis = vector(0, 0, 1) # initial orientation of gyroscope gaxis = norm(gaxis) I = 1/2*M*R**2 # moment of inertia of gyroscope Lrot = I*omega*gaxis # angular momentum cm = gpos + 0.5*Ls*gaxis # center of mass of shaft # ############################################################ the scene vp = Plotter(verbose=0, axes=0, interactive=0) shaft = vp.cylinder([[0,0,0], Ls*gaxis], r=0.03, c='dg') rotor = vp.cylinder([(Ls-0.55)*gaxis, (Ls-0.45)*gaxis], r=R, c='t') bar = vp.cylinder([Ls*gaxis/2-R*vector(0,1,0), Ls*gaxis/2+R*vector(0,1,0)], r=R/6, c='r') gyro = vp.Assembly([shaft, rotor, bar]) # group actors into a single one spring= vp.helix(top, gpos, r=0.06, thickness=0.01, c='gray') vp.box(top, length=0.2, width=0.02, height=0.2, c='gray') vp.box(pos=(0,.5,0), length=2.2, width=3, height=2.2, c='gray', wire=1, alpha=.2)
vp = Plotter(axes=0) s = vp.load('data/290.vtk', wire=1) vp.actors.append(s.clone(c='red 1.0', wire=0)) c = centerOfMass(s) vp.point(c) Niter = 4 for t in range(Niter): print('iteration', t) coords = s.coordinates() normals = s.normals() aves = averageSize(s) * 1.5 for i in range(s.N()): n = normals[i] p = coords[i] q = norm(p - c) * aves + c dp = mag(q - p) alongn = n * dp alongr = q - p # bias normal newp = p + (alongn + alongr) / 2 / Niter s.point(i, newp) #refresh actor, so polydata normals are recalculated s = s.clone(wire=1, alpha=.1) vp.actors.append(s) vp.show()
vp = Plotter(verbose=0, axes=0) s = vp.load('data/shapes/cow.vtk', alpha=0.3)#.subdivide() pts1, pts2, vals, cols = [], [], [], [] for i, p in enumerate(s.coordinates()): pts = s.closestPoint(p, N=12) # find the N closest points to p sph = fitSphere(pts) # find the fitting sphere if sph is None: continue value = sph.info['radius']*10 color = colorMap(value, name='jet') # map value to a RGB color n = norm(p-sph.info['center']) # unit vector from sphere center to p vals.append(value) cols.append(color) pts1.append(p) pts2.append(p+n/8) if not i%500: print(i,'/',s.N()) vp.points(pts1, c=cols) vp.addScalarBar() vp.lines(pts1, pts2, c='black 0.2') vp.histogram(vals, title='values', bins=20, vrange=[0,1]) vp.show()
def loop(*event ): ################################################################## global bob_x, x_dot, bob_y, y_dot # Compute the midpoint variables bob_x_m = list(map((lambda x, dx: x + Dt2 * dx), bob_x, x_dot)) # midpoint variables bob_y_m = list(map((lambda y, dy: y + Dt2 * dy), bob_y, y_dot)) for k in range(1, N + 1): factor = fctr(dij[k]) x_dot_m[k] = x_dot[k] - Dt2 * (Ks * (bob_x[k] - bob_x[k - 1]) * factor + gamma * x_dot[k]) y_dot_m[k] = y_dot[k] - Dt2 * (Ks * (bob_y[k] - bob_y[k - 1]) * factor + gamma * y_dot[k] + g) for k in range(1, N): factor = fctr(dij[k + 1]) x_dot_m[k] -= Dt2 * Ks * (bob_x[k] - bob_x[k + 1]) * factor y_dot_m[k] -= Dt2 * Ks * (bob_y[k] - bob_y[k + 1]) * factor # Compute the full step variables bob_x = list(map((lambda x, dx: x + Dt * dx), bob_x, x_dot_m)) bob_y = list(map((lambda y, dy: y + Dt * dy), bob_y, y_dot_m)) for k in range(1, N + 1): dij[k] = mag([bob_x[k] - bob_x[k - 1], bob_y[k] - bob_y[k - 1]]) dij_m[k] = mag( [bob_x_m[k] - bob_x_m[k - 1], bob_y_m[k] - bob_y_m[k - 1]]) factor = fctr(dij_m[k]) x_dot[k] -= Dt * (Ks * (bob_x_m[k] - bob_x_m[k - 1]) * factor + gamma * x_dot_m[k]) y_dot[k] -= Dt * (Ks * (bob_y_m[k] - bob_y_m[k - 1]) * factor + gamma * y_dot_m[k] + g) for k in range(1, N): factor = fctr(dij_m[k + 1]) x_dot[k] -= Dt * Ks * (bob_x_m[k] - bob_x_m[k + 1]) * factor y_dot[k] -= Dt * Ks * (bob_y_m[k] - bob_y_m[k + 1]) * factor # Check to see if they are colliding for i in range(1, N): for j in range(i + 1, N + 1): dist2 = (bob_x[i] - bob_x[j])**2 + (bob_y[i] - bob_y[j])**2 if dist2 < DiaSq: # are colliding Ddist = np.sqrt(dist2) - 2 * R tau = norm(vector(bob_x[j] - bob_x[i], bob_y[j] - bob_y[i])) DR = Ddist / 2 * tau bob_x[i] += DR[0] # DR.x bob_y[i] += DR[1] # DR.y bob_x[j] -= DR[0] # DR.x bob_y[j] -= DR[1] # DR.y Vji = vector(x_dot[j] - x_dot[i], y_dot[j] - y_dot[i]) DV = np.dot(Vji, tau) * tau x_dot[i] += DV[0] # DV.x y_dot[i] += DV[1] # DV.y x_dot[j] -= DV[0] # DV.x y_dot[j] -= DV[1] # DV.y # Update the loations of the bobs and the stretching of the springs for k in range(1, N + 1): bob[k].pos([bob_x[k], bob_y[k], 0]) link[k - 1].stretch(bob[k - 1].pos(), bob[k].pos()) vp.render(resetcam=True) # show() would cause exiting the loop vp.camera.Azimuth(0.1) # move camera a bit
from vtkplotter import Plotter, colorMap, norm from vtkplotter.analysis import fitSphere vp = Plotter(verbose=0, axes=0) s = vp.load('data/shapes/cow.vtk', alpha=0.3) #.subdivide() pts1, pts2, vals, cols = [], [], [], [] for i, p in enumerate(s.coordinates()): pts = s.closestPoint(p, N=12) # find the N closest points to p sph = fitSphere(pts) # find the fitting sphere if sph is None: continue value = sph.radius * 10 color = colorMap(value, name='jet') # map value to a RGB color n = norm(p - sph.center) # unit vector from sphere center to p vals.append(value) cols.append(color) pts1.append(p) pts2.append(p + n / 8) if not i % 500: print(i, '/', s.N()) vp.points(pts1, c=cols) vp.addScalarBar() vp.lines(pts1, pts2, c='black 0.2') vp.histogram(vals, title='values', bins=20, vrange=[0, 1]) vp.show()
gamma * x_dot_m[k]) y_dot[k] -= Dt * (Ks * (bob_y_m[k] - bob_y_m[k - 1]) * factor + gamma * y_dot_m[k] + g) for k in range(1, N): factor = fctr(dij_m[k + 1]) x_dot[k] -= Dt * Ks * (bob_x_m[k] - bob_x_m[k + 1]) * factor y_dot[k] -= Dt * Ks * (bob_y_m[k] - bob_y_m[k + 1]) * factor # Check to see if they are colliding for i in range(1, N): for j in range(i + 1, N + 1): dist2 = (bob_x[i] - bob_x[j])**2 + (bob_y[i] - bob_y[j])**2 if dist2 < DiaSq: # are colliding Ddist = np.sqrt(dist2) - 2 * R tau = norm(vector(bob_x[j] - bob_x[i], bob_y[j] - bob_y[i])) DR = Ddist / 2 * tau bob_x[i] += DR[0] # DR.x bob_y[i] += DR[1] # DR.y bob_x[j] -= DR[0] # DR.x bob_y[j] -= DR[1] # DR.y Vji = vector(x_dot[j] - x_dot[i], y_dot[j] - y_dot[i]) DV = np.dot(Vji, tau) * tau x_dot[i] += DV[0] # DV.x y_dot[i] += DV[1] # DV.y x_dot[j] -= DV[0] # DV.x y_dot[j] -= DV[1] # DV.y # Update the loations of the bobs and the stretching of the springs for k in range(1, N + 1): bob[k].pos([bob_x[k], bob_y[k], 0])