Simulating diffusing molecules

I am trying to simlate some molecules moving in Solar 2d. All I wanted was a number of independent molecules which bounce off each other elastically and against the walls of the container changing direction as they collide but keeping the same velocity until the simulation ends.

the simulation creates a boundary box (static, bounce = 1, friction = 0) and then creates molecules with a random start location inside the box with properties dynamic, bounce = 1 and friction = 0 . I give all the objects the same linear velocity (100,100).

My assumptions from the documentation is that those particles would bounce off each other randomly until the simulation stops.

What I get is particles that start of perfectly elastic but gradually (one by one ) the particles become horizontal bounces along the top of hte box and gradually stop.

I cant see what is wrong. Any ideas?

for interest here is my code:

– Create “walls” around screen
local cellwall = display.newLine( mainGroup, 60,80, 260,80, 260,280, 60,280, 60,80 )
physics.addBody( cellwall, “static”, { bounce=1, friction=0.0 })–filter=borderCollisionFilter } )

local Membrane = display.newLine( mainGroup,60,180,260,180 )
physics.addBody( Membrane, “static”, { bounce=1, friction=0.0 })–filter=borderCollisionFilter } )

– Create blue molecules in top

for b = 1,4 do
local blueMolecule = display.newImageRect(“sodium.png”,moleculeSize,moleculeSize)
repeat
xpos = math.random(65,255)
ypos = math.random(85,155)
until xpos~= ypos
blueMolecule.x = xpos
blueMolecule.y = ypos
physics.addBody( blueMolecule, “dynamic”, { bounce=1.0, friction=0, radius=1}) --filter=blueCollisionFilter } )
blueMolecule.isFixedRotation = false
blueMolecule:
blueMolecule:setLinearVelocity(100,100)
end

Sorry if this isnt a complete solution your problem but you definitely should not be relying on setting velocity for this as it is sure to result in erratic behaviour. Velocity is a result of forces so if you want to create a realistic simulation, you’d have to rely on applying a force or impulse to your bodies.

If using a force makes them go too fast for your requirement, you can keep checking their resultant velocity and cap it if it exceeds a threshold but i really won’t recommend applying a velocity as that’s just an override for what should really be achieved through the use of force or impulse

Edit: further it seems that you’re only setting the linear velocity once for each object so i suspect that the engine might allow the velocity to diminish/increase based on collisions which is why they all eventually slow down. On the other hand, if you apply the velocity to each object in every frame, they will likely ignore collisions. Like i said above, you’d be best served by relying on force application

thanks. i think you may well be correct but from the documentation this is not what should happen. the description of bounce and velocity say that the collisions are perfectly elastic (ie no reduction after collision) and setting zero gravity means there are no external forces. As I am simulating physics/chemistry i assumed the physics engine would do what it says on the tin.

If this is not a bug then the reduction in velocity from collisions should be gradual but in fact for each molecule most collisions are perfectly elastic but when one isnt (seems random) that particle then grinds to a halt which wouldnt happen in physics.

I had begun before your comment to consider object:applyLinearImpulse each frame but it seemed overkill but now it seems it may be needed.

If you apply an impulse just once that should be enough to keep the system going like you want provided you set bounce to 1 and no linear damping so that may be worth a try

actually your comment got me thinking. See if you follow my logic:

I make an object and put it into physics with no gravity
my current code then gave all particles a standard linear velocity (100, 100) ie 100 pixels horizontally and 100 pixels vertically per second (ie right and down 100 = diagonally) down and right and yet the particles all move in different directions.

i will try your suggestion and let you know.

Hmm. If they are not moving diagonally from the start it’s hard to say what the problem
is but at least in theory, it would appear to be a better option if you can just replace the uniform v with an impulse when you init the particles.

I don’t know the exact treatment box2d physics use for objects travelling at a uniform velocity but I do know that it can cause erratic behaviour. As an example, we use linear velocity in a platform game where we want to move a character across a surface but arent looking for any physics per se and the only motive for incorporating solar2d physics was to be able to detect collisions. It’s basically the equivalent of translating your display objects’ coordinates which prevents the engine from correctly judging the impact forces on a collision surface (i think)

What matters is your method does work - with some very small impulses and for some reason the radius of the object (cog i think) needs to be very small).
for r = 1,noOfMolecules do
blueMolecule[r] = display.newImageRect(“sodium.png”,moleculeSize,moleculeSize)
repeat
xpos = math.random(65,255)
ypos = math.random(85,155)
until xpos~= ypos
blueMolecule[r].x = xpos
blueMolecule[r].y = ypos
physics.addBody( blueMolecule[r], “dynamic”, { bounce=1.0, friction=0, radius=0.01}) --filter=blueCollisionFilter } )
blueMolecule[r].isFixedRotation = true
repeat
xdir = math.random(-5,5)
ydir = math.random (-5,5)
until xdir~=ydir

blueMolecule[r]:applyLinearImpulse( 0.00000001*xdir, 0.00000001*ydir, blueMolecule[r].x, blueMolecule[r].y )

end

Ive stuck them in an array because I was going to do the impulse each frame.

ive had the simulation running for 20 minutes and no molecules die now. I am still convinced there is a bug in the physics engine but it works.

It’s likely that the values get constantly rounded during runtime, which means if you don’t re set them at some point, they’ll keep on gradually decreasing until they hit zero or you’ll hit some floating point oddity after enough rounding, which will do who knows what.

that may well be true but the description of the functionality of physics objects is clear that nobounce with no gravity keeps velocity constant as required by Newton.

Sure, but Newton didn’t write code using floating point numbers.

I think the problem, as I have suspected throughout, is not that the physics engine is not operating correctly but that how things happen with real physics and in the engine are not necessarily consistent.

Under ideal conditions, there will have to have been a force that acts on a body at some stage for it to be in a state of motion (uniform or non-uniform) but when you omit that force and directly set the velocity in your code, you are risking erratic behaviour upon collisions because the engine simply is not written to work in reverse by computing impact of a collision based on the final resultant velocity and mass. It needs to have moved that body under its own control after the application of a force in order to be able to solve the overlap at the time of a collision. When you translate a sprite by using setLinearVelocity, you are working around the engine so it might still detect collisions and attempt to resolve the overlap but it won’t be accurate (i.e, it will depend on deltaTime, timeSteps, velocitySteps and other parameters that I don’t know very much about)

EDIT: Think of it like this-- by setting the linearVelocity you are essentially asking the engine to not change the velocity of the object at any stage but then you are also defining it as a dynamic body which can be subject to collision forces and forces, as we have established, affect velocity. The two can just not be reconciled.

  1. Confused about your saying ‘nobounce’. You mean bounce right? e.g. restitution = 100%
  2. That is not correct. It is only true for a dynamic object bouncing off a static object.

I think your physics understanding and expectations are wrong for dynamic versus dynamic collisions.:

Even with 100% restitution (bounce) objects will not maintain their individual velocities when they collide with each other.

High mass objects colliding with low mass objects will tend to slow, whereas the low mass objects will speed up.

  • What would happen if a moving pool ball collided with a moving tennis ball on a pool table.

There will be some losses in the system due to: rounding errors, precisions, and wall sliding (if you have rectangular objects moving about).

If you want an objects to maintain the same speed at all times, you’ll have to enforce it yourself.

I answered a question like this back in 2015 (post date says 2018, but I think that is wrong): Constant speed ball after collision

Direct link to demo
https://github.com/roaminggamer/RG_FreeStuff/raw/master/AskEd/2015/11/bouncy.zip

RG Free Stuff (answers to many posts)

SSK2(Helper Libs)

I am grateful for your input and it has solved my problem… but as a scientist you are wrong in your interpretation of Newton’s first law. That doesnt matter as the issue is how does Solar2d’s physics engine react, so I am grateful.