Я работаю над программой симуляции гравитационного взаимодействия частиц для c ++, и я почти до такой степени работаю, но у меня есть глупая необъяснимая ошибка, которая сводит меня с ума.
Программа имеет 2048 частиц и моделирует их с шагом 200; в каждом состоянии он обновляет новые положения, скорости и ускорения каждой из частиц, основываясь на суммарной силе всех других частиц. По сути, вот рекурсивная функция, которую я написал, которая перебирает quad_tree и обновляет все значения частиц:
void iterateThroughQuadTree(double alpha, double delta_t)
{
std::cout << particles_count << std::endl;
if (particles_count > 10)
{
//std::cout << particles_count << std::endl;
children[0]->iterateThroughQuadTree(alpha,delta_t);
children[1]->iterateThroughQuadTree(alpha,delta_t);
children[2]->iterateThroughQuadTree(alpha,delta_t);
children[3]->iterateThroughQuadTree(alpha,delta_t);
}
if (particles_count > 0)
{
std::cout << *(particles_x) << " " << *(particles_y) << " " << *(particles_vx) << " " << *(particles_vy) << std::endl;
double acc_magnitude = 0, distance = 0, unit_vector_x = 0, unit_vector_y = 0, x_displacement = 0, y_displacement = 0, theta = 0, x_acc = 0, y_acc = 0;
for (size_t i = 0; i < particles_count; i++) {
double temp_x_acc = 0;
double temp_y_acc = 0;
for (size_t k = 0; k < particles_count; k++) {
if (i != k) {
x_displacement = particles_x[k] - particles_x[i];
y_displacement = particles_y[k] - particles_y[i];
distance = sqrt(pow(x_displacement,2) + pow(y_displacement,2));
unit_vector_x = x_displacement / distance;
unit_vector_y = y_displacement / distance;
acc_magnitude = particles_m[k] / pow(distance,2);
// //theta = atan(y_displacement/x_displacement);
x_acc = acc_magnitude * unit_vector_x;
y_acc = acc_magnitude * unit_vector_y;
// //x_acc = (x_displacement);
// //y_acc = (y_displacement);
temp_x_acc = temp_x_acc + x_acc;
//temp_y_acc = temp_y_acc + y_acc;
}
}
//std::cout << temp_x_acc << " " << temp_y_acc << std::endl;
particles_x[i] += ((particles_vx[i]*delta_t) + alpha*temp_x_acc*pow(delta_t,2));
particles_y[i] += ((particles_vy[i]*delta_t) + alpha*temp_y_acc*pow(delta_t,2));
particles_vx[i] += 2*alpha*temp_x_acc*delta_t;
particles_vy[i] += + 2*alpha*temp_y_acc*delta_t;
// if (i < 1) {
// //std::cout << *(particles_x + i) << " ";
// }
}
}
}
Если вы обратите внимание на две следующие две строки в середине функции:
temp_x_acc = temp_x_acc + x_acc;
//temp_y_acc = temp_y_acc + y_acc;
Ошибка в том, что если одна из этих строк закомментирована (не имеет значения, какая из них), программа работает нормально. Но когда они оба не закомментированы, программа падает после нескольких итераций, что приводит к ошибке сегментации. Я использовал ValGrind Memcheck, и он говорит, что переполнение стека. Я не понимаю, почему обе строки не могут быть в программе вместе; один просто суммирует все ускорения x-компонента, а один суммирует ускорения y-компонента. Есть ли проблемы с памятью, когда у меня два оператора + =? Я пытался каждый раз переинициализировать переменные, но все равно получал тот же результат. Если у вас есть идея, почему это происходит, не могли бы вы объяснить это мне? Спасибо, я ценю вашу помощь.
Я опубликую дополнительный код для программы, если необходимо, проблема в том, что программа большая, поэтому я не хочу публиковать больше, чем нужно.
Не видя весь ваш код, у меня есть теория, которая могла бы сдержать. Где-то в вашем коде, который вы не показывали, вы, безусловно, должны изменять значение частиц_счетное число, которое является глобальной переменной. Ваша рекурсивная функция не может быть прервана до тех пор, пока не будет опущено значение частиц 10
Возможно ли, что когда оба параметра temp_x_acc и temp_y_acc установлены, то значение вашего частиц_count каким-то образом возрастает, вызывая еще больше итераций цикла, что приводит к переполнению стека? В качестве проверки работоспособности, чтобы помочь проверить, я рекомендую вам добавить статический счетчик в начало вашей функции, например так:
static int iteration=0;
iteration++;
cerr<<"Iteration: "<<iteration<<", "<<Particles count: "<<particles_count<<endl;
Обратите внимание на использование cerr, чтобы вы получили весь вывод до его сбоя. Cout может не печатать всю историю, когда она падает.
Как правило, в рекурсивном коде важные переменные, такие как частица_числа, должны передаваться как параметр функции. Я думаю, что значение elements_count может меняться так, как вы этого не ожидаете.
Других решений пока нет …