-3

Below is my first serious go at a python 3.13 Class problem. I am self taught. Please don't be put off by the maths. The program is simple, and the solution must be obvious to someone with a bit of coding experience.

A 1 kg particle 'p' orbits earth at sufficient height and velocity to get reasonably circular motion. I started out with all variables being Class variables and whittled these down to 4(G , ME, t (time) and dt (time increment). All else are instance variables. There is one instance of class, called 'p'. At 6th last line: p.move(p.r, p.rAng, p.v, p.vAng), I get the error:

TypeError: Particle.move() takes 4 positional arguments but 5 were given 
import math class Particle: # CLASS VARIABLES and constants G = 6.674e-11 # gravity constant kilogram metre second ME = 5.972e24 # mass earth kg t = 0 # start time dt = 1 # time increment seconds def __init__(self, r, rAng, v, vAng, potE, kinE, totalE): self.r = r self.rAng = rAng self.v = v self.vAng = vAng self.potE = potE self.kinE = kinE self.totalE = totalE def move(r, rAng, v, vAng): a = -Particle.G * Particle.ME / r**2 ax = a * math.cos(rAng) ay = a * math.sin(rAng) vx = v * math.cos(vAng) + ax * Particle.dt vy = v * math.sin(vAng) + ay * Particle.dt v = (vx**2 + vy**2) ** 0.5 vAng = math.atan2(vy, vx) rx = r * math.cos(rAng) + vx * Particle.dt + 0.5 * ax * Particle.dt**2 ry = r * math.sin(rAng) + vy * Particle.dt + 0.5 * ay * Particle.dt**2 r = (rx**2 + ry**2) ** 0.5 rAng = math.atan2(ry, rx) potE = -Particle.G * Particle.ME / r kinE = 0.5 * 1 * v**2 totalE = potE + kinE Particle.t += Particle.dt def result(t, r, rAng, totalE, potE, kinE): print( f"t: {Particle.t: >7,d} s\ r: {r/1000:6.3f} km\ rAng: {(rAng*180/3.14159):6.1f}deg\ totalE: {int(totalE*1.0E-6)}MJ\ potE: {int(potE*1.0E-6)}MJ\ kinE: {int(kinE*1.0E-6)}MJ" ) p = Particle(12748e03, 0, 5592, math.pi / 2, 0, 0, 0) while Particle.t < 13000: p.move(p.r, p.rAng, p.v, p.vAng) if Particle.t % 100 == 0: p.result(Particle.t, p.r, p.rAng, p.totalE, p.potE, p.kinE) else: continue Particle.t += Particle.dt 

There are only 4 arguments. Python is interpreting p.move as a 5th argument. I have tried deleting the references to p in the arguments but that leads to more errors. The math stacks up ok, so it's just an error of referencing between Particle the class and p the instance.

I haven't been able to find anything understandable on the net. What am I doing wrong?

1
  • always put full error message because there are other useful information. Commented Mar 2 at 13:44

1 Answer 1

1

It seems that you have a major misunderstanding how structs and self works.

You are mixing static and non-static functions here; there's no need to 'feed' the values p.r, p.rAng, p.v, p.vAng into the function because the p.move already contains those inside of self.

Also, you both modify Particle.t in every move() call as also in your loop, I assume the modification inside of move() is a mistake.

Further, you are print-ing twice, once inside of result(), which then returns a None, which you print again outside of result().

There's also something fishy going on in the string that result() generates (I assume you wanted to print a multi-line string, not a string that has an increasing number of spaces between each element), but I didn't fix that one.

With that all fixed, this is the code I arrive at:

import math class Particle: # CLASS VARIABLES and constants G = 6.674e-11 # gravity constant kilogram metre second ME = 5.972e24 # mass earth kg t = 0 # start time dt = 1 # time increment seconds def __init__(self, r, rAng, v, vAng, potE, kinE, totalE): self.r = r self.rAng = rAng self.v = v self.vAng = vAng self.potE = potE self.kinE = kinE self.totalE = totalE def move(self): a = -Particle.G * Particle.ME / self.r**2 ax = a * math.cos(self.rAng) ay = a * math.sin(self.rAng) vx = self.v * math.cos(self.vAng) + ax * Particle.dt vy = self.v * math.sin(self.vAng) + ay * Particle.dt self.v = (vx**2 + vy**2) ** 0.5 self.vAng = math.atan2(vy, vx) rx = self.r * math.cos(self.rAng) + vx * Particle.dt + 0.5 * ax * Particle.dt**2 ry = self.r * math.sin(self.rAng) + vy * Particle.dt + 0.5 * ay * Particle.dt**2 self.r = (rx**2 + ry**2) ** 0.5 self.rAng = math.atan2(ry, rx) self.potE = -Particle.G * Particle.ME / self.r self.kinE = 0.5 * 1 * self.v**2 self.totalE = self.potE + self.kinE def result(self): return f"t: {Particle.t: >7,d} s\ r: {self.r/1000:6.3f} km\ rAng: {(self.rAng*180/3.14159):6.1f}deg\ totalE: {int(self.totalE*1.0E-6)}MJ\ potE: {int(self.potE*1.0E-6)}MJ\ kinE: {int(self.kinE*1.0E-6)}MJ" p = Particle(12748e03, 0, 5592, math.pi / 2, 0, 0, 0) while Particle.t < 13000: p.move() if Particle.t % 100 == 0: print(p.result()) else: continue Particle.t += Particle.dt 
t: 0 s r: 12747.998 km rAng: 0.0deg totalE: -15MJ potE: -31MJ kinE: 15MJ 
Sign up to request clarification or add additional context in comments.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.