C# 中的 N 体模拟

2024-03-10

我正在尝试使用 Runge Kutta 4 或 Velocity Verlet 集成算法在 C# 中实现 N 体模拟。

在我转向更多数量的粒子之前,我想通过模拟地球绕太阳的轨道来测试模拟,但是,由于某种原因,我得到的不是椭圆轨道,而是一个奇怪的螺旋。

我无法解决这个问题,因为我使用相同的算法对太阳系进行了更简单的模拟,其中太阳固定在位置并且一切都运行良好。积分器工作得很好,因为无论我使用哪一个,我都会得到螺旋。

任何帮助,将不胜感激。

这是代码:

class NBODY
{
    public static double G = 4 * Math.PI * Math.PI;

    class Particle
    {
        public double[] r;       // position vector
        public double[] v;       // velocity vector
        public double mass;    

        //constructor
        public Particle() {}
        public Particle(double x, double y, double z, double vx, double vy, double vz, double m)
        {
            this.r = new double[3];
            this.v = new double[3];

            this.r[0] = x;
            this.r[1] = y;
            this.r[2] = z;
            this.v[0] = vx;
            this.v[1] = vy;
            this.v[2] = vz;
            this.mass = m;
        }

        public void Update(Particle[] particles, double t, double h, int particleNumber)
        {
            RungeKutta4(particles, t, h, particleNumber);
        }

        private double acc(double r, Particle[] particles, int particleNumber, double[] r_temp, int l)
        {

            // dv/dt = f(x) = -G * m_i * (x - x_i) / [(x - x_i)^2 + (y - y_i)^2 + (z - z_i)^2]^(3/2)

            double sum = 0;

            switch (l)
            {
                case 0:
                    for (int i = 0; i < particles.Length; i++)
                        if (i != particleNumber)
                            sum += particles[i].mass * (r - particles[i].r[l]) / Math.Pow( Math.Pow(r - particles[i].r[l], 2)
                                + Math.Pow(r_temp[1] - particles[i].r[1], 2) + Math.Pow(r_temp[2] - particles[i].r[2], 2), 1.5);
                    break;

                case 1:
                    for (int i = 0; i < particles.Length; i++)
                        if (i != particleNumber)
                            sum += particles[i].mass * (r - particles[i].r[l]) / Math.Pow(Math.Pow(r - particles[i].r[l], 2)
                                + Math.Pow(r_temp[0] - particles[i].r[0], 2) + Math.Pow(r_temp[2] - particles[i].r[2], 2), 1.5);
                    break;

                case 2:
                    for (int i = 0; i < particles.Length; i++)
                        if (i != particleNumber)
                            sum += particles[i].mass * (r - particles[i].r[l]) / Math.Pow(Math.Pow(r - particles[i].r[l], 2)
                                + Math.Pow(r_temp[0] - particles[i].r[0], 2) + Math.Pow(r_temp[1] - particles[i].r[1], 2), 1.5);
                    break;
            }

            return -G * sum;
        }

        private void RungeKutta4(Particle[] particles, double t, double h, int particleNumber)
        {
            //current position of the particle is saved in a vector
            double[] r_temp = new double[3];

            for (int j = 0; j < 3; j++)
                r_temp[j] = this.r[j];

            //loop going over all the coordinates and updating each using RK4 algorithm
            for (int l = 0; l < 3; l++)
            {   
                double[,] k = new double[4, 2];

                k[0, 0] = this.v[l];                                                                //k1_r
                k[0, 1] = acc(this.r[l], particles, particleNumber, r_temp, l);                     //k1_v

                k[1, 0] = this.v[l] + k[0, 1] * 0.5 * h;                                            //k2_r
                k[1, 1] = acc(this.r[l] + k[0, 0] * 0.5 * h, particles, particleNumber, r_temp, l); //k2_v

                k[2, 0] = this.v[l] + k[1, 1] * 0.5 * h;                                            //k3_r
                k[2, 1] = acc(this.r[l] + k[1, 0] * 0.5 * h, particles, particleNumber, r_temp, l); //k3_v

                k[3, 0] = this.v[l] + k[2, 1] * h;                                                  //k4_r
                k[3, 1] = acc(this.r[l] + k[2, 0] * h, particles, particleNumber, r_temp, l);       //k4_v

                this.r[l] += (h / 6.0) * (k[0, 0] + 2 * k[1, 0] + 2 * k[2, 0] + k[3, 0]);
                this.v[l] += (h / 6.0) * (k[0, 1] + 2 * k[1, 1] + 2 * k[2, 1] + k[3, 1]);   
            }
        }

        /*
            Velocity Verlet algorithm:
            1. Calculate y(t+h) = y(t) + v(t)h + 0.5a(t)h*h
            2. Derive a(t+h) from dv/dt = -y using y(t+h)
            3. Calculate v(t+h) = v(t) + 0.5*(a(t) + a(t+h))*h
        */
        private void VelocityVerlet(Particle[] particles, double t, double h, int particleNumber)
        {

            double[] r_temp = new double[3];

            for (int j = 0; j < 3; j++)
                r_temp[j] = this.r[j];

            //loop going over all the coordinates and updating each using RK4 algorithm
            for (int l = 0; l < 3; l++)
            {
                //position
                this.r[l] += h * this.v[l] + 0.5 * h * h * acc(this.r[l], particles, particleNumber, r_temp, l);
                //velocity
                this.v[l] += 0.5 * h * (acc(r_temp[l], particles, particleNumber, r_temp,l)
                    + acc(this.r[l], particles, particleNumber, r_temp,l));
            }
        }     


    }

    static void Main(string[] args)
    {
        //output file
        TextWriter output = new StreamWriter("ispis.txt");

        // declarations of variables
        Particle[] particles = new Particle[2];
        particles[0] = new Particle(0, 0, 0, 0, 0, 0, 1);                  //sun
        particles[1] = new Particle(1, 0, 0, 0, 6.28, 0,  3.003467E-06);   //earth


        int N = 200;
        double h, t, tmax;
        double[,,] x = new double[particles.Length, N, 3];  //output


        //  setting initial values, step size and max time tmax
        h = 0.01;   // the step size in years
        tmax = h * N;

        // initial time        
        t = 0;

        int i = 0;

        while (t <= tmax) {

            //updates position of all particles
            for (int z = 1; z < particles.Length; z++)
                particles[z].Update(particles, t, h, z);

            //saves the position for output
            for (int j = 1; j < particles.Length ; j++)
                for (int z = 0; z < 3; z++ )
                    x[j,i,z] = particles[j].r[z];

            t += h;
            i++;
        }

        //output to file
        for (int k = 0; k < particles.Length; k++ )
        {
            for (int f = 0; f < 3; f++)

            {
                for (int l = 0; l < N; l++)
                    output.Write(string.Format("{0,-15:0.########},", x[k,l,f]));
                output.Write(string.Format("\n\n"));
            }
            output.Write(string.Format("\n\n\n\n"));
        }

        output.Close();
    }
}

这是地球轨道的输出数据图:


您的模型计算两个粒子之间的重力两次:对于第一个粒子,力基于其原始坐标,对于第二个粒子,力基于第一个粒子的更新位置。这明显违反了牛顿第三定律。在任何更新之前,您必须预先计算所有力。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

C# 中的 N 体模拟 的相关文章

  • 在 WCF 上重用我的 PagedList 对象

    问题 我有一个自定义集合PagedList
  • 信号与信号2

    我的应用程序可能会受益于使用 boost 的信号库之一而不是本土解决方案 该应用程序是多线程的 但执行信号处理的部分是单线程的 如果多线程不是问题 是否有任何理由更喜欢 Boost Signals2 而不是 Boost Signal Boo
  • Winform DatagridView 数字列排序

    我只使用一个简单的 DataGridView 来保存一堆数据 有趣的是 我在特定列中有小数 但是当按小数列排序时 它的排序是错误的 例如 起始顺序可能是 0 56 3 45 500 89 20078 90 1 56 100 29 2 39
  • 对 ExecuteNonQuery() 的单次调用是原子的

    对 ExecuteNonQuery 的单次调用是否是原子的 或者如果单个 DbCommand 中有多个 sql 语句 那么使用事务是否有意义 请参阅我的示例以进行说明 using var ts new TransactionScope us
  • 如何使用c#从数据桶中获取所有文档?

    如何获取数据桶中的所有文档 我尝试过一个示例 但我只能获得一个特定的文档 这是我的代码 CouchbaseClient oclient oclient new CouchbaseClient vwspace data bucket name
  • 如何使用 CUDA/Thrust 对两个数组/向量根据其中一个数组中的值进行排序

    这是一个关于编程的概念问题 总而言之 我有两个数组 向量 我需要对一个数组 向量进行排序 并将更改传播到另一个数组 向量中 这样 如果我对 arrayOne 进行排序 则对于排序中的每个交换 arrayTwo 也会发生同样的情况 现在 我知
  • 原子存储抛出错误

    我最近升级到了 C 11 兼容编译器 并且尝试将一些代码从 boost 更新到 c 11 标准 我在使用atomic store转换一些代码时遇到了问题 这是一些简单的测试代码 似乎会引发编译器错误 int main std shared
  • 如何在 C++ 和 QML 应用程序中使用 qrc?

    我在 Windows7 上用 c qnd Qt Creator QML 编写了 Qt Quick Desktop 应用程序 现在 我必须部署它 并且我需要隐藏 qml 文件和图像 意味着 将它们放入资源等中 我读到有一个很好的方法可以使用
  • 检查两个函数或成员函数指针的签名是否相等

    我编写了一些代码来检查自由函数的签名是否等于成员函数的签名等 它比较提取的返回类型和函数参数 include
  • 在 O(n) 时间内找到 n x n 矩阵中的局部最小值

    所以 这不是我的家庭作业问题 而是取自 coursera 算法和数据结构课程的未评分作业 现已完成 You are given an n by n grid of distinct numbers A number is a local m
  • 查找方法不适用于 EF6.1 模拟

    我已经使用这些 msdn 指南设置了模拟 使用模拟框架进行测试 EF6 及以上 http msdn microsoft com en us data dn314429 var bsAc db BusAcnts FirstOrDefault
  • 编程 Pearls - 随机选择算法

    Programming Pearls 第一版第 120 页介绍了从 N 个整数总体中选择 M 个等概率随机元素的算法 InitToEmpty Size 0 While Size lt M do T RandInt 1 N if not Me
  • 本地时间的内存需要释放吗?

    void log time t current time 0 tm ptm localtime current stuf 只是想确定 我是否需要在方法结束时释放 tm 指针分配的内存 不 你不应该释放它 该结构是静态分配的 检查文档 htt
  • 冒号在c中起什么作用?

    我在课堂上得到了这个例子 但我不确定它的作用 我知道冒号添加了一个位字段 但我仍然不确定这个问题 a b gt 0 3 1 运算符称为条件运算符 If b值为 gt 0 价值3被分配给a否则值1被分配给a 以 Kernighan Ritch
  • linq where 子句和 count 导致 null 异常

    除非 p School SchoolName 结果为 null 否则下面的代码将起作用 在这种情况下 它会导致 NullReferenceException if ExistingUsers Where p gt p StudentID i
  • 调试错误:在 vc++ 项目中使用 COM 时发生 所需的运行时?

    我为我的工作创建了一个 COM 组件 我也注册了该组件 在我的系统上 我有两个虚拟机工作站 在我的第一个工作站中 它运行良好 在我的第二个工作站中 它显示一个包含消息的错误框该程序需要一段时间并以不寻常的方式关闭 请联系应用程序管理员 我认
  • 在特定线程上运行工作

    我想要一个特定的线程 任务队列并在该单独的线程中处理任务 应用程序将根据用户的使用情况创建任务并将其排队到任务队列中 然后单独的线程处理任务 即使队列为空 保持线程活动并使用它来处理排队任务也至关重要 我尝试过几种实现TaskSchedul
  • 实体框架读取列但阻止其更新

    给定一个数据库表 其中有一列包含历史数据但不再填充 实体框架中是否有一种方法可以读取该列 但在使用相同的模型对象时防止它被更新 例如我有一个对象 public class MyObject public string CurrentData
  • 如何重用具有稍微不同的 ProcessStartInfo 实例的 Process 实例?

    我有以下开始的代码robocopy https technet microsoft com en us library cc733145 aspx as a Process 我还需要进行数据库查询以确定每次需要复制哪些目录robocopy被
  • 如何通过API退出Win32应用程序?

    我有一个使用 Win32 API 编写的 C Win32 应用程序 我希望强制它在其中一个函数中退出 有没有类似的东西Exit or Destroy or Abort 类似的东西会终止它吗 哎呀呀呀呀呀呀 不要做任何这些事情 exit 和

随机推荐

  • 通过连接字符串连接到远程数据库

    我正在尝试让我的程序从连接在同一 LAN 网络 内联网 中的另一台计算机读取访问数据库 这是我正在使用的代码 namespace CalUnderFoot public partial class Window1 Window CarsDB
  • Angular mat-selection-list,如何使单个复选框选择类似于单选按钮?

    如何使单个复选框选择mat selection list 类似于单选按钮 它接受一组值中的一个值 组件 gt 9 1 0 选择列表现在直接支持单选模式 将多个输入设置为 false 来启用它
  • 如何取消 NSBlockOperation

    我有一个很长的运行循环 我想在后台运行NSOperation 我想使用一个块 NSBlockOperation operation NSBlockOperation blockOperationWithBlock while not can
  • Swift 中处理窗口关闭事件

    如何使用swift处理窗口的关闭事件 例如询问 您确定要关闭表单吗 如果 是 则该表格将关闭 如果 否 该表格将不关闭 显示消息框对我来说不是问题 viewWillDisappear 也适用于最小化 但我只需要关闭事件 Thanks 就像上
  • 为什么 Laravel Redis::scan('*') 返回预期的键,但 Redis::keys('*') 没有返回?

    Problem 我使用 Python 代码向 redis 添加了一个值 当我尝试查询时使用 Laravel Redis get key name 它返回null Redis keys 返回使用 Laravel 但不使用 Python 创建的
  • limitTo 在 AngularJs 的 ng-repeat 中不起作用

    我正在为某些应用程序编写一些代码 我想限制聊天中的消息 this limitM 10 scope msgsCount contains the number of messages
  • 将复杂类型作为数据传递给 jquery ajax post

    我的数据模型类如下所示 DataContract public class Order DataMember public string Id get set DataMember public string AdditionalInstr
  • CF 标志的行为难以理解

    假设有一段代码 mov al 12 mov bl 4 sub al bl 在这种情况下 CF 0 标志 但在我看来它应该等于 1 因为减法运算是在加法运算上实现的 并且处理器不知道我们将其作为输入提供什么 无论是有符号还是无符号数字 它只是
  • 如何告诉窗体在关​​闭时不要释放特定控件?

    我想为我的子类表单对象编写一个函数 该函数必须关闭窗体并返回该窗体上的控件 以便我可以将其放在另一个窗体上 我无法阻止控件被处置 我认为使用 this Controls Remove someControl 从控件集合中删除它足以阻止它处置
  • Spring security中每个请求不同的csrf令牌

    我在用
  • 具有重载赋值的嵌套派生类型

    我有一个派生类型 wrapper 包含其他派生类型 over 对于后者 赋值运算符已被重载 由于派生类型的分配按默认组件方式发生 因此我希望分配两个实例wrapper将调用重载分配over在某一点 然而 使用下面的程序 情况似乎并非如此 仅
  • SelectById2 的指针标注

    我正在尝试将我在 VBA 中编写的一些代码移植到 Python 中以控制 Solidworks 特别是自动化草图编辑 我在 Python 中使用 Solidworks SelectById2 时遇到问题 在 VBA 中 以下代码工作正常 P
  • PHP continue 函数内

    这可能非常微不足道 但我一直无法弄清楚 这有效 function MyFunction Do stuff foreach x as y MyFunction if foo bar continue Do stuff echo output
  • Java 并发:Synchronized(this) => 和 this.wait() 和 this.notify()

    我非常感谢您帮助理解以下内容的 并发示例 http forums sun com thread jspa threadID 735386 http forums sun com thread jspa threadID 735386 pub
  • 计算时间跨度的最佳方法是什么

    在我的 C 程序中 我的要求是计算 foreach 循环内的业务逻辑执行的时间跨度 我必须存储时间跨度 我正在使用以下代码 for int i 0 i lt 100 i DateTime start DateTime Now Busines
  • Docker 信任初始化

    当对 tuf 上的公证人对 docker 内容信任的初始信任初始化时 我了解了 TUF 公证人和内容信任的工作原理 但我不清楚的是 最初的信任是如何建立的 我怎么知道第一次拉取没有受到损害并且初始 root json 是值得信赖的 例如 如
  • 使用foldr实现zip

    我目前正在阅读 Real World Haskell 的第 4 章 我正在努力理清思路根据foldr 实现foldl http book realworldhaskell org read functional programming ht
  • 寻找一种非“蛮力”算法来删除矩形集合的相交区域

    我有一个 n 大小的矩形集合 其中大部分彼此相交 我想删除相交并将相交的矩形减少为较小的非相交的矩形 我可以轻松地暴力破解解决方案 但我正在寻找一种有效的算法 这是一个可视化 原来的 处理 理想情况下 方法签名如下所示 public sta
  • 如何解决以下 SDK 版本报告了严重问题:com.google.android.gms:play-services-safetynet:17.0.0

    我在发布应用程序时收到此警告 play services safetynet 的开发商 com google android gms play services safetynet 已报告严重 版本 17 0 0 存在问题 在发布新版本之前
  • C# 中的 N 体模拟

    我正在尝试使用 Runge Kutta 4 或 Velocity Verlet 集成算法在 C 中实现 N 体模拟 在我转向更多数量的粒子之前 我想通过模拟地球绕太阳的轨道来测试模拟 但是 由于某种原因 我得到的不是椭圆轨道 而是一个奇怪的