是否有可能在尺寸和质量方面进行逼真的n体太阳系模拟?

Ber*_*ayD 8 simulation physics game-physics

重要提示:这个问题与"PhysX" 完全没有关系,"PhysX"是一个计算机游戏物理系统(对于街机游戏中的物理学有用,如球类游戏等); PhysX是Unity3D和其他游戏引擎内置的系统; PhysX在这里完全无关紧要.

////////////////////更新(先读到底部)/////////////////////

我一直在记录值并搜索确切问题的位置,我想我找到了它.我的代码中有这样的东西

Velocity += Acceleration * Time.deltaTime;
position += Velocity * Time.deltaTime;
Run Code Online (Sandbox Code Playgroud)

加速度就像0,0000000000000009 ..现在.当代码流动时,速度应该增加,浮动没有问题.但是在开始时,地球的初始位置是(0,0,23500f)你可以在我最后给出的图表中看到这一点.

那么现在当我将速度*timedelta(此时类似于0,00000000000000005)添加到23500的位置时,它基本上不会添加它.位置仍然是(0,0,23500)不像(0,0,23500.00000000000005),因此地球不移动,因此加速度不会改变.

如果我将地球的初始位置设置为0,0,0并且仍然将加速度设置为0.0000000000000000009以使其位置为(0,0,23500)然后"ADDS"速度*timedelta.它变得类似于(0,0,000000000000000000005)并且继续增加.当float为0时,添加这么小的值没有问题.但是如果浮点数类似于23500,那么它就不会增加小值.

我不知道这是完全统一的问题还是c#的漂浮.

这就是为什么我不能让它与小值一起工作.如果我能克服这一点,我的问题将得到解决.

////////////////////////////////////////////////// /////////////////////////////

我一直在开发n体植物以模拟我们的太阳系,因此我一直在收集数据以使其尽可能逼真.但是数据大小存在问题.我搜索了每一点互联网,我找不到人们如何克服这一点的单一解释.(如果是这样的话)所以我在这里尝试拍摄.

因此,为了保持行星之间的距离,半径和"质量"的比例,我创建了一个excel文件来计算所有数据.(因为有人为什么会把"地球的质量如果有"那个"半径图"在互联网上?)我将把ss作为附件.它基本上"标准化"或换句话说"缩放"行星的每个属性到给定的参考.在这种情况下,我把参考作为"地球的半径".

我团结一致,你知道,你不能在统一中使用"太大"或"太小"的价值观.所以我不得不缩小太阳能系统,"很多!"

因此,我使用牛顿万有引力定律,即F = GMm/r ^ 2,使其变得简单,我直接计算a = GM/r ^ 2,对于来自所有其他物体的给定物体.

因此,地球的"朝向太阳"的重力加速度的实际值大约是0,000006 km/s ^ 2,这在统一的工作中甚至是非常小的值,但它可以工作.然而,为了获得这个值,1我需要将地球的半径(比例)设置为6371单位,并将太阳比例设置为696,342 !,这对于将其统一起来来说太大了.

所以我说,让地球的半径为1,以统一为单位.因此,当半径改变时,一切都会改变,质量,距离......我保持行星的密度,并用新半径计算新体积的质量.所有计算都在附件中.

所以事实是,当我把地球的半径变为1时,对太阳的引力加速就像0,0000000000009那样小得可笑.当然,Unity不会使用这个值.

所以,如果我改变地球的半径,那么太阳的质量和半径变得非常大,然后再次,我无法使用它.

我不知道其他人如何解决这个问题,他们为解决这个问题做了什么,但正如我从这里看到的那样,看起来不可能对太阳系进行逼真的n体模拟.(至少统一)

所以我需要有10个代表来发布图片-_-,我会给出链接. http://berkaydursun.com/solar_system_simulator/data.PNG 另外一个目录是使用n体计算但具有UNREALISTIC值的工作实验太阳系模拟.它工作得很好,它甚至看起来有点接近真实,但不,它没有正确的比率^^你可以在这里测试它,如果你希望http://berkaydursun.com/solar_system_simulator/

编辑:WoW我几乎用"So"开始了每个段落^^

Spe*_*tre 14

我也做了程序溶胶系统模拟,所以这里是我的见解:

  1. 翻译

    我使用OpenGL1:1缩放.所有单位都是SI所以[m,s,kg,...].问题从Z-buffer开始.通常的Z缓冲区位宽16/24/32 bit不足以满足您的需求.我正在渲染0.1米到1000澳元,那么如何解决这个问题呢?

    我通过组合Z-sortingZ-buffering一起渲染3个frustrums来管理它(由于透明环......和其他效果,Z-sort是必要的).所以首先我将最远的部分渲染到zfar=1000AU.天空圆顶投射到z=750AU距离然后清除Z缓冲区并渲染对象zfar=0.1AU.然后再次清除Z缓冲区并渲染近处的对象zfar=100000 m.

    要完成这项工作,您必须拥有尽可能精确的投影矩阵.gluPerspective有unprecise cotangens所以它需要修复有关的元素(让我很长的时间来发现这一点).Z near值取决于Z缓冲区的位宽.如果编码正确,那么即使使用缩放也能正常工作10000x.我使用这个程序作为矿山望远镜对象的导航/搜索器:)从我的家庭视图实时.我结合了3D星,天文体,船只,真实地面(通过DTM和卫星纹理).它甚至能够产生红 - 青色立体输出:).可以从表面,大气,空间渲染......(不仅仅是锁定在地球上).没有其他第三方lib然后使用OpenGL.这是它的样子:

    IMG IMG IMG IMG IMG

    正如你所看到的,它可以在任何高度上工作,也可以像大气散射着色器一样完成大气

  2. 模拟

    我没有使用n体重力模拟,因为你需要大量非常难以获得的数据(并且几乎不可能达到所需的精度).计算必须非常精确.

    我使用开普勒方程式,所以看看这些:

    如果你仍然想使用引力模型,然后使用喷气推进实验室的视野美国航空航天局.我认为他们在C/C++中也有源代码,但他们使用不兼容的参考框架和我的地图,所以它对我来说无法使用.

    一般来说,开普勒方程具有更大的误差,但它并没有随着时间的推移而增加.重力模型更精确但其误差随着时间的推移而增加,您需要不断更新astro体数据以使其工作......

[edit1]集成精度

您当前的实现是这样的:

// object variables
double  acc[3],vel[3],pos[3];
// timer iteration
double dt=timer.interval;
for (int i=0;i<3;i++)
 {
 vel[i]+=acc[i]*dt;
 pos[i]+=vel[i]*dt;
 }
Run Code Online (Sandbox Code Playgroud)

问题是当你添加非常小且非常大的值时,它们会在添加之前转移到相同的指数,这将使重要数据四舍五入.为了避免这种情况,只需将其更改为:

// object variables
double          vel0[3],pos0[3]; // low
double          vel1[3],pos1[3]; // high
double  acc [3],vel [3],pos [3]; // full
// timer iteration
double dt =timer.interval;
double max=10.0; // precision range constant
for (int i=0;i<3;i++)
 {
 vel0[i]+=acc[i]*dt; if (fabs(vel0[i]>=max)) { vel1[i]+=vel0[i]; vel0[i]=0.0; } vel[i]=vel0[i]+vel1[i];
 pos0[i]+=vel[i]*dt; if (fabs(pos0[i]>=max)) { pos1[i]+=pos0[i]; pos0[i]=0.0; } pos[i]=pos0[i]+pos1[i];
 }
Run Code Online (Sandbox Code Playgroud)

现在xxx0已经整合到max了,整个事情都被添加到了xxx1

四舍五入仍然存在,但它不再累积.您必须选择max集成本身是安全的值,并且添加xxx0+xxx1必须是安全的.因此,如果一个分裂的数字太不相同,则分割两次或更多次......

  • 喜欢: xxx0+=yyy*dt; if (fabs(xxx0>max0))... if (fabs(xxx1>max1))...

[Edit2]明星

[Edit3]进一步提高Newton d'Lambert的集成精度

迭代积分的基本问题是,基于当前身体位置来应用基于引力的加速将导致更大的轨道,因为在整合步骤中dt,位置改变了一点,这在初始积分中没有考虑.要解决这个问题,请看一下这张图片:

积分

假设我们的身体处于圆形轨道并处于0度位置.而不是使用基于当前位置的加速度方向我使用后的位置0.5*dt.这增加了加速度小位,从而产生了更高的精度(与开普勒轨道的对应关系).通过这个调整,我能够成功地从开普勒轨道转换为Newton d'Lambert的2体系统.(为n-body执行此操作是下一步).与我们的太阳系的实际数据粗略相关只能用于不受​​潮汐效应和/或卫星影响的2体系统.要构建自己的虚构数据,您可以使用开普勒圆轨道和重力均衡重力:

G = 6.67384e-11;
v = sqrt(G*M/a);                           // orbital speed
T = sqrt((4.0*M_PI*M_PI*a*a*a)/(G*(m+M))); // orbital period
Run Code Online (Sandbox Code Playgroud)

a圆形轨道半径在哪里是m体重,M是焦点体质(太阳).为了保持精度在可接受的容差范围内(对我而言),集成步骤dt应该是:

dt = 0.000001*T
Run Code Online (Sandbox Code Playgroud)

因此,将新机构用于测试只需将其放在:

pos = (a,0,0)
vel = (0,sqrt(G*M/a),0)
Run Code Online (Sandbox Code Playgroud)

主要焦点机构(Sun)位于:

pos = (0,0,0)
vel = (0,0,0)
Run Code Online (Sandbox Code Playgroud)

这将使您的身体处于圆形轨道,这样您就可以比较Kepler和Newton d'Lambert来评估模拟的精确度.

  • @BerkayDrsn 1.是的,开普勒方程不能用于弹弓和非周期性运动。2. 由于连续求和积分误差,重力模型的误差不断增加(它可能看起来很现实,但当你将它与真实的东西进行比较时,它不匹配) 3. 我强烈建议不要使用 Unity 进行此类计算,而是自己进行计算,但是您需要使用某种更高精度的定点/浮点数和足够小的积分 dt 步长。很可能也有一些天文数字库。Unity 是为游戏而设计的,而不是为真实模拟而设计的 (2认同)