3
\$\begingroup\$

The following C# source code creates a histogram of Maxwell-Boltzmann's distribution:

using System;
using System.Drawing;
using ZedGraph;

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
{
    private static double KB = 1.38064852e-23;

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

    public 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 MaxwellSpeed(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 Normalization
{
    public static int Normalize(double n_bins, double mu, double sigma, double gaussian)
    {
        var z = (mu - gaussian)/sigma;

        if (z > 3 || z < -3)
        {
            return -1;
        }
        else
        {
            return (int)((z + 3) * n_bins / 6d);
        }
    }
}

class Program
{
    static void Main(string[] args)
    {
        const double N = 1000000;
        int time = (int)N;
        int binsCount = 51;

        Random rand = new Random();
        int[] bins = new int[binsCount];

        double mass = 14 * 1.67e-27;
        double T = 300;

        for (int i = 0; i < time; i++)
        {
            double gauss = MaxwellBolzman.MaxwellSpeed(rand, mass, T);
            double mu = MaxwellBolzman.MaxwellComponent(rand, mass, T);
            double sigma = MaxwellBolzman.MaxwellVariance(mass, T);

            int index = Normalization.Normalize(binsCount,  mu, sigma, gauss);

            if (index >= 0)
            {
                bins[index]++;
            }
        }

        PointPairList list = new PointPairList();
        for (int i = 0; i < bins.Length; i++)
        {
            list.Add(i, bins[i]);
        }

        PlotForm form = new PlotForm("Maxwell-Bolzman");
        form.AddBar(list, "Actual", Color.Blue);
        form.AxisChange();
        form.ShowDialog();
    }
}

enter image description here

Kindly, review the code.

N.B. The curve seems to be off the shape.

\$\endgroup\$

1 Answer 1

3
\$\begingroup\$

Static classes

You've (correctly) marked Normalization as static. You should do the same for every other class in your program - they are all currently being used as statics.

Expression bodies

C# has a wonderful bit of syntactic sugar - expression bodies - that lets you rewrite this:

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

as

public static double MaxwellVariance(double mass, double temperature) =>
    Math.Sqrt(KB * temperature / mass);

Classes

You're in C#, so you're stuck without the ability to have global functions. It's somewhat similar to Java in this way: it really pushes you to think about your code in an OOP style.

Going down this path, you would make a class to encapsulate your graph, which would take most of the code out of your Main. Potentially, everything up to and including the initialization of your point list could go in the constructor, and the PlotForm calls could go in a plot method. There are some advantages to this approach, including reusability, re-entrance, and testability.

As for MaxwellBolzman - I think you should refactor it to be a non-static class, with members for mass and temperature. random can be accepted as an optional parameter or the class could instantiate it itself. That will simplify many things:

  • Variance will turn into a one-line property with an expression body
  • Component and Speed will turn into parameter-less properties

Names

This is minor, but I find the Maxwell prefixes in all of the methods of MaxwellBolzman to be redundant; I think they would be even more legible if you simply named them Variance, Component and Speed.

Loops

I would find Speed more legible as

double sum = 0;
for (int i = 0; i < 3; i++) {
    double comp = Component;
    sum += comp*comp;
}
return Math.Sqrt(sum);
\$\endgroup\$
1
  • \$\begingroup\$ I think the curve is not drawn properly. \$\endgroup\$
    – user366312
    Apr 16, 2020 at 17:25

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.