假设一个polymer 链中有N个单体.我想用bead-spring模型来模拟它的运动.然而,没有应用周期性边界条件.因为,点的生成是这样的,它们永远不会越过边界.

所以,我写了下面的程序.

我用了100万步.能量并不像预期的那样波动.走了几千步后,曲线就完全变平了.

enter image description here

enter image description here

X轴为步数.Y轴是总能量.

有人能判断一下源代码,告诉我应该修改什么吗?

注:我特别关注计算polymer 总能量的函数.

算法可能不正确.

    public double GetTotalPotential()
    {
        double totalBeadPotential = 0.0;
        double totalSpringPotential = 0.0;

        // calculate total bead-energy
        for (int i = 0; i < beadsList.Count; i++)
        {
            Bead item_i = beadsList[i];
            Bead item_i_plus_1 = null;

            try
            {
                item_i_plus_1 = beadsList[i + 1];

                if (i != beadsList.Count - 1)
                {
                    // calculate total spring energy.
                    totalSpringPotential += item_i.GetHarmonicPotential(item_i_plus_1);
                }
            }
            catch { }

            for (int j = 0; j < beadsList.Count; j++)
            {
                if (i != j)
                {
                    Bead item_j = beadsList[j];
                    totalBeadPotential += item_i.GetPairPotential(item_j);
                    //Console.Write(totalBeadPotential + "\n");
                    //Thread.Sleep(100);
                }
            }
        }

        return totalBeadPotential + totalSpringPotential;
    } 

推荐答案

该应用程序的问题是,模拟(Simulation.SimulateMotion)与绘制计时器(SimulationGuiForm.timer1_Tick)并行在单独的线程中运行,并共享相同的状态(polymerChain),而没有任何同步/信令,因此完全跳过polymerChain的一些Mutations (未绘制),当模拟完成时(远远早于绘制完成),timer1_Tick将重新绘制相同的polymerChain.您可以通过将计数器添加到Simulation并在SimulateMotion中增加它来轻松判断:

public class Simulation
{
    public static int Simulations = 0; // counter
    public static void SimulateMotion(PolymerChain polymerChain, int iterations)
    {
        Random random = new Random();
        
        for (int i = 0; i < iterations; i++)
        {
            Simulations++; // bump the counter
            // rest of the code
            // ...

并将其签入timer1_Tick:

private void timer1_Tick(object sender, EventArgs e)
{
    // ...
    // previous code
    if (Simulation.Simulations == totalIterations)
    {
        // breakpoint or Console.Writeline() ...
        // will be hit as soon as "the curve goes totally flat" 
    }

    DrawZGraph();            
}

您需要以这样的方式重写应用程序:SimulateMotion要么在timer1_Tick使用的某个集合中存储迭代(基本上实现生产者-消费者模式,例如,您可以try 使用BlockingCollection,就像我在pull request中所做的那样),要么仅在呈现当前状态时执行其操作.

Csharp相关问答推荐

数组被内部函数租用时,如何将数组返回给ArrayPool?

为什么C#Bigbit不总是相同的比特长度?

是否可以使用EF—Core进行临时部分更新?

如何在C#中使用正则表达式抓取用逗号分隔的两个单词?

为什么任务需要在内部使用ManualResetEventSlim?

在命名管道上使用GRPC ASP.NET核心时如何配置命名管道权限

如何将ASP.NET Core 2.1(在.NET框架上运行)更新到较新的版本?

更改执行目录

Polly重试URL复制值

数据库.Migrate在对接容器重启时失败

如何避免在.NET中将日志(log)写入相对路径

如何在同一成员上组合[JsonPropertyName]和[ObservableProperty]?

使用未赋值的、传递的局部变量

如何解决System.StackOverflowException:抛出System.StackOverflowException类型的异常.&# 39;生成随机代码时发生异常?

使用DI实例化带有动态参数的服务?

Xamarin中出错.表单:应用程序的分部声明不能指定不同的基类

用于分钟和秒验证的MudTextfield的正则表达式掩码

客户端/服务器RPC如何处理全局变量?

ASP.NET核心中的验证错误-该字段为必填字段

方法加载时出现类型加载异常