hunar4321/particle-life

Simultaneous attractive and repulsive forces in the same particle

KhadrasWellun opened this issue · 23 comments

Hi! I want a particle of a certain colour to attract and repel a particle of another colour simultaneously, on different beams and with different intensities. In the original application, a particle either attracts or repels another particle, depending on the sign of the intensity of the interaction force.
I started by defining interactions as follows:
void interaction(std::vector* Group1, const std::vector* Group2, float G, float Gradius, float A, float Aradius, float viscosity, float Gprobability, float Aprobability);
"G" would be "powerSlider_a_" for pull force, "Gradius" would be "vSlider_a_" for pull force, "A" would be "powerSlider_r_" for repelling force, "Aradius" would be "vSlider_r_" for repelling force.
Defining interactions would be of the form:
if (numberSliderR > 0) interaction(&green, &red, powerSlider_a_GR, vSlider_a_GR, powerSlider_r_GR, vSlider_r_GR, viscosityG, probability_a_GR, probability_r_GR);

However, I have no idea how the calculation of forces and velocities should be defined.

I try to defined:

void ofApp::interaction(std::vector* Group1, const std::vector* Group2, const float G, const float Gradius, const float A, const float Aradius, const float viscosity, const float Gprobability, const float Aprobability)
{
const float g = G / -100; //Gravity coefficient
const float a = A / 100; //Anti-Gravity coefficient
const auto group1size = Group1->size();
const auto group2size = Group2->size();
const bool radius_toggle = radiusToogle;

But I don't know if it's good.

Then I modified this:
//Calculate the force in given bounds.
if ((r < (Gradius * Gradius - Aradius * Aradius) || radius_toggle) && r != 0.0F)
{
fx += (dx / std::sqrt(dx * dx + dy * dy));
fy += (dy / std::sqrt(dx * dx + dy * dy));
}
}

				//Calculate new velocity
				p1.vx = (p1.vx + (fx * (g + a))) * (1 - viscosity);
				p1.vy = (p1.vx + (fx * (g + a))) * (1 - viscosity) + worldGravity;

But I don't know if it's good.

It must be kept in mind that each type of force has its intensity and range of action and this must be clearly defined in the application.

There would be three situations:
when Gradius > Aradius;
when Gradius = Aradius;
when Gradius < Aradius.

For each of them I think the formulas for force and velocity should be defined.

For example: Blue can attract White with an intensity of 20, on a radius of 100, and at the same time repel White with an intensity of 30 but on a radius of 40. Then White can attract Blue with an intensity of 30 on a radius of 70, but simultaneously repel it with an intensity of 50 on a radius of 60. So White can be caught by the attraction of Blue but cannot approach it at less than 60, because it repels Blue with an intensity of 50 which is greater than the attraction of 30 it has to Blue at a radius of 70. At a distance of 60, there is a neutral force of zero intensity between Blue and White.

Any ideas? Any help?

ker2x commented

A simple patch would be to revert the sign in an else condition.

if(within radius) {
  attract
} else {
  repulse
}

from my experience, any rule that apply to the whole screen (r > radius*radius) lead to uninteresting result.

A simple patch would be to revert the sign in an else condition.

if(within radius) {
  attract
} else {
  repulse
}

from my experience, any rule that apply to the whole screen (r > radius*radius) lead to uninteresting result.

But I don't want to apply the rules to the whole screen. I think I misunderstood part of the code.

Do you have any idea how to make settings menu with vertical scrollbar? When you have a lot of data in the menu, you need to be able to scroll through it to view it. I'd like to do that but I don't know how.

ker2x commented

I don't know. I made gui group instead.

I finished inserting the matrix but i got this:
image

Something is very wrong here in what i've done.

I don't understand this part of the code. This is where the problem with the strange behaviour of the particles comes from. Please, could you help me?
I have defined two intensities (one for attraction and one for repulsion) and two ranges of action. How should this piece of code be modified so that each distance or distance difference corresponds to the appropriate intensity or intensity difference?
I have attached a document explaining how I see the two types of forces and what I want to implement in this code.
Attraction and Repulsion Explained.pdf
Here I have attached my latest version of the code.
src.zip
And here is the piece of code where I think it is wrongly modified by me:
#pragma omp for
for (auto i = 0; i < group1size; i++)
{
if (rd() % 100 < probability) {
auto& p1 = (*Group1)[i];
float fx = 0;
float fy = 0;

			//This inner loop is, of course, where most of the CPU time is spent. Everything else is cheap
			for (auto j = 0; j < group2size; j++)
			{
				const auto& p2 = (*Group2)[j];
		
				// you don't need sqrt to compare distance. (you need it to compute the actual distance however)
				const auto dx = p1.x - p2.x;
				const auto dy = p1.y - p2.y;
				const auto r = dx * dx + dy * dy;

				//Calculate the force in given bounds. 
				if ((r > (Gradius * Gradius - Aradius * Aradius) || radius_toggle) && r != 0.0F)
				{
					fx += (dx / std::sqrt(dx * dx + dy * dy));
					fy += (dy / std::sqrt(dx * dx + dy * dy));
				}
			}
			
				//Calculate new velocity
				p1.vx = (p1.vx + (fx * (g + a)) * (1 - viscosity));
				p1.vy = (p1.vx + (fx * (g + a))) * (1 - viscosity) + worldGravity;
ker2x commented

Try with this (doing comparison with the distance squared was a dirty optimization trick that may not even worth it).
I'm not sure about this part with the if(r> ...) , I need to take time to understand the pdf.
But at least the code will be much more clear

		for (auto j = 0; j < group2size; j++)
			{
				const auto& p2 = (*Group2)[j];
		
				// you don't need sqrt to compare distance. (you need it to compute the actual distance however)
				const auto dx = p1.x - p2.x;
				const auto dy = p1.y - p2.y;
				const auto r = std::sqrt(dx * dx + dy * dy);

				//Calculate the force in given bounds. 
				if ((r > (Gradius - Aradius) || radius_toggle) && r != 0.0F)
				{
					fx += (dx / r);
					fy += (dy / r);
				}
			}
			
				//Calculate new velocity
				p1.vx = (p1.vx + (fx * (g + a)) * (1 - viscosity));
				p1.vy = (p1.vx + (fx * (g + a))) * (1 - viscosity) + worldGravity;

No change.
image

I noticed that changing the parameters of the interaction forces has no effect on what happens on the screen. This means that those parameters are not taken into account.
This definition is wrong:
void ofApp::interaction(std::vector* Group1, const std::vector* Group2, const float G, const float Gradius, const float viscosity, const float Gprobability, const float A, const float Aradius, const float Aprobability)

But how should it be correct?

I will try another way. I will define 2 types of interactions: interaction1 and interaction2. One is for attraction and the other for repulsion. Then I will use them as follows:
image

But no efect.

I got stuck. I don't know what to do.

ker2x commented

wait, how old is the code you're using as a base ?
I'm pretty sure I removed all the raw pointer.

Also :
I'm really getting confused by the ">". you tell it to apply force to particle that are outside the radius. therefore : the whole screen. which lead to result with a single group of particle like you have. why not "<" ?

wait, how old is the code you're using as a base ? I'm pretty sure I removed all the raw pointer.

Also : I'm really getting confused by the ">". you tell it to apply force to particle that are outside the radius. therefore : the whole screen. which lead to result with a single group of particle like you have. why not "<" ?

I don't know how old. I downloaded with the last modification.

With r < Gradius, I gain:

image

With r < Gradius * Gradius I gain:

image

ker2x commented

well my bad. I'm so busy playing with my oneapi branch that I forgot to do some merge request here. you have the last code indeed ^^

The main problem is this:
I made a button to randomize only the interaction parameters and changing them over and over again nothing happens on the screen.

Look:

image

After a cuple of randomization,

image

It can be seen that the forces acting on the screen are not those resulting from the parameters. There are other forces on the screen that move and keep the particles aligned that are much stronger than the forces resulting from the parameters defined by those sliders. So, the formulas for calculating forces and velocities do not take into account the powerSlider and vSlider parameters.

ker2x commented

There is something super weird, even in my code.
How come power became G. and why did I write "gravity coefficient" when it clearly isn't ...

ker2x commented

ha yes I see... "attraction" is named "gravity"... (which is kind of bad since there is a world gravity parameter)

ker2x commented

random guess.

can you try with std::abs(Gradius - Aradius) ?

I have already modified the code defining the 2 interactions and I no longer have how to write the Gradius - Aradius condition in the same sentence.

image

Now, two types of interactions occur simultaneously between two particles.

image

Now, two types of interactions occur simultaneously between two particles. (or they should...)

image

However, I think this code should be rewritten from scratch and rewritten taking into account what is written in this document.
Attraction and Repulsion Explained.pdf
Because what is written in this document should actually happen in this simulation.
Also, there should be a very, very weak gravitational force that brings together all the structures formed by the colored forces and makes them reinteract, always regrouping. At some point, because of the small action radii of the coloured forces, the structures formed by the particles remain outside these action radii and stop moving. That's why you need a gravitational force with an infinite action radius to bring them all together. Or a particle with an infinite radius of action and very weak forces that do the job of universal gravity. In order to prevent all the particles from clumping into a small area of the simulation surface, dark matter should be introduced, which will prevent the matter from collapsing into itself. That is, a very strong repulsive force, but with a very small radius of action.
Only then will this simulator generate interesting structures.

Romanian Adrian Ferent from the University of Bucharest has some very interesting findings on dark photons, dark matter, dark energy, Planck's wall and Ferent's wall, gravitons and elementary particle theory. From here I would like to implement some ideas.

https://www.academia.edu/30873188/Dark_Energy_is_Gravitational_Waves_Dark_Energy_is_Gravitons?email_work_card=title

https://independent.academia.edu/ADRIANFERENT

I can say that this Romanian professor is a true genius.