用.NET模拟天体运动

用.NET模拟天体运动

这将是一篇罕见而偏极客的文章。

我上大学时就见过一些模拟太阳系等天体运动的软件和网站,觉得非常酷炫,比如这个(http://www.astronoo.com/en/articles/positions-of-the-planets.html): 

其酷炫之处不仅在于天体运动轨迹能画出美妙的弧线,更重要的是其运动规律完全由万有引力定律产生,不需要对其运动轨迹进行编程。所有天体受其它天体的合力,然后按照其加速度运行。只需一个起始坐标和起始速度,就能坐下来欣赏画面。

我从大学毕业后就一直对这个抱有深厚兴趣,工作第一年时我就用 C++做过一版;后来我负责公司前端工作,又用 jscanvas又做了一个重制版;由于近期爆发的 .NET“革命”,我近期又用 C#.NET再次重制了一版。

需要的数学知识

由于是程序看数学知识,此处我将使用代码来表示公式。

  • 万有引力,该力 F与两个天体的质量 m1m2成正比,如距离 r的平方成反比,用代码表示为: F=m1*m2*G/r^2

  • 牛顿第二定律,加速度 a等于合力 F除以质量 m,用代码表示为: a=F/m

  • 速度 v与加速度 a以及时间 t的关系,用代码表示为: v=a*t

  • 距离 s与速度 v以及时间 t的关系,用代码表示为: s=v*t

这里面的所有知识都已经在高中物理提过了,但有两点需要注意:

  • 所有的力、加速度、速度以及距离都需要分为 x轴和 y轴两个分量;

  • 所有的时间 t实际上是小段时间 dt,程序将循环模拟小段时间累加起来,来模拟天体运动。

核心代码

天体类:

class Star
{public LinkedList<Vector2> PositionTrack = new LinkedList<SharpDX.Vector2>();public double Px, Py, Vx, Vy;public double Mass;public float Size => (float)Math.Log(Mass) * 2;public Color Color = Color.Black;public void Move(double step){Px += Vx * step;Py += Vy * step;PositionTrack.AddFirst(new Vector2((float)Px, (float)Py));if (PositionTrack.Count > 1000){PositionTrack.RemoveLast();}}
}

注意,我没指定大小 Size,直接给值为其质量的对数乘 2,另外注意我使用了一个 PositionTrack的 链表来存储其运动轨迹。

万有引力、加速度、速度计算

void Step()
{foreach (var s1 in Stars){// star velocity// F = G * m1 * m2 / r^2// F has a direction:double Fdx = 0;double Fdy = 0;const double Gm1 = 100.0f;     // G*s1.mvar ttm = StepDt * StepDt; // t*t/s1.mforeach (var s2 in Stars){if (s1 == s2) continue;var rx = s2.Px - s1.Px;var ry = s2.Py - s1.Py;var rr = rx * rx + ry * ry;var r = Math.Sqrt(rr);var f = Gm1 * s2.Mass / rr;var fdx = f * rx / r;var fdy = f * ry / r;Fdx += fdx;Fdy += fdy;}// Ft = ma    -> a = Ft/m// v  = at    -> v = Ftt/mvar dvx = Fdx * ttm;var dvy = Fdy * ttm;s1.Vx += dvx;s1.Vy += dvy;}foreach (var star in Stars){star.Move(StepDt);}
}

注意其中有个 foreach循环,它将一一计算每个天体对某天体的力,然后通过累加的方式求出合力,最后依照合力计算加速度和速度。如果使用 gmp等高精度计算库,该循环将存在性能热点,因此可以将这个 foreach改成 Parallel.For加 lock的方式修改合力 Fdx和 Fdy,可以提高性能( C++的代码就是这样写的)。

绘图代码

public void Draw(DeviceContext ctx)
{ctx.Clear(Color.DarkGray);using var solidBrash = new SolidColorBrush(ctx, Color.White);float allHeight = ctx.Size.Height;float allWidth = ctx.Size.Width;float scale = allHeight / 100.0f;foreach (var star in Stars){using var radialBrush = new RadialGradientBrush(ctx, new RadialGradientBrushProperties{Center = Vector2.Zero,RadiusX = 1.0f,RadiusY = 1.0f,}, new SharpDX.Direct2D1.GradientStopCollection(ctx, new[]{new GradientStop{ Color = Color.White, Position = 0f},new GradientStop{ Color = star.Color, Position = 1.0f},}));ctx.Transform =Matrix3x2.Scaling(star.Size) *Matrix3x2.Translation(((float)star.Px + 50) * scale + (allWidth - allHeight) / 2, ((float)star.Py + 50) * scale);ctx.FillEllipse(new Ellipse(Vector2.Zero, 1, 1), radialBrush);ctx.Transform =Matrix3x2.Translation(allHeight / 2 + (allWidth - allHeight) / 2, allHeight / 2);foreach (var line in star.PositionTrack.Zip(star.PositionTrack.Skip(1))){ctx.DrawLine(line.First * scale, line.Second * scale, solidBrash, 1.0f);}}ctx.Transform = Matrix3x2.Identity;
}

注意我在绘图代码逻辑中做了一些矩阵变换,我把所有逻辑做成了窗体分辨率无关的,假定屏幕长和宽的较小值为 100,然后左上角坐标为 -50,-50,右下角坐标为 50,50

星系模拟

太阳、地球和月亮

这是最容易想到了,地球绕太阳转,月亮绕地球转,创建代码如下:

public static StarSystem CreateSolarEarthMoon()
{var solar = new Star{Px = 0, Py = 0,Vx = 0.6, Vy = 0,Mass = 1000,Color = Color.Red,};// Earthvar earth = new Star{Px = 0, Py = -41,Vx = -5, Vy = 0,Mass = 100,Color = Color.Blue,};// Moonvar moon = new Star{Px = 0, Py = -45,Vx = -10, Vy = 0,Mass = 10,};return new StarSystem(new List<Star> { solar, earth, moon });
}

注意所有数据都没使用真实数字模拟(不然地球绕太阳转一圈需要 365天才能看完????),运行效果如下: 

从轨迹可以看出,由于太阳引力的作用,地球会转着太阳转,但也同样由于地球和月球引力的作用,太阳也在以微小的角度在“公转”。

扩展

如果将太阳质量翻倍( 1000-> 2000),会是何种效果呢?

可见这样一来,由于引力太大,导致地球速度变快,月亮就被地球“甩”出去了,然后地球轨道也变成了实实在在的椭圆。

双子星

宇宙中存在这样一种星系,它的两颗恒星互相围绕对方转,也可以模拟出来: 

注意两个天体在接近时速度会变快,远离时速度会变慢,这是由于万有引力与距离平方成反比决定的。

扩展N星系统

static IEnumerable<Star> CreateStars(int N)
{for (var i = 0; i < N; ++i){double angle = 1.0f * i / N * Math.PI * 2;double R = 45;double M = 10000 * 2 / (N * Math.Sqrt(N) * Math.Log(N));double v = 5;double px = R * Math.Sin(angle);double py = R * -Math.Cos(angle);double vx = v * Math.Cos(angle);double vy = v * Math.Sin(angle);yield return new Star{Px = px,Py = py,Vx = vx,Vy = vy,Mass = M,};}
}

通过精密的数学计算,可以让任意多的天体组织为系统,如将 3当作 N传入函数,即可组织为“三星系统”,运行效果如下: 

注意,超过 2星的系统都不稳定(因此“三星系统”也不稳定),转过两圈之后所有天体由于 double类型的误差已经累积到不可逆转的程度,“三星系统”会慢慢崩溃解体。

看看四星系统,命运也差不多(又比“三星”稍稳定,需要等待好几圈才崩溃): 

展望与总结

由于误差是 double类型的精度限制而累积的,在 C++中我可以使用 gmp、 mpir、 mpfr等高精度计算库来模拟计算,性能也非常高。我之前使用 C++和 mpirboost配合,可以让四星系统稳定运行长达 15分钟不崩溃,还能在我的 WindowsPhone(????)上流畅运行。

之前有人将 mpir移植到了 .NET,但不支持 .NETCore(https://github.com/wezeku/Mpir.NET),有人将 mpfr移植到了 .NET(https://github.com/emphasis87/mpfr.NET/pull/5), .NETCore可以运行,但有坑爹的 bug,我提了 PR,但作者似乎没心思Merge????。

大小数计算在天文、地震、天气、海洋等科研领域有不可取代的作用,我挺希望 .NET能提供一个高性能、高精度的小数计算库,如 BigFloat。有人会问 .NET4.0不是提供了 BigInteger吗?难道不够?是真不够!整数计算和小数计算不完全一样,性能这一关就过不去。但在 .NETCore中这个问题官方似乎没有太大动力去做,我在 github上找到了几个相关 issue,都是 open状态:

  • https://github.com/dotnet/corefx/issues/17267

  • https://github.com/dotnet/corefxlab/issues/2635

本文中涉及的所有完整、可运行代码都已经上传到我的 github博客,各位可以自行下载:https://github.com/sdcb/blog-data/tree/master/2019/20191214-simulate-planet-movement-using-dotnet

喜欢的朋友 请关注我的微信公众号:【DotNet骚操作】

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/312662.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

01 手把手带你构建大规模分布式服务--高并发、高可用架构系列,高质量原创好文!...

作者&#xff1a;丁浪&#xff0c;目前在创业公司担任高级技术架构师。曾就职于阿里巴巴大文娱和蚂蚁金服。具有丰富的稳定性保障&#xff0c;全链路性能优化的经验。架构师社区特邀嘉宾&#xff01;阅读本&#xff08;系列&#xff09;文章&#xff0c;你将会收获&#xff1a;…

如何正确的探索 Microsoft Ignite The Tour

Microsoft Ignite The Tour 是一年一度微软为全球开发者、IT专家、安全专家以及数据专家提供的为期两天&#xff0c;包含众多核心产品的实践性技术培训。2019.12.10-2019.12.11 已经在北京国家会议中心胜利闭幕&#xff0c;我作为一名Speaker 参与了两门课程的分享&#xff0c;…

回顾这一年,我沉默良久

今天是一个特殊的日子&#xff0c;因为还有一周就2024了。 回忆 我骑着我心爱的小电驴慢悠悠的走在下班的路上&#xff0c;看着万家灯火&#xff0c;匆匆而过的行人和那开着三轮车的摊贩们与城管斗智斗勇。 我陷入了回忆&#xff1f; 回忆着今年的进程&#xff0c;先是裁员…

使用ASP.NET Core 3.x 构建 RESTful API - 4.1 面向外部的Model

Entity Framework Core 使用的 Entity Model 是用来表示数据库里面的记录的。 而面向外部的 model 则表示了要传输的东西。这类 model 有时候叫做 Dto&#xff0c;有时候叫做 ViewModel。 举一个例子&#xff0c;人员的Entity Model如下&#xff1a; 最后一个字段表示人员的出生…

特意向大家推荐.NET技术圈一些优秀开发者的公众号

在互联网技术飞速发展的今天&#xff0c;各种技术席卷而来&#xff0c;总是让人感觉压力山大。作为.NET开发者&#xff0c;我们该如何刷新自己&#xff0c;实现价值的提升呢&#xff1f;2019年.NET中国开发者峰会之后&#xff0c;我们汇总了.NET技术圈一些优秀开发者的公众号&a…

ASP.NET Core on K8S深入学习(11)K8S网络知多少

Photo &#xff1a;Kubernetes文 | Edison Zhou本文已加入《.NET Core on K8S 学习与实践系列文章索引目录》&#xff0c;点击查看阅读更多容器化相关文章&#xff0c;希望对你有所帮助&#xff01;Kubernetes网络模型我们都知道Kubernetes作为容器编排引擎&#xff0c;它有一个…

Amazon、Linux基金会开发边缘网络交换器操作系统

Amazon、Linux基金会和5家网络业者上周宣布边缘网络交换器操作系统项目DENT&#xff0c;可能冲击开发专属操作系统的网络晶片及设备业者。DENT希望集结网络设备制造商&#xff0c;系统整合商及晶片厂商&#xff0c;为分散式厂区、远端办公室、分公司及零售业开发解构式网络交换…

多库操作:多个数据库的动态切换(一)

▼更多精彩推荐&#xff0c;上午11点到达▼在平时的开发中&#xff0c;受到传统模式的影响&#xff0c;我们都是习惯了单一的数据库表操作&#xff0c;把数据都建到一个库里边&#xff0c;然后进行增删改查&#xff0c;这个是很经典的开发模式。但是随着项目开发&#xff0c;总…

超燃| 2019 中国.NET 开发者峰会视频发布

首届 .NET Conf China 2019 年&#xff0c;注定会是 .NET Core 社区发展的关键一年&#xff0c;诸多重大事件在这一年发生&#xff01;正如大家所期待的那样&#xff0c;刷新中国 .NET 社区的年度盛会——2019 中国 .NET 开发者峰会&#xff08;.NET Conf China 2019&#xff0…

Lingo优化模型概述

注意事项 lingo中变量默认是非负的示例 model: max 2*x1 3*x2; 2*x1 x2 < 8; 4*x1 3*x2 < 15; end数组型变量 集合段、数据段、目标与约束段、计算段、初始段和子模型段 model: sets: s/1..10/:x; endsetsdata: x 1 2 3 4 5 6 7 8 9 10; enddatamin sum(s(i):x…

刷新.NET

.NET Core 发布的那一天起&#xff0c;它在完成自我刷新的过程&#xff0c;一切为了适应未来&#xff0c;云原生。不仅仅跨平台那么简单。.NET Core 未来发展路线我们发现跳过了.NET Core 4.X 避免了和目前.NET Framework4.X命名上的混乱&#xff0c;明年直接命名为了.NET 5 &a…

如何备份和还原您的Kubernetes集群资源和持久卷?

众所周知&#xff0c;Kubernetes可以协调连接在一起&#xff0c;作为一个工作单元&#xff0c;形成高可用性的计算机集群。Kubernetes包含许多抽象概念&#xff0c;这些抽象概念允许将容器化的应用程序部署到集群中&#xff0c;而无需将它们附加到单独的机器上。简而言之&#…

sklearn评价指标

机器学习中&#xff0c;常见的评价指标如下&#xff1a; 准确率&#xff08;Accuracy&#xff09; 精确率&#xff08;Precision&#xff09; 灵敏度&#xff08;Sensitivity&#xff09;&#xff0c;即召回率&#xff08;Recall&#xff09; 特异度&#xff08;Specificity&am…

C# WPF抽屉效果实现

时间如流水&#xff0c;只能流去不流回&#xff01;点赞再看&#xff0c;养成习惯&#xff0c;这是您给我创作的动力&#xff01;本文 Dotnet9 https://dotnet9.com 已收录&#xff0c;站长乐于分享dotnet相关技术&#xff0c;比如Winform、WPF、ASP.NET Core等&#xff0c;亦有…

视频来了!Visual Studio Online 东半球首秀 @ .NET Conf 2019 中国峰会

2019 年 11 月 9 日&#xff0c; .NET Conf 2019 中国峰会于上海中谷小南国花园酒店举行&#xff0c;全国的 .NET 大咖相聚上海。这次我演讲的主题是《Visual Studio Code —— .NET 开发利器》。除了聊了聊韩老师开发的 .NET Core Test Explorer&#xff0c;还重点聊了聊 Visu…

开源性能监控工具APM之Skywalking和Pinpoint的实测对比

作者&#xff1a;zollty&#xff0c;资深程序员和架构师&#xff0c;私底下是个爱折腾的技术极客&#xff0c;架构师社区合伙人&#xff01;零&#xff0c;什么是APM&#xff1f;APM&#xff08;ApplicationPerformance Management&#xff09;是一种应用性能监控工具&#xff…

.Net Core 3.1,这匹黑马,2020年值得所有程序员重视!

强人掌舵 重回巅峰2014年萨蒂亚纳德拉接棒史蒂芬鲍尔默成为微软掌门人&#xff0c;五年的时间&#xff0c;纳德拉将夕阳西下、停滞不前的微软重新带回巅峰状态。2019年&#xff0c;微软今年挤下苹果&#xff0c;成为2019年全球市值最高企业&#xff0c;终止苹果过去7年来的龙头…

为什么你没有选择xamarin?

点击上方“dotNET全栈开发”&#xff0c;“设为星标”加“星标★”&#xff0c;每天11.50&#xff0c;好文必达全文约900字&#xff0c;预计阅读时间11分钟注&#xff1a;本篇文章只是关于xamarin的一个分享&#xff0c;没有xamarin技术深入的地方2019 年&#xff0c;注定会是 …

新款 Azure .NET SDK 如何设定 Content-Type

点击上方蓝字关注“汪宇杰博客”导语前不久我写了一篇《尝鲜新版 Azure .NET SDK》之后&#xff0c;使用了一段时间发现没爆&#xff0c;于是今天决定把博客的图片存储从旧版 SDK 迁移到新版 SDK&#xff0c;结果小收福报。Content-Type上传到 Azure Blob 的文件必须设置正确的…

聊聊程序员的成长与价值提升

一、 回顾我的职场体会我的职场生涯开始于十年前&#xff0c;一直在中小企业发展&#xff0c;未曾有幸到沿海那些高速发展的互联网公司工作&#xff0c;也就错过了互联网的大时代。但这不影响我的正常工作生活&#xff0c;事实上无论你身在何处&#xff0c;或在哪家公司&#x…