分子 MC 模拟未平衡

Molecular MC simulation is not equilibrating

假设,聚合物链中有 N 个单体。我想使用 bead-spring 模型模拟它的运动。但是,没有应用周期性边界条件。因为,生成的点永远不会越过边界。

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

我正在使用 100 万步。能量没有像预期的那样波动。几千步后曲线完全平坦。

X轴是步数。 Y轴是总能量。

任何人都可以检查源代码并告诉我应该更改什么吗?

N.B。我特别关心计算聚合物总能量的函数。

可能算法不正确

    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) 没有任何 sync/signaling,所以 polymerChain 的一些突变被完全跳过(未绘制)并且当模拟完成时(远远早于绘图完成) 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 使用的某个集合中的方式重写您的应用程序(基本上实现 producer-consumer 模式,例如您可以尝试使用 BlockingCollection, like I do in the pull request) 或仅在呈现当前状态时执行其操作。