Close encounter condition for Nbody code - c++

I wrote a simple N-body code using a leapfrog algorithm. Now what I am trying to do is create a close encounter condition. I want the code to let me know whenever two particles come closer than a certain distance. This is what I came up with, it seems to me that it should work, but it doesn't. It's in c++:
In the code: num is the number of particles, r[num][3] is a global 2d array that holds the 3d position of each particle (x,y,z coords).
I am just writing the function check_collisions, which is executed in the main function under a time loop, which evolves the system.
What I was trying to do is to store the distances between any given pair of particles, and compare them to some distance (in this case rad[i]+rad[j], where rad[num] is a global array of the radius of each particle). If the distance between 2 particles is less than rad[i]+rad[j], then I want the variable dummy to increase. Then I want to do some stuff those particles, leaving the others intact.
The problem is that dummy is still 0 no matter what. I independently check that 2 particles in one of my trials are actual close to each other for several timesteps, but the dummy variable keeps on zero.
Here is the fucntion
int check_collisions(int num, double dt)
{ double rji[3]; double r2, dis; int dummy = 0;
double rad_sum[num][num]; double coll_dis[num][num];
for (int l = 0; l < num; l++)
{ for (int m = 0; m < num; m++)
{ coll_dis[l][m] = 10000; rad_sum[l][m] = 0;} }
for (int i = 0; i < num; i++)
{ for (int j = i+1; j < num; j++)
{
for (int k = 0; k < 3; k++)
{ rji[k] = r[j][k] - r[i][k]; }
for (int k = 0; k < 3; k++)
{ r2 += rji[k] * rji[k]; }
dis = sqrt(r2);
coll_dis[i][j] = dis;
rad_sum[i][j] = rad[i]+rad[j];
}//end for j
}//end for i
for (int i = 0; i < num; i++)
{ for (int j = i+1; j < num; j++)
{
if ( coll_dis[i][j] <= rad_sum[i][j] )
{ dummy++;
}
if (dummy != 0)
{ do { some stuff involving dt
} while (coll_dis[i][j] <= rad_sum[i][j]);
}
}
}
}

Related

Calculating Big-O notation that has three nested loops

I want to find Big_O notation for my code. It has three nested loops and each loop has parameter that maybe vary.
According to my understanding (I am not sure if that correct).
time complexity is O(NKC) where N is the size in the outer loop, K is a constant inserted by user. C is also constant that may be change when using other dataset.
my code:
for (int m=0; m< size; m++)
{
int array_Y_class_target[2]{};
float CT[2]{};
float SumOf_Each_class_distances[2] = { 0.0 };
int min_index = -1;
for (int i = k; i > 0; --i) {
for (int c = 0; c < 2; ++c) {
for (int j = 0; j < i; ++j) {
int index = index_arr[j];
if (Y_train[index] == c)
{
array_Y_class_target[c] ++;
float dist = array_dist[index_arr[j]];
SumOf_Each_class_distances[c] += dist;
}
}
if (array_Y_class_target[c] != 0)
{
CT[c] = (((float)k / (float)array_Y_class_target[c]) + (SumOf_Each_class_distances[c] / (float)array_Y_class_target[c]));
}
else
{
CT[c] = 1.5; // max CT value
}
}

Partial Pivoting/Gaussian elimination- swapping columns instead of rows producing wrong output

I'm trying to implement a quick program to solve a system of linear equations. The program reads the input from a file and then writes the upper-triangular system and solutions to a file. It is working with no pivoting, but when I try to implement the pivoting it produces incorrect results.
As example input, here is the following system of equations:
w+2x-3y+4z=12
2w+2x-2y+3z=10
x+y=-1
w-x+y-2z=-4
I expect the results to be w=1, x=0, y=-1 and z=2. When I don't pivot, I get this answer (with some rounding error on x). When I add in the pivoting, I get the same numbers but in the wrong order: w=2,x=1,y=-1 and z=0.
What do I need to do to get these in the correct order? Am I missing a step somewhere? I need to do column swapping instead of rows because I need to adapt this to a parallel algorithm later that requires that. Here is the code that does the elimination and back substitution:
void gaussian_elimination(double** A, double* b, double* x, int n)
{
int maxIndex;
double temp;
int i;
for (int k = 0; k < n; k++)
{
i = k;
for (int j = k+1; j < n; j++)
{
if (abs(A[k][j]) > abs(A[k][i]))
{
i = j;
}
}
if (i != k)
{
for (int j = 0; j < n; j++)
{
temp = A[j][k];
A[j][k] = A[j][i];
A[j][i] = temp;
}
}
for (int j = k + 1; j < n; j++)
{
A[k][j] = A[k][j] / A[k][k];
}
b[k] = b[k] / A[k][k];
A[k][k] = 1;
for (i = k + 1; i < n; i++)
{
for (int j = k + 1; j < n; j++)
{
A[i][j] = A[i][j] - A[i][k] * A[k][j];
}
b[i] = b[i] - A[i][k] * b[k];
A[i][k] = 0;
}
}
}
void back_substitution(double**U, double*x, double*y, int n)
{
for (int k = n - 1; k >= 0; k--)
{
x[k] = y[k];
for (int i = k - 1; i >= 0; i--)
{
y[i] = y[i] - x[k]*U[i][k];
}
}
}
I believe what you implemented is actually complete pivoting.
With complete pivoting, you must keep track of the permutation of columns, and apply the same permutation to your answer.
You can do this with an array {0, 1, ..., n}, where you swap the i'th and k'th values in the second loop. Then, rearange the solution using this array.
If what you were trying to do is partial pivoting, you need to look for the maximum in the respective row, and swap the rows and the values of 'b' accordingly.

better algorithm for counting points in grids

Suppose I have a point P in [0,1]*[0,1], and [0,1] is divided into m(say 200) grids. I use A[m][m] to indicate whether [a small square centred at P with length 2h] covers each grid or not. So for a point P, A[i][j] is either (increase by) 1 or 0.
Suppose I have n such points(P1,...,Pn), I want to calculate A(for each point Pi, I redo the above procedure, adding 1 or not). How can I do this efficiently(with C++) rather than writing 3 layers of for loops to check for each grid and each point(So O(nm^2))?
I tried the naive 3 for loops with C++. It takes longer time than using some of the vectorized operations(like vector<= number for comparing n numbers together, A[bool vector, bool vector] for subsetting) in R.
Since C++ is generally faster than R, is there any smart way to implement this process?
#include <Rcpp.h>
#include <cmath>
using namespace Rcpp;
// [[Rcpp::export]]
double myfun(NumericVector u, NumericVector v)
{
double n = u.size();
double A[200][200] = {0};
double pos[200];
int i = 0, j = 0, k = 0;
for (i = 0; i < 200; i++)
{
pos[i] = (double)i / 201;
}
for (k = 0; k < n; k++)
{
for (i = 0; i < 200; i++)
{
for (j = 0; j < 200; j++)
{
if ( (fabs(u[k] - pos[i]) <= h) && (fabs(v[k] - pos[j]) <=h ) )
{
A[i][j]++;
}
}
}
}
double s = 0, avg = 0;
for (i = 0; i <200; i++)
{
for (j = 0; j < 200; j++)
{
s += A[i][j];
}
}
avg = s / (200 * 200);
return (avg);
}
The two inner loops only determine index of the point in your grid. But you can compute the index directly:
int i = (int)(u[k]*200);
int j = (int)(v[k]*200);
You probably also need to check that i and j don't reach the index 200. This only happens though, when u[k] == 1.0 or v[k] == 1.0.
double n = u.size();
double A[200][200] = {0};
for (int k = 0; k < n; k++)
{
int i = (int)(u[k]*200);
int j = (int)(v[k]*200);
if (i == 200)
i = 199;
if (j == 200)
j = 199;
A[i][j]++;
}

Trying to multiply two dynamically created matrices(2d vector's) together in c++

So what I am trying to do is multiply one 2d vector by another 2d vector.
I come from Java,Python and C# so I am pretty much learning C++ as I go along.
I have the code down to generate the vector and display the vector but I can't seem to finish the multiplication part.
v1 is another matrix that is already generated.
vector<vector<int> > v2 = getVector();
int n1 = v1[0].size();
int n2 = v2.size();
vector<int> a1(n2, 0);
vector<vector<int> > ans(n1, a1);
for (int i = 0; i < n1; i++) {
for (int j = 0; j < n2; j++) {
for (int k = 0; k < 10; k++) {
// same as z[i][j] = z[i][j] + x[i][k] * y[k][j];
ans[i][j] += v1[i][k] * v2[k][j];
}
}
}
displayVector(ans);
My guess for where I am going wrong is in the inner-most loop. I can't figure out what to actually put in place of that 10 I have there now.
When you multiply matrices, the number of columns of the matrix on the left side must equal the number of rows of the matrix on the right side. You need to check that that is true, and use that common number for your size of the k variable:
int nCommon = v1.size();
assert(v2[0].size() == nCommon);
for (int i = 0; i < n1; i++) {
for (int j = 0; j < n2; j++) {
for (int k = 0; k < nCommon ; k++) {
ans[i][j] += v1[i][k] * v2[k][j];
}
}
}
For you inner loop, you should do something like this
ans[i][j] = 0;
for (int k = 0; k < n2; k++) {
ans[i][j] += v1[i][k] * v2[k][j];
}
I don't know where the 10 comes from.

How can I properly add and access items to a multidimensional vector using loops?

I have this program that is trying to determine how many unique items are within some intersecting sets. The amount of input entirely depends on the the first value n, and then the amount of sets entered afterward. For example, if I start with entering n = 2, I am expected to enter 2 integers. The program then determines how many intersections there are between n items (this is like choosing 2 items from n items). This goes on as k increments. But that's kind of beyond the point. Just some background info.
My program adapts correctly and accepts the proper amount of input, but it stops working properly before the first for loop that is outside of the while loop. What I have tried to do is make a vector of integer vectors and then add every other row (when index starts at 0 AND index starts at 1). But I am guessing I have constructed my vectors incorrectly. Does anybody see an error in my vector logic?
#include <iostream>
#include <vector>
using namespace std;
int fact (int m) {
if (m <= 1)
return 1;
return m * fact(m - 1);
}
int comb (int n, int k) {
return fact(n)/(fact(n-k)*fact(k));
}
int main() {
int n = 0;
int k = 2;
int sum = 0;
int diff = 0;
int final = 0;
vector <vector <int> > arr;
cin >> n;
while (n > 0) {
vector <int> row;
int u;
for (int i = 0; i < n ; ++i) {
cin >> u;
row.push_back(u);
}
arr.push_back(row);
n = comb(row.size(), k);
k++;
}
for (int i = 0; i < arr.size(); i+2)
for (int j = 0; j < arr[i].size(); ++j)
sum += arr[i][j];
for (int i = 1; i < arr.size(); i+2)
for (int j = 0; j < arr[i].size(); ++j)
diff += arr[i][j];
final = sum - diff;
cout << final;
return 0;
}
for (int i = 0; i < arr.size(); i+=2)
^
You want to do i+=2 or i=i+2, else the value of i is never changed, leading to an infinite loop.