我用C ++写了一个蛮力的三维N体模拟,它按预期工作。
我尝试通过包含行" myPhys.Collisions(particleList);"来实现非弹性粒子碰撞。作为我在main.cpp中的for循环的一部分," Collisions"在物理学中定义了#34;课程(也见下文)。
代码在data.csv中运行并生成输出。但是,有时运行会被“#34;分段故障:11"并且碰撞导致意外行为。
我想知道我是否在某种程度上没有正确地处理向量"碰撞"功能,特别是在行
// create particle with new parameters
Particle newParticle(newMass, newPosition, newVelocity);
// replace first particle in collision with new particle
particleList[idx1] = newParticle;
// erase second particle in collision
particleList.erase(particleList.begin()+idx2);
我还应该提一下,我是C ++的新手,所以如果我做一些愚蠢的事情,我会道歉。
完整代码位于https://www.dropbox.com/sh/b3oq7x546c9lktv/AAAdUE7Nrzaiov0TaGtgjbfNa?dl=0
的main.cpp
#include <iostream>
#include <fstream>
#include <vector>
#include "vectorops.h"
#include "particle.h"
#include "physics.h"
using namespace std;
int main(){
ofstream myData;
myData.open("data.csv");
// initialize a vector of particles
int numParticles = 20;
vector<Particle> particleList;
for(int i = 0; i < numParticles; i++){
particleList.push_back(Particle(1));
}
// declare physics engine
Physics myPhys;
// time evolution
for(int t = 0; t < 10000; t++){
// calculate force on every particle
vector< vector<double > > currentForces = myPhys.forceList(particleList);
// iterate over particleList
for(int i = 0; i < numParticles; i++){
if(i < particleList.size())
{
// compute accelerations
particleList[i].updateAcceleration(currentForces[i]);
// increment velocities
particleList[i].updateVelocity();
// increment positions
particleList[i].updatePosition();
// print coordinates of each particle
for(int j = 0; j < 3; j++){
myData << particleList[i].getPosition().at(j) << ",";
}
}
else
{
for(int j = 0; j < 3; j++){
myData << 0 << ",";
}
}
}
// update particleList after collisions
myPhys.Collisions(particleList);
myData << "\n";
}
myData.close();
return 0;
}
从Physics.cpp中提取
void Physics::Collide(vector<Particle> &particleList, int idx1, int idx2){
// compute parameters of new particle
double m1 = particleList[idx1].getMass();
double m2 = particleList[idx2].getMass();
double newMass = m1+m2;
vector<double> newVelocity;
vector<double> v1 = particleList[idx1].getVelocity();
vector<double> v2 = particleList[idx2].getVelocity();
for(int i = 0; i < 3; i++){
newVelocity.push_back((m1*v1[i]+m2*v2[i])/newMass);
}
vector<double> newPosition;
vector<double> x1 = particleList[idx1].getPosition();
vector<double> x2 = particleList[idx2].getPosition();
for(int i = 0; i < 3; i++){
newPosition.push_back((m1*x1[i]+m2*x2[i])/newMass);
}
// create particle with new parameters
Particle newParticle(newMass, newPosition, newVelocity);
// replace first particle in collision with new particle
particleList[idx1] = newParticle;
// erase second particle in collision
particleList.erase(particleList.begin()+idx2);
}
void Physics::Collisions(vector<Particle> &particleList){
for(int i = 0; i < particleList.size();i++){
for(int j=0; j < i; j++){
double dist = Vectors.distance(particleList[i].getPosition(),particleList[j].getPosition());
if(dist < 0.01){
Collide(particleList,i,j);
}
}
}
}
答案 0 :(得分:0)
代码的问题在于,在“粒子列表”因碰撞而调整大小后,“myData”中粒子的位置与前一个时间步长没有正确对齐。
快速解决方法是简单地将其中一个碰撞粒子移动到与其他粒子相距很远的距离,而不是将其从矢量中删除
// create particle with new parameters
Particle newParticle(newMass, newPosition, newVelocity);
// replace first particle in collision with new particle
particleList[idx1] = newParticle;
// move second particle to large distance
vector<double> farAway;
for(int i = 0; i < 3; i++){
farAway.push_back(1000000);
}
particleList[idx2].setPosition(farAway);
然而,这并不是特别优雅。我认为更优雅的方法可能是将位置历史存储在粒子对象本身中。