Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > de.alt.folklore.computer > #50746

Historische Programme in Python rekonstruiert

From ram@zedat.fu-berlin.de (Stefan Ram)
Newsgroups de.alt.folklore.computer
Subject Historische Programme in Python rekonstruiert
Date 2025-06-14 20:04 +0000
Organization Stefan Ram
Message-ID <Simulation-20250614210329@ram.dialup.fu-berlin.de> (permalink)

Show all headers | View raw


  Als Schüler wollte ich meinen Computer in der Schule vorführen, das
  war vielleicht 1978 oder 1979. Im Physikunterricht stellte ich eine
  Gas-Simulation in Maschinensprache vor, die zeigt, daß sich eine
  Maxwell-Verteilung ergibt - hatte ich aber nicht selber geschrieben.

  Der Chatbot hat sofort auf meinen ersten Prompt hin das ganze
  Programm in Python rekonstruiert, es lief sofort. Ich mußte ihn
  dann nur darum bitten, daß sich zunächst nur ein Atom bewegt
  und daß die Stöße noch etwas realistischer werden.

  Nun ist die Spannung groß: Wird sich eine Maxwell-Verteilung
  einstellen??

# Maxgas
# -----------------------------------------------------------------------------
# Copyright 2025 Stefan
#
# Written by Stefan Ram on June 14, 2025.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# -----------------------------------------------------------------------------

import tkinter as tk
import random
import math

class Ball:
    def __init__(self, x, y, vx, vy, radius):
        self.x = x
        self.y = y
        self.vx = vx
        self.vy = vy
        self.radius = radius

    def move(self, dt, width, height, balls):
        # Move ball
        self.x += self.vx * dt
        self.y += self.vy * dt

        # Wall collisions
        if self.x - self.radius < 0:
            self.x = self.radius
            self.vx = -self.vx
        elif self.x + self.radius > width:
            self.x = width - self.radius
            self.vx = -self.vx
        if self.y - self.radius < 0:
            self.y = self.radius
            self.vy = -self.vy
        elif self.y + self.radius > height:
            self.y = height - self.radius
            self.vy = -self.vy

        # Ball-ball collisions (realistic elastic)
        for ball in balls:
            if ball is not self:
                dx = self.x - ball.x
                dy = self.y - ball.y
                dist = math.hypot(dx, dy)
                if dist < self.radius + ball.radius:
                    # Normalize collision vector
                    nx = dx / dist if dist > 0 else 1
                    ny = dy / dist if dist > 0 else 0
                    # Relative velocity
                    dvx = self.vx - ball.vx
                    dvy = self.vy - ball.vy
                    # Velocity along collision normal
                    vel_along_normal = dvx * nx + dvy * ny
                    # Only resolve collision if balls are moving towards each other
                    if vel_along_normal < 0:
                        # Impulse (elastic collision, same mass)
                        impulse = vel_along_normal
                        # Apply impulse to both balls
                        self.vx -= impulse * nx
                        self.vy -= impulse * ny
                        ball.vx += impulse * nx
                        ball.vy += impulse * ny
                        # Move balls apart to prevent sticking
                        overlap = (self.radius + ball.radius) - dist
                        self.x += overlap * nx * 0.5
                        self.y += overlap * ny * 0.5
                        ball.x -= overlap * nx * 0.5
                        ball.y -= overlap * ny * 0.5

class App:
    def __init__(self, root):
        self.root = root
        self.width = 900
        self.height = 600
        self.plot_width = int(self.width * 0.2)
        self.sim_width = self.width - self.plot_width
        self.canvas = tk.Canvas(root, width=self.width, height=self.height)
        self.canvas.pack()
        self.balls = []
        self.n_balls = 30
        self.ball_radius = 5

        # Create balls: all at rest except one fast ball
        for i in range(self.n_balls):
            x = random.uniform(self.ball_radius, self.sim_width - self.ball_radius)
            y = random.uniform(self.ball_radius, self.height - self.ball_radius)
            if i == 0:  # Make the first ball fast
                speed = 10
                angle = random.uniform(0, 2 * math.pi)
                vx = speed * math.cos(angle)
                vy = speed * math.sin(angle)
            else:  # All other balls at rest
                vx = 0
                vy = 0
            self.balls.append(Ball(x, y, vx, vy, self.ball_radius))

        self.update()

    def update(self):
        self.canvas.delete("all")

        # Draw divider
        self.canvas.create_line(self.sim_width, 0, self.sim_width, self.height, fill="gray")

        # Draw balls
        for ball in self.balls:
            ball.move(0.5, self.sim_width, self.height, self.balls)
            x1, y1 = ball.x - ball.radius, ball.y - ball.radius
            x2, y2 = ball.x + ball.radius, ball.y + ball.radius
            self.canvas.create_oval(x1, y1, x2, y2, fill="blue")

        # Compute and plot speed distribution
        speeds = [math.hypot(ball.vx, ball.vy) for ball in self.balls]
        max_speed = max(speeds) if speeds else 1
        bin_size = max_speed / 10
        bins = [0] * 10
        for s in speeds:
            idx = min(int(s / bin_size), 9) if bin_size > 0 else 0
            bins[idx] += 1

        # Draw histogram
        hist_height = self.height * 0.8
        max_count = max(bins) if bins else 1
        for i, count in enumerate(bins):
            x1 = self.sim_width + 10 + i * (self.plot_width - 30) / 10
            x2 = x1 + (self.plot_width - 30) / 10 - 2
            bar_height = hist_height * count / max_count
            y1 = self.height - 20 - bar_height
            y2 = self.height - 20
            self.canvas.create_rectangle(x1, y1, x2, y2, fill="red")

        self.root.after(20, self.update)

root = tk.Tk()
app = App(root)
root.mainloop()

Back to de.alt.folklore.computer | Previous | NextNext in thread | Find similar


Thread

Historische Programme in Python rekonstruiert ram@zedat.fu-berlin.de (Stefan Ram) - 2025-06-14 20:04 +0000
  Re: Historische Programme in Python rekonstruiert Sebastian Barthel <naitsabes@freenet.de> - 2025-06-15 12:59 +0000
    Re: Historische Programme in Python rekonstruiert ram@zedat.fu-berlin.de (Stefan Ram) - 2025-06-15 13:18 +0000
  Re: Historische Programme in Python rekonstruiert "F. W." <me@home.invalid> - 2025-06-16 08:10 +0200
    Re: Historische Programme in Python rekonstruiert Gerrit Heitsch <gerrit@laosinh.s.bawue.de> - 2025-06-16 08:52 +0200
      Re: Historische Programme in Python rekonstruiert "F. W." <me@home.invalid> - 2025-06-16 09:49 +0200
        Re: Historische Programme in Python rekonstruiert Gerrit Heitsch <gerrit@laosinh.s.bawue.de> - 2025-06-16 09:54 +0200
          Re: Historische Programme in Python rekonstruiert "F. W." <me@home.invalid> - 2025-06-16 11:38 +0200

csiph-web