This is an update of the code from my previous question.
I'm simulating a system of particles which interact with each other and move and rotate due to the interaction. There are 2000 particles in total but each particle interacts with other particles and their image (I'm using a periodic boundary condition) if particles and their images have distances larger thanl0. I just consider image of particles in 8 near boxes to the main box.
y[N],x[N] are the position of points in the plane; dx[n] and dy[N] their changes in each time step. c shows different time steps. e_x and e_y shows x and y component of direction of each particle respect to x and y-axis.
#include <iostream>
#include <math.h>
#include <vector>
#include <array>
#include <list>
#include <random>
#include <functional>
#include <fstream>
#include <string>
#include <sstream>
#include <algorithm>
#include <chrono>
using namespace std;
#define pi 3.14159265358979323846
// function declarations(these lines are defined to generate uniform random numbers)
double dist(double x1, double y1, double x2, double y2, double L);
double PBC(double x, double L);
uint64_t s[2] = { 0x41, 0x29837592 };
static inline uint64_t rotl(const uint64_t x, int k) {
return (x << k) | (x >> (64 - k));
}
uint64_t next(void) {
const uint64_t s0 = s[0];
uint64_t s1 = s[1];
const uint64_t result = s0 + s1;
s1 ^= s0;
s[0] = rotl(s0, 55) ^ s1 ^ (s1 << 14); // a, b
s[1] = rotl(s1, 36); // c
return result;
}
double uniform() {
return next()*(1.0/18446744073709551616.0);
}
// main function
int main()
{
unsigned short int N=2000, l0=2;
double dt=0.001, a=0.001, b=0.002;
long c_equilib=10;
double L=10,
x[N], // x coordinate of r
y[N], // y coordinate of r
theta[N]; // angle (direction)
double e_x[N], e_y[N];
for (unsigned short int i=0; i<N; i++)
{
x[i]=uniform()*L; // in the range (0, L)
y[i]=uniform()*L; // in the range (0, L)
theta[i]=-pi+uniform()*2.0*pi;
e_x[i]=cos(theta[i]);
e_y[i]=sin(theta[i]);
}
// evolution of time
long c = 0; //This is number of past time steps in while loop of time
while (c < c_equilib)
{
double dx[N], dy[N],theta_new[N];
c++;
for(unsigned short int i = 0; i < N; i++)
{
// orientation (theta) change
unsigned int count = 0;
double S_theta=0.0, S_x=0.0, S_y=0.0, S;
for(unsigned short int j=0; j<N; j++)
{
if (j==i) continue;
for(int ky=-1; ky<=1; ky++)
{
for(int kx=-1; kx<=1; kx++)
{
double r_x_ij=x[i]-(x[j]+kx*L),
r_y_ij=y[i]-(y[j]+ky*L),
r_ij=sqrt(pow(r_x_ij,2.0)+pow(r_y_ij,2.0));
if (r_ij >= l0)
{
r_x_ij/=r_ij;
r_y_ij/=r_ij;
S_theta += (e_x[i]*e_x[j]+e_y[i]*e_y[j]) / pow(r_ij, 3) * ( 3.0* (r_x_ij*e_x[j]+r_y_ij*e_y[j]) *
pow(e_x[i]*r_y_ij - e_y[i]*r_x_ij, 2.0) -
e_x[i]*e_y[j] + e_y[i]*e_x[j] );
S = ( 3.0* pow(r_x_ij*e_x[j]+r_y_ij*e_y[j], 2.0) -1.0 ) / pow(r_ij, 2.0);
S_x += r_x_ij*S;
S_y += r_y_ij*S;
}
}
}
}
theta_new[i] += dt*b*S_theta;
dx[i] += dt*a*S_x;
dy[i] += dt*a*S_y;
}
// update angles and positions
for(unsigned short int i=0; i<N; i++)
{
theta[i]=theta_new[i];
// keep theta in the range [-pi, pi]
while(theta[i]>pi)
theta[i]-=2*pi;
while(theta[i]<-pi)
theta[i]+=2*pi;
e_x[i]=cos(theta[i]);
e_y[i]=sin(theta[i]);
x[i]+=dx[i];
y[i]+=dy[i];
// apply periodic boundary condition
if (x[i] > L)
{
x[i]-= L;
} else if( x[i] < 0) {
x[i]+= L;
}
if (y[i] > L)
{
y[i]-=L;
} else if( y[i] < 0) {
y[i]+= L;
}
}
}
return 0;
}
// calculates the distance between two points
double dist(double x1, double y1, double x2, double y2, double L)
{
return sqrt(pow(PBC(x1-x2,L),2.0)+pow(PBC(y1-y2,L),2.0));
}
// periodic boundary condition
double PBC(double x, double L)
{
if(fabs(x)>L/2.0)
return L-fabs(x);
else
return fabs(x);
}
I'm looking to optimize the large loop of this C++ program. This is one part of my simulation (I have ignored some calculations inside the loop to make the question simpler). The main question is his part is extremely time-consuming. How can I make it faster? Second question: How should I choose discretization step size (dt)? could you please give me a good choice for it (comparing with other values in the question) This question is related to the other question which is linked to this one. But, according to comments in the previous question, I have added the runnable code here. As I was asked to post a new question for this purpose by the moderators.
S_theta
with. Furthermore, I would ask for a general code review as well (there is a lot of room for improvement here). \$\endgroup\$