Beruflich Dokumente
Kultur Dokumente
old-fashioned-light-bulb
Hello!
Here, we are going to simulate some vector field (for instance, an electromagnetic
field) in an N-d space.
class Vector(list):
def __init__(self, *el):
for e in el:
self.append(e)
v = Vector(1, 2, 3)
class Vector(list):
...
def __add__(self, other):
if type(other) is Vector:
assert len(self) == len(other), "Error 0"
r = Vector()
for i in range(len(self)):
r.append(self[i] + other[i])
return r
else:
other = Vector.emptyvec(lens=len(self), n=other)
return self + other
Result:
v1 = Vector(1, 2, 3)
v2 = Vector(2, 57, 23.2)
v1 + v2
>>> [3, 59, 26.2]
We similarly define all the arithmetic operations (the full code of the vector is
at the end). Now, we need a distance function. I could simply make dist (v1, v2) �
but this is not beautiful, so we will redefine the % operator:
class Vector(list):
...
def __mod__(self, other):
return sum((self - other) ** 2) ** 0.5
Result:
v1 = Vector(1, 2, 3)
v2 = Vector(2, 57, 23.2)
v1 % v2
>>> 58.60068258988115
We also need a couple of methods for faster vector generation and beautiful output.
There is nothing tricky here, so here is the entire code of the Vector class.
A Particle
Here, in theory, everything is simple � the point has coordinates, speed, and
acceleration. In addition, it has mass and a set of custom parameters (for example,
for an electromagnetic field, you can set charge).
class Point:
def __init__(self, coords, mass=1.0, q=1.0 speed=None, **properties):
self.coords = coords
if speed is None:
self.speed = Vector(*[0 for i in range(len(coords))])
else:
self.speed = speed
self.acc = Vector(*[0 for i in range(len(coords))])
self.mass = mass
self.__params__ = ["coords", "speed", "acc", "q"] + list(properties.keys())
self.q = q
for prop in properties:
setattr(self, prop, properties[prop])
To move, immobilize and accelerate our point, we will write the following methods:
class Point:
...
def move(self, dt):
self.coords = self.coords + self.speed * dt
def accelerate(self, dt):
self.speed = self.speed + self.acc * dt
def accinc(self, force): # Considering exerted force the point obtains
acceleration
self.acc = self.acc + force / self.mass
def clean_acc(self):
self.acc = self.acc * 0
Interaction Field
We call a field of interaction an object that includes a set of all particles from
space and exerts force on them. We will consider a special case of our universe, so
we will have one custom interaction (of course, this is easy to expand). Declare
the constructor and add a point:
class InteractionField:
def __init__(self, F): # F - is a custom force, F(p1, p2, r), p1, p2 - points,
r - distance inbetween
self.points = []
self.F = F
def append(self, *args, **kwargs):
self.points.append(Point(*args, **kwargs))
Now, the fun part is to declare a function that returns �tension� at that point.
Although this concept refers to electromagnetic interaction, in our case, it is
some abstract vector, along which we will move the point. In this case, we will
have the property of the point q, in the particular case � the charge of the point
(in general � whatever we want, even the vector). So, what is tension at point C?
Something like this:Tension at point C
Tension at point C
Electric intensity in point C is equal to the sum of the forces of all material
points acting on some unit point.
class InteractionField:
...
def intensity(self, coord):
proj = Vector(*[0 for i in range(coord.dim())])
single_point = Point(Vector(), mass=1.0, q=1.0) # That's our "Single
point"
for p in self.points:
if coord % p.coords < 10 ** (-10): # Check whether we compare coord
with a point P where P.coords = coord
continue
d = p.coords % coord
fmod = self.F(single_point, p, d) * (-1)
proj = proj + (coord - p.coords) / d * fmod
return proj
At this point, you can already visualize a vector field, but we will do it at the
end. Now, let's take a step in our interaction.
class InteractionField:
...
def step(self, dt):
self.clean_acc()
for p in self.points:
p.accinc(self.intensity(p.coords) * p.q)
p.accelerate(dt)
p.move(dt)
For each point, we determine the intensity in these coordinates and then determine
the final force on this particle:
Determining final force on the particle
Next, we add ten points (2-dimensional space) with coordinates from 0 to 10 along
each axis. Also, we give each point a charge from -0.25 to 0.25. Then, we run
through a loop and draw points according to their coordinates (and traces):
X, Y = [], []
for i in range(130):
u.step(0.0006)
xd, yd = zip(*u.gather_coords())
X.extend(xd)
Y.extend(yd)
plt.figure(figsize=[8, 8])
plt.scatter(X, Y)
plt.scatter(*zip(*u.gather_coords()), color="orange")
plt.show()
Example of output
In fact, the plot will be completely random because the trajectory of each point is
currently (in 2019) unpredictable.
You should have gotten something like this:First vector field visualization
Now, all coordinates, speeds, etc. are defined in five dimensions. Now, let's model
something:
velmod = 0
velocities = []
for i in range(100):
u.step(0.0005)
velmod = sum([p.speed.mod() for p in u.points]) # Adding sum of modules of
all the velocities
velocities.append(velmod)
plt.plot(velocities)
plt.show()
Sum of all speeds at given time
Well, that was a short instruction on how to simply simulate elementary physical
stuff, thank you for your attention.