BAND.pos[:, 1] = vp.where(BELOW, -1, BAND.pos[:, 1]) # need a more physical way to make 'damped springs' than this! BAND.p = BAND.p * DAMP #band.p[0] = 0 # nail down left endpoint #band.p[-1] = 0 # nail down right endpoint BAND.pos = BAND.pos + BAND.p/M*DT #gravity 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:
PTOTAL = PTOTAL+a.p for a in ATOM: a.p = vp.array(a.p-PTOTAL/(INDEX**2)) # Convert to tuples for faster indexing access. We aren't growing any more of them. SPRINGS = tuple(SPRINGS) ATOM = tuple(ATOM) # Evaluate a couple of constants outside the loop K_DT = K * DT DT_M = DT / M while True: vp.rate(100) for a in ATOM: r = vp.array(a.nearpos) - a.pos rmag = (vp.sqrt(vp.sum(vp.square(r), -1))).reshape(-1, 1) # reshape rmag from row to column a.p += K_DT * vp.sum((1-L/rmag)*r, 0) # sum the forces k*dt*(rmag-L)*(r/rmag) for a in ATOM: a.pos += a.p * DT_M for s in SPRINGS: p1 = s.atom1.pos r12 = s.atom2.pos-p1 direction = r12.norm() s.pos = p1+RS*direction s.axis = (r12.mag-2*RS)*direction
BAND.pos[:, 1] = vp.where(BELOW, -1, BAND.pos[:, 1]) # need a more physical way to make 'damped springs' than this! BAND.p = BAND.p * DAMP #band.p[0] = 0 # nail down left endpoint #band.p[-1] = 0 # nail down right endpoint BAND.pos = BAND.pos + BAND.p / M * DT #gravity 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: