如何实现麦克斯韦分布?

How can I implement Maxwell's distribution?

我需要解决以下问题(本文是从俄语翻译而来。因此,可能存在一些翻译问题):

... Another method to draw from the normal distribution is to draw two independent random numbers from the uniform distribution x1, x2 ∈ [0:0, 1:0). Then apply the following transformation:

resulting in two randomly independent numbers n1, n2 from a normal distribution with zero expected value and unit variance.

To change the distribution parameters to other parameters, e.g. the expected value for and the variance to, you should multiply the result of the draw by and add, i.e.

In the equation above, N(μ, σ) is a random variable with normal distribution with expected value μ and variance σ.

According to the Maxwell distribution, each component (x, y or z) of the velocity vector v is a random variable from a normal distribution with zero expected value, and variance

where m is the mass of the molecule, T is the temperature in Kelvin, kB is Boltzmann constant.

Your task: Draw 10,000 velocity vectors for the N2 nitrogen molecule at 300K. Calculate the average length of these vectors, and therefore the average value of the speed of the nitrogen molecule, using the formula:

public class Maxwell
{
    public double N1 { get; private set; }
    public double N2 { get; private set; }
    public void Compute(Random random)
    {
        double x1 = random.NextDouble();
        double x2 = random.NextDouble();

        N1 = Math.Sqrt(-2 * Math.Log(x1)) * Math.Cos(2 * Math.PI * x2);
        N2 = Math.Sqrt(-2 * Math.Log(x1)) * Math.Sin(2 * Math.PI * x2);
    }
}

public class Program
{
    static void Main(string[] args)
    {
        Random r = new Random();
        Maxwell m = new Maxwell();
        m.Compute(r);

        double n1 = m.N1;
        double n2 = m.N2;

        //.....? 
    }
}

我不明白如何从 n1 和 n2 实现 N(μ, σ),以及如何从那里得到向量 v

有人能帮忙吗?

编辑:我是在的基础上实现的:

using System;

public class CommonDistributions
{
    public static double Uniform(Random random)
    {
        return random.NextDouble();
    }

    static double Gaussian(Random random)
    {
        return Math.Sqrt(-2 * Math.Log(Uniform(random))) * Math.Cos(2 * Math.PI * Uniform(random));
    }
    public static double Gaussian(Random random, double mu, double sigma)
    {
        return sigma * Gaussian(random) + mu;
    }
}

public class MaxwellBolzman
{
    static double KB = 1.38064852e-23;

    static double MaxwellVariance(double mass, double temperature)
    {
        return Math.Sqrt(KB * temperature / mass);
    }

    static double MaxwellComponent(Random random, double mass, double temperature)
    {
        double mu = 0.0;
        double sigma = MaxwellVariance(mass, temperature);

        return CommonDistributions.Gaussian(random, mu, sigma);
    }
    public static double Maxwell(Random random, double mass, double temperature)
    {
        double one = MaxwellComponent(random, mass, temperature);
        double two = MaxwellComponent(random, mass, temperature);
        double thr = MaxwellComponent(random, mass, temperature);

        return Math.Sqrt(one * one + two * two + thr * thr);
    }
}

public static class MainClass
{
    public static void Main(String[] args)
    {
        Random random = new Random();

        const int N = 10000;
        const int T = 300;//300K
        const double mass = 28.02;//28.02 g/mol

        double sum = 0.0;

        for (int i = 1; i < N; i++)
        {
            sum = sum + MaxwellBolzman.Maxwell(random, mass, T);
        }

        Console.WriteLine($"Maxwell-Boltzman = {sum/N}");

        string str = string.Empty;
    }
}

我不确定氮气 2 的温度值和质量。

如果有人能对代码发表评论就太好了。

在这种情况下要做的事情是考虑 "suppose I had a magic box that answered a specific question that I posed to it; what would the inputs and outputs of that box be?" 和 编写一个实现该框的方法

从最简单的盒子开始。没有输入,输出是一个介于 0 和 1 之间的均匀分布的数字:

static Random random = new Random();
static double Uniform() => random.NextDouble();

好的,现在我们的工具箱里多了一个新工具。我们的下一个魔法盒是什么?没有输入,输出是正态分布的数字,均值为零,标准差为一:

static double StandardNormal() =>
  Sqrt(-2 * Log(Uniform())) * Cos(2 * PI * Uniform());

我们还有另一个工具。我们可以用它建造什么?输入:均值和标准差,输出,具有该均值和标准差的正态分布数:

static double Normal(double mean, double sigma) =>
  sigma * StandardNormal() + mean;

好的,现在我们需要什么?作为质量和温度函数的方差:

static double KB = 1.38064852e-23;
static double MaxwellVariance(double mass, double temperature) => 
  Sqrt(KB * temperature / mass);

太好了,我们继续前进。现在我们需要什么?输入是质量和温度,输出是单个随机麦克斯韦速度分量:

static double MaxwellComponent(double mass, double temperature) =>
  Normal(0.0, MaxwellVariance(mass, temperature));

现在我们需要什么?表示向量的类型:

struct Vector
{
  public double X { get; }
  public double Y { get; }
  public double Z { get; }
  public Vector(double x, double y, double z)
  {
    this.X = x;
    this.Y = y;
    thiz.Z = z;
  }
}

接下来我们需要什么?一个随机向量:

static Vector MaxwellVector(double mass, double temperature) =>
  ...

你能从这里拿走吗?接下来你需要什么?同样,继续将其分解为单行。不要花哨。写出你看不懂的长代码是没有奖的。

这里的技巧是分而治之。对于这些问题,您几乎总是可以编写一个少于五行代码的方法来计算 一件事情 。这样做吧;每次只计算一件事,然后你的工具包中就有了一个新工具来计算下一件。此外,您拥有一组方法,其中每个方法 (1) 显然是正确的,因为它只是一行代码,并且 (2) 可测试!编写测试套件!


更新:问题已更新以实现其中的一些想法,看起来还不错。还有一个关于温度和质量的后续问题。

温度看起来不错; 300K。但是群众是完全错误的。说明说使用一个分子的质量,但您输入的是一摩尔分子的质量。

请记住,"mol" 类似于 "pair" 或 "dozen"。一对是两件事,一打是十二件事,一摩尔是大约 600000000000000000000000 事。显然,一个 N2 分子的重量不到 28 克。相反,600000000000000000000000 个 N2 分子重 28 克。

还请记住,质量和体积的公制单位完全是任意选择的。如果你把地球的周长除以 40 亿,做一个边长相同的立方体盒子,然后装满水,就是一克的质量。

我们选择了与 "mol" 关联的值,因为它具有 属性 相同种类分子的 mol 质量等于该分子的原子量(以克为单位)。所以这些小盒子中有 18 个有 1 mol 的水分子。使用摩尔质量只是为了方便,因为它使数字更多 "reasonably sized" 以达到我们的目的;通常我们习惯于考虑一些的水,而不是一些分子的水,但你的问题只涉及一万个分子,不是一万克。 所以你想要做的是用一摩尔的质量除以一摩尔的数量,得到一个分子的质量.

接下来要做的就是进行单位分析,确定质量是需要克还是千克!我们有 KB 的值 1.38E-23,维基百科有帮助地指出它的单位是焦耳每开尔文。我们如何使用它?我们取 KB*T/M 的平方根。平方根需要的单位是什么?它是速度的标准偏差,单位是米每秒,所以我们需要KB*T/M单位是米平方每秒平方。

  • KB 是每开尔文焦耳; T 是开尔文,所以 KB * T 的单位是焦耳。
  • 焦耳的单位是 千克 乘以平方米每平方秒。
  • 因此,要得到米的平方/秒的平方,我们需要除以 千克,而不是

所以你需要的是克/摩尔除以分子/摩尔得到克/分子,然后将其转换为千克/分子。

有道理吗? 养成对每个问题进行单元分析的习惯。当我在黑暗时代还是一名物理系学生时,这让我犯了很多错误。

旁白:说到单元分析,有一点需要注意:你的文字摘录称标准差方差,但标准差实际上定义为方差的平方根。这种用法非常常见,您需要根据上下文推断 "variance" 是否表示 "really variance",或者在本例中为标准偏差。

也就是说,文本 应该 说 "N(μ, σ) is a random variable with normal distribution with expected value μ and variance σ2." 或者应该说 "N(μ, σ) is a random variable with normal distribution with expected value μ and standard deviation σ." 请留意并谨慎阅读。

另外:您可能已经注意到我们表示分布的方式非常 "clunky"。感觉你必须做很多工作来表示相当简单的东西。我目前的研究是概率语言,这使得这类工作非常简单。在概率语言中,我们会像这样表示您的工作流程:

IDistribution<double> Speed(double mass, double temp)
{
  IDistribution<double> c = 
    Normal.Distribution(0.0, MaxwellVariance(mass, temp))
  double x = sample c;
  double y = sample c;
  double z = sample c;
  return Sqrt(x*x + y*y + z*z);
}
...
double mean = Speed(mass, temp).Mean(10000);

(如果这看起来像一个异步方法,其中 Task<T>IDistribution<T> 替换并且 awaitsample 替换,那是因为它是;异步和概率工作流可以作为协程实现。)

如果您对概率语言的主题感兴趣,我有一个温和但冗长的介绍,从这里开始:https://ericlippert.com/2019/01/31/fixing-random-part-1/