Example #1
0
    def setQuaternion(self, Quaternion):
        """Set the orientation of the body in world coordinates (the display object is oriented to match)."""
        odelib.BaseBody.setQuaternion(self, Quaternion)

        # now set the orientation of the display frame
        # Rotating a point is q * (0,v) * q-1
        # q-1 is w, -x, -y, -z assuming that q is a unit quaternion
        w1, x1, y1, z1 = Quaternion
        v1 = visual.vector(x1, y1, z1)
        w3 = w1
        v3 = -v1

        # First do the axis vector
        w2 = 0.0
        v2 = visual.vector((1.0, 0.0, 0.0))

        # This code is equivalent to a quaternion multiply: qR = q1 * q2 * q3
        w12 = (w1 * w2) - visual.dot(v1, v2)
        v12 = (w1 * v2) + (w2 * v1) + visual.cross(v1, v2)
        wR = (w12 * w3) - visual.dot(v12, v3)
        vR = (w12 * v3) + (w3 * v12) + visual.cross(v12, v3)

        self._myFrame.axis = vR

        # Do it again for the up vector
        w2 = 0.0
        v2 = visual.vector((0.0, 1.0, 0.0))

        # This code is equivalent to a quaternion multiply: qR = q1 * q2 * q3
        w12 = (w1 * w2) - visual.dot(v1, v2)
        v12 = (w1 * v2) + (w2 * v1) + visual.cross(v1, v2)
        wR = (w12 * w3) - visual.dot(v12, v3)
        vR = (w12 * v3) + (w3 * v12) + visual.cross(v12, v3)

        self._myFrame.up = vR
Example #2
0
    def setQuaternion(self, Quaternion):
        """Set the orientation of the body in world coordinates (the display object is oriented to match)."""
        odelib.BaseBody.setQuaternion(self, Quaternion)

        # now set the orientation of the display frame
        # Rotating a point is q * (0,v) * q-1
        # q-1 is w, -x, -y, -z assuming that q is a unit quaternion
        w1, x1, y1, z1 = Quaternion
        v1 = visual.vector(x1, y1, z1)
        w3 = w1
        v3 = -v1

        # First do the axis vector
        w2 = 0.0
        v2 = visual.vector((1.0, 0.0, 0.0))

        # This code is equivalent to a quaternion multiply: qR = q1 * q2 * q3
        w12 = (w1 * w2) - visual.dot(v1, v2)
        v12 = (w1 * v2) + (w2 * v1) + visual.cross(v1, v2)
        wR = (w12 * w3) - visual.dot(v12, v3)
        vR = (w12 * v3) + (w3 * v12) + visual.cross(v12, v3)

        self._myFrame.axis = vR

        # Do it again for the up vector
        w2 = 0.0
        v2 = visual.vector((0.0, 1.0, 0.0))

        # This code is equivalent to a quaternion multiply: qR = q1 * q2 * q3
        w12 = (w1 * w2) - visual.dot(v1, v2)
        v12 = (w1 * v2) + (w2 * v1) + visual.cross(v1, v2)
        wR = (w12 * w3) - visual.dot(v12, v3)
        vR = (w12 * v3) + (w3 * v12) + visual.cross(v12, v3)

        self._myFrame.up = vR
Example #3
0
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))
Example #4
0
    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
Example #5
0
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))
            elif propulsion['type'] == HORIZONTAL:
                ortho_vector = rocket_pos / rocket_pos.mag
                direction = vector(ortho_vector.y, -ortho_vector.x)
            else:
                raise SystemError

            force = propulsion['magnitude'] * direction
            f_propulsion += force
        else:
            if not notified and time > propulsion['from']:
                print("PRopulsion stopped")
                notified = True
                # plt.pause(0.02)
    try:
        theta = acos(
            dot(rocket_vel, rocket_pos) / rocket_vel.mag / rocket_pos.mag) / pi
    except:
        pass

    if time > TIME_SKIP:
        print(
            "t= {0}, v={1:.0f}, h={2:.2f}, theta={3:.2f}, g={4:.2f}, E={5:1.1e}"
            .format(time, rocket_vel.mag - 241,
                    rocket_pos.mag - RADIUS_OF_MARS, theta, f_gravity.mag,
                    get_total_energy()))

    if rocket_pos.mag < RADIUS_OF_MARS:
        print("Rocket landed on ground with velocity: {0:.0f}".format(
            rocket_vel.mag))
        print("Total energy used: {}".format(get_total_energy()))
        with open("energy-used.tmp", "a") as f:
Example #7
0
        if Q_PY:
            GEARING = 4
        else:
            GEARING = 1
        CAM_DIST = CAM_DIST + (MOUSE_CHANGE.x + MOUSE_CHANGE.y + MOUSE_CHANGE.z)*GEARING
        if CAM_DIST <= 0:
            CAM_DIST = 0.001  # allow only positive
        LIMIT = SCENE_SIZE*2
        if CAM_DIST > LIMIT:
            CAM_DIST = LIMIT # limit size
        redraw_lines()
        CAM_BOX.pos = (CAM_DIST, 0, 0)
        CAM_LAB.pos = (CAM_DIST, 0, 0)
        FWR_ARROW.pos = (CAM_DIST, 0, 0)
        MOUSE_ARROW.pos = (CAM_DIST, 0, 0)
        MOUSE_LAB.pos = -RAY*(CAM_DIST/vs.dot(RAY, (1, 0, 0))) + (CAM_DIST, 0, 0)
        RANGE_X = CAM_DIST * vs.tan(FOV/2.0)
        CENT_PLANE.width = RANGE_X*2
        CENT_PLANE.height = RANGE_X*4.0/3
        redraw_tri()  # redraw the camera triangle
        RANGE_LAB.pos = (0, 0, -RANGE_X)
        MODE_LAB.SetLabel('scene.range:\n' + format(RANGE_X, "9.3"))
        if not Q_PY:
            VSS.range = RANGE_X

    elif MODE == 'v': # demonstrate altering scene.fov
        CAM_DIST = CAM_DIST + (MOUSE_CHANGE.x + MOUSE_CHANGE.y + MOUSE_CHANGE.z)*4
        if CAM_DIST <= 0:
            CAM_DIST = 0.001  # allow only positive
        RAY = (MOUSE_LAB.pos - (CAM_DIST, 0, 0)).norm()
        redraw_lines()
Example #8
0
def proj(a,b):
    '''Projects the vector a along the direction of b.'''
       
    return vector(dot(a, norm(b)) * norm(b))
 def dot(self, other):
     return dot(self.v, other.v)
Example #10
0
       mode_lab.SetLabel('scene.forward:\n' + str2( - cam_frame.axis))
       if not qPy:  vss.forward = - cam_frame.axis                
       
    elif mode == 'r': # demonstrate altering scene.range.  Alters size of camera triangle.
        if qPy: gearing = 4
        else: gearing = 1 
        cam_dist = cam_dist + (mouse_change.x + mouse_change.y + mouse_change.z)*gearing
        if cam_dist <= 0:  cam_dist = 0.001  # allow only positive
        limit = scene_size*2
        if cam_dist > limit: cam_dist = limit # limit size 
        reDrawLines()
        cam_box.pos = (cam_dist,0,0) 
        cam_lab.pos = (cam_dist,0,0) 
        fwd_arrow.pos = (cam_dist,0,0)
        mouse_arrow.pos = (cam_dist,0,0)
        mouse_lab.pos = -ray*(cam_dist/vs.dot(ray,(1,0,0))) + (cam_dist,0,0)
        range_x = cam_dist * vs.tan(fov/2.0)
        cent_plane.width = range_x*2
        cent_plane.height = range_x*4.0/3
        reDrawTri()  # redraw the camera triangle
        range_lab.pos= (0,0,-range_x)
        mode_lab.SetLabel( 'scene.range:\n' + format( range_x, "9.3")) 
        if not qPy:  vss.range = range_x

    elif mode == 'v': # demonstrate altering scene.fov
        cam_dist = cam_dist + (mouse_change.x + mouse_change.y + mouse_change.z)*4
        if cam_dist <= 0:  cam_dist = 0.001  # allow only positive
        ray = (mouse_lab.pos - (cam_dist, 0,0)).norm()  
        reDrawLines()
        cam_box.pos = (cam_dist,0,0) 
        cam_lab.pos = (cam_dist,0,0) 
Example #11
0
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))
Example #12
0
        if not qPy: vss.forward = -cam_frame.axis

    elif mode == 'r':  # demonstrate altering scene.range.  Alters size of camera triangle.
        if qPy: gearing = 4
        else: gearing = 1
        cam_dist = cam_dist + (mouse_change.x + mouse_change.y +
                               mouse_change.z) * gearing
        if cam_dist <= 0: cam_dist = 0.001  # allow only positive
        limit = scene_size * 2
        if cam_dist > limit: cam_dist = limit  # limit size
        reDrawLines()
        cam_box.pos = (cam_dist, 0, 0)
        cam_lab.pos = (cam_dist, 0, 0)
        fwd_arrow.pos = (cam_dist, 0, 0)
        mouse_arrow.pos = (cam_dist, 0, 0)
        mouse_lab.pos = -ray * (cam_dist / vs.dot(ray, (1, 0, 0))) + (cam_dist,
                                                                      0, 0)
        range_x = cam_dist * vs.tan(fov / 2.0)
        cent_plane.width = range_x * 2
        cent_plane.height = range_x * 4.0 / 3
        reDrawTri()  # redraw the camera triangle
        range_lab.pos = (0, 0, -range_x)
        mode_lab.SetLabel('scene.range:\n' + format(range_x, "9.3"))
        if not qPy: vss.range = range_x

    elif mode == 'v':  # demonstrate altering scene.fov
        cam_dist = cam_dist + (mouse_change.x + mouse_change.y +
                               mouse_change.z) * 4
        if cam_dist <= 0: cam_dist = 0.001  # allow only positive
        ray = (mouse_lab.pos - (cam_dist, 0, 0)).norm()
        reDrawLines()
Example #13
0
# For planet data
ptf=int(raw_input("Which planet are you interested in (Mercury: 0,..., Pluto: 7) ")) # Planet to find (0: Mercury,..., 8 for Pluto)
times=float(raw_input("How many data points do you want for the planet: ")) # Number of times data are taken

timc=0 # Counter

year=[] # List of orbital periods
per=[] # List of perihelion distances
aph=[] # List of aphelion distances

pos0=v.vector(planet[ptf].pos) # Initial position of chosen planet

pe1=v.mag(pos0) # Variable for perihilion distance
ap1=v.mag(pos0) # Variable for aphilion distance
dirc0=v.dot(pos0,pos0) # Dot product (changes sign when angle crosses pi/2: keeping track of revolutions)

t_init=0 # Initial time for starting calculation (when the planet is perpendicular to initial position vector for the first time)


# For moon data
timoon=float(raw_input("How many data points do you want for the moon: ")) # Number of times moon data are taken
#mtf=int(raw_input("Which moon are you interested in (Moon: 0, Deimos: 1) ")) # Moon to find
mtf=9 # Moon to find: only one anyway
timcm=0 # Counter
month=[] # List of lunar orbital periods
posm0=planet[mtf].pos-planet[planet[mtf].mom].pos # Initial position of moon relative to its planet
dircm0=v.dot(posm0,posm0) # Dot product
tm_init=0 # Initial time for taking moon data
peg=[] # List of prigee distances
apg=[] # List of apogee distance
Example #14
0
def proj(a, b):
    '''Projects the vector a along the direction of b.'''

    return vector(dot(a, norm(b)) * norm(b))
Example #15
0
def Simulation():

    config.Atoms = []  # spheres
    p = []  # momentums (vectors)
    apos = []  # positions (vectors)
    ampl = 0  #амплитуда движения
    period = 5
    k = 1.4E-23  # Boltzmann constant
    R = 8.3
    dt = 1E-5
    time = 0

    def checkCollisions(Natoms, Ratom):
        hitlist = []
        r2 = 2 * Ratom
        for i in range(Natoms):
            for j in range(i):
                dr = apos[i] - apos[j]
                if dr.mag < r2:
                    hitlist.append([i, j])
        return hitlist

    def speed(time, piston_mode, period, ampl, temp):
        if (piston_mode == 0):
            return 0
        if (piston_mode == 1):
            return ampl / 10 * 3 * sin(time / period * 2 * pi) * sqrt(
                3 * config.mass * k * temp) / (5 * config.mass) / period * 100
        if (piston_mode == 2):
            if (time % period < period // 2):
                return 1.5 * ampl / 10 * sqrt(3 * config.mass * k * temp) / (
                    5 * config.mass) / period * 100
            else:
                return -1.5 * ampl / 10 * sqrt(3 * config.mass * k * temp) / (
                    5 * config.mass) / period * 100
        if (piston_mode == 3):
            if (time % period < period // 5):
                return 5 * ampl / 10 * sqrt(3 * config.mass * k * temp) / (
                    5 * config.mass) / period * 100
            else:
                return -5 / 4 * ampl / 10 * sqrt(
                    3 * config.mass * k * temp) / (5 *
                                                   config.mass) / period * 100
        if (piston_mode == 4):
            if (time % period < 4 * period // 5):
                return 5 / 4 * ampl / 10 * sqrt(3 * config.mass * k * temp) / (
                    5 * config.mass) / period * 100
            else:
                return -5 * ampl / 10 * sqrt(3 * config.mass * k * temp) / (
                    5 * config.mass) / period * 100

    width, height = config.w.win.GetSize()

    offset = config.w.dheight
    deltav = 100  # histogram bar width

    disp = display(
        window=config.w,
        x=offset,
        y=offset,
        forward=vector(0, -0.05, -1),
        range=1,  # userspin = False,
        width=width / 3,
        height=height)

    g1 = gdisplay(window=config.w,
                  x=width / 3 + 2 * offset,
                  y=2 * offset,
                  background=color.white,
                  xtitle='t',
                  ytitle='v',
                  foreground=color.black,
                  width=width / 3,
                  height=height / 2 - 2 * offset)

    g2 = gdisplay(window=config.w,
                  x=width / 3 + 2 * offset,
                  y=height / 2 + offset,
                  background=color.white,
                  foreground=color.black,
                  width=width / 3,
                  height=height / 2 - 2 * offset)

    # adding empty dots to draw axis
    graph_average_speed = gcurve(gdisplay=g1, color=color.white)
    graph_average_speed.plot(pos=(3000, 1500))
    graph_temp = gcurve(gdisplay=g2, color=color.white)
    graph_temp.plot(pos=(3000, config.Natoms * deltav / 1000))

    speed_text = wx.StaticText(config.w.panel,
                               pos=(width / 3 + 2 * offset, offset),
                               label="Средняя скорость")
    graph_text = wx.StaticText(config.w.panel,
                               pos=(width / 3 + 2 * offset, height / 2),
                               label="")

    L = 1  # container is a cube L on a side
    d = L / 2 + config.Ratom  # half of cylinder's height
    topborder = d
    gray = color.gray(0.7)  # color of edges of container

    # cylinder drawing
    cylindertop = cylinder(pos=(0, d - 0.001, 0), axis=(0, 0.005, 0), radius=d)
    ringtop = ring(pos=(0, d, 0), axis=(0, -d, 0), radius=d, thickness=0.005)
    ringbottom = ring(pos=(0, -d, 0),
                      axis=(0, -d, 0),
                      radius=d,
                      thickness=0.005)
    body = cylinder(pos=(0, -d, 0), axis=(0, 2 * d, 0), radius=d, opacity=0.2)

    # body_tmp = cylinder(pos = (0, d, 0), axis = (0, 2 * d, 0), radius = d + 0.1, color = (0, 0, 0))
    # ceil = box(pos = (0, d, 0), length = 5, height = 0.005, width = 5, color = (0, 0, 0))
    # floor = box(pos = (0, -d, 0), length = 100, height = 0.005, width = 100, color = (0, 0, 0))
    # left = box(pos = (d + 0.005, 0, 0), axis = (0, 1, 0), length = 100, height = 0.005, width = 100, color = (0, 0, 0))
    # right = box(pos = (-d - 0.005, 0, 0), axis = (0, 1, 0), length = 100, height = 0.005, width = 100, color = (0, 0, 0))

    # uniform particle distribution
    for i in range(config.Natoms):
        qq = 2 * pi * random.random()

        x = sqrt(random.random()) * L * cos(qq) / 2
        y = L * random.random() - L / 2
        z = sqrt(random.random()) * L * sin(qq) / 2

        if i == 0:
            # particle with a trace
            config.Atoms.append(
                sphere(pos=vector(x, y, z),
                       radius=config.Ratom,
                       color=color.cyan,
                       make_trail=False,
                       retain=100,
                       trail_radius=0.3 * config.Ratom))
        else:
            config.Atoms.append(
                sphere(pos=vector(x, y, z), radius=config.Ratom, color=gray))

        apos.append(vector(x, y, z))

    # waiting to start, adjusting everything according to changing variables
    """WAITING TO START"""
    last_Natoms = config.Natoms
    last_Ratom = config.Ratom
    while config.start == 0:
        if config.menu_switch == 0:
            disp.delete()
            g1.display.delete()
            g2.display.delete()

            graph_text.Destroy()
            speed_text.Destroy()
            return

        if config.Natoms > last_Natoms:
            for i in range(config.Natoms - last_Natoms):
                qq = 2 * pi * random.random()
                x = sqrt(random.random()) * L * cos(qq) / 2
                y = L * random.random() - L / 2
                z = sqrt(random.random()) * L * sin(qq) / 2

                if last_Natoms == 0:
                    # particle with a trace
                    config.Atoms.append(
                        sphere(pos=vector(x, y, z),
                               radius=config.Ratom,
                               color=color.cyan,
                               make_trail=False,
                               retain=100,
                               trail_radius=0.3 * config.Ratom))
                else:
                    config.Atoms.append(
                        sphere(pos=vector(x, y, z),
                               radius=config.Ratom,
                               color=gray))
                apos.append(vector(x, y, z))
            last_Natoms = config.Natoms

        elif config.Natoms < last_Natoms:
            for i in range(last_Natoms - config.Natoms):
                config.Atoms.pop().visible = False
                apos.pop()
            last_Natoms = config.Natoms

        if last_Ratom != config.Ratom:
            for i in range(last_Natoms):
                config.Atoms[i].radius = config.Ratom
            last_Ratom = config.Ratom

        if config.model == 0:
            if config.piston_mode >= 1:
                graph_text.SetLabel("Температура")
            else:
                graph_text.SetLabel("Распределение скоростей частиц")
        sleep(0.1)

    # freezed all variables, ready to start
    last_T = config.T
    last_ampl = config.ampl
    last_period = config.period
    last_piston_mode = config.piston_mode
    last_model = config.model

    pavg = sqrt(3 * config.mass * k *
                last_T)  # average kinetic energy p**2/(2config.mass) = (3/2)kT

    for i in range(last_Natoms):
        theta = pi * random.random()
        phi = 2 * pi * random.random()

        px = pavg * sin(theta) * cos(phi)
        py = pavg * sin(theta) * sin(phi)
        pz = pavg * cos(theta)

        p.append(vector(px, py, pz))

    if last_model == 1:
        disp.delete()
        unavail = wx.StaticText(
            config.w.panel,
            style=wx.ALIGN_CENTRE_HORIZONTAL,
            label="Отображение модели недоступно в режиме статистики",
            pos=(offset, height / 2 - offset))
        unavail.Wrap(width / 3)
        last_period = last_period / 10
        last_piston_mode += 1
        graph_text.SetLabel("Температура")
    """ DRAW GRAPHS """

    g1.display.delete()
    g2.display.delete()

    if last_piston_mode == 0:
        g1 = gdisplay(window=config.w,
                      x=width / 3 + 2 * offset,
                      y=2 * offset,
                      background=color.white,
                      xtitle='t',
                      ytitle='v',
                      foreground=color.black,
                      width=width / 3,
                      height=height / 2 - 2 * offset,
                      ymin=0.7 * pavg / config.mass,
                      ymax=1.3 * pavg / config.mass)

        g2 = gdisplay(window=config.w,
                      x=width / 3 + 2 * offset,
                      y=height / 2 + offset,
                      background=color.white,
                      foreground=color.black,
                      xtitle='v',
                      ytitle='Frequency',
                      width=width / 3,
                      height=height / 2 - 2 * offset,
                      xmax=3000 / 300 * last_T,
                      ymax=last_Natoms * deltav / 1000)

    else:
        g1 = gdisplay(window=config.w,
                      x=width / 3 + 2 * offset,
                      y=2 * offset,
                      background=color.white,
                      xtitle='t',
                      ytitle='v',
                      foreground=color.black,
                      width=width / 3,
                      height=height / 2 - 2 * offset)

        g2 = gdisplay(window=config.w,
                      x=width / 3 + 2 * offset,
                      y=height / 2 + offset,
                      background=color.white,
                      xtitle='t',
                      ytitle='T',
                      foreground=color.black,
                      width=width / 3,
                      height=height / 2 - 2 * offset)

    graph_average_speed = gcurve(gdisplay=g1, color=color.black)

    if last_piston_mode:
        graph_temp = gcurve(gdisplay=g2, color=color.black)
    else:
        theory_speed = gcurve(gdisplay=g2, color=color.black)
        dv = 10
        for v in range(0, int(3000 / 300 * last_T), dv):
            theory_speed.plot(pos=(v, (deltav / dv) * last_Natoms * 4 * pi *
                                   ((config.mass /
                                     (2 * pi * k * last_T))**1.5) *
                                   exp(-0.5 * config.mass * (v**2) /
                                       (k * last_T)) * (v**2) * dv))

        hist_speed = ghistogram(gdisplay=g2,
                                bins=arange(0, int(3000 / 300 * last_T), 100),
                                color=color.red,
                                accumulate=True,
                                average=True)

        speed_data = []  # histogram data
        for i in range(last_Natoms):
            speed_data.append(pavg / config.mass)
            # speed_data.append(0)
    """ MAIN CYCLE """
    while config.start:

        while config.pause:
            sleep(0.1)

        rate(100)

        sp = speed(time, last_piston_mode, last_period, last_ampl, 300)
        cylindertop.pos.y -= sp * dt
        time += 1

        for i in range(last_Natoms):
            config.Atoms[i].pos = apos[i] = apos[i] + (p[i] / config.mass) * dt

            if last_piston_mode == 0:
                speed_data[i] = mag(p[i]) / config.mass

        total_momentum = 0
        v_sum = 0
        for i in range(last_Natoms):
            total_momentum += mag2(p[i])
            v_sum += sqrt(mag2(p[i])) / config.mass

        graph_average_speed.plot(pos=(time, v_sum / last_Natoms))

        if last_piston_mode:
            graph_temp.plot(pos=(time, total_momentum / (3 * k * config.mass) /
                                 last_Natoms))
        else:
            hist_speed.plot(data=speed_data)

        hitlist = checkCollisions(last_Natoms, last_Ratom)

        for ij in hitlist:

            i = ij[0]
            j = ij[1]
            ptot = p[i] + p[j]
            posi = apos[i]
            posj = apos[j]
            vi = p[i] / config.mass
            vj = p[j] / config.mass
            vrel = vj - vi
            a = vrel.mag2
            if a == 0:  # exactly same velocities
                continue
            rrel = posi - posj
            if rrel.mag > config.Ratom:  # one atom went all the way through another
                continue

            # theta is the angle between vrel and rrel:
            dx = dot(rrel, norm(vrel))  # rrel.mag*cos(theta)
            dy = cross(rrel, norm(vrel)).mag  # rrel.mag*sin(theta)
            # alpha is the angle of the triangle composed of rrel, path of atom j, and a line
            #   from the center of atom i to the center of atom j where atome j hits atom i:
            alpha = asin(dy / (2 * config.Ratom))
            d = (2 * config.Ratom) * cos(
                alpha
            ) - dx  # distance traveled into the atom from first contact
            deltat = d / vrel.mag  # time spent moving from first contact to position inside atom

            posi = posi - vi * deltat  # back up to contact configuration
            posj = posj - vj * deltat
            mtot = 2 * config.mass
            pcmi = p[
                i] - ptot * config.mass / mtot  # transform momenta to cm frame
            pcmj = p[j] - ptot * config.mass / mtot
            rrel = norm(rrel)
            pcmi = pcmi - 2 * pcmi.dot(rrel) * rrel  # bounce in cm frame
            pcmj = pcmj - 2 * pcmj.dot(rrel) * rrel
            p[i] = pcmi + ptot * config.mass / mtot  # transform momenta back to lab frame
            p[j] = pcmj + ptot * config.mass / mtot
            apos[i] = posi + (
                p[i] / config.mass) * deltat  # move forward deltat in time
            apos[j] = posj + (p[j] / config.mass) * deltat

        # collisions with walls
        for i in range(last_Natoms):

            # проекция радиус-вектора на плоскость
            loc = vector(apos[i])
            loc.y = 0

            # вылет за боковую стенку (цилиндр радиуса L / 2 + config.Ratom)
            if (mag(loc) > L / 2 + 0.01 - last_Ratom +
                    sqrt(p[i].x**2 + p[i].z**2) / config.mass * dt):

                # проекция импульса на плоскость
                proj_p = vector(p[i])
                proj_p.y = 0

                loc = norm(loc)
                # скалярное произведение нормированного радиус-вектора на импульс (все в проекции на плоскость)
                dotlp = dot(loc, proj_p)

                if dotlp > 0:
                    p[i] -= 2 * dotlp * loc
                # dotlp < 0 - атом улетает от стенки
                # dotlp = 0 - атом летит вдоль стенки

            loc = apos[i]

            # вылет за торцы
            if loc.y + p[i].y / config.mass * dt < -L / 2 - 0.01 + last_Ratom:
                p[i].y = abs(p[i].y)

            if loc.y + p[
                    i].y / config.mass * dt > cylindertop.pos.y - last_Ratom:
                v_otn = p[i].y / config.mass + sp
                if v_otn > 0:
                    p[i].y = (-v_otn - sp) * config.mass

        # type here

    if last_model == 0:
        disp.delete()
    else:
        unavail.Destroy()

    g1.display.delete()
    g2.display.delete()

    graph_text.Destroy()
    speed_text.Destroy()
Example #16
0
 def dot(self, other):
     return dot(self.v, other.v)