1

I've written or rather attempted to plot the free space Schrodinger equation in C# using ZedGraph and encountered a System.OutOfMemoryException error while running the created executable.

************** Exception Text **************
System.OutOfMemoryException: Exception of type 'System.OutOfMemoryException' was thrown.
   at System.Collections.Generic.List`1.set_Capacity(Int32 value)
   at System.Collections.Generic.List`1.EnsureCapacity(Int32 min)
   at System.Collections.Generic.List`1.Add(T item)
   at ZedGraph.PointPairList.Add(Double x, Double y)
   at Wavepacket.Form1.CreateGraph(ZedGraphControl schrodinger) in C:\Users\user1748005\Documents\Visual Studio 2010\Projects\Wavepacket\Wavepacket\Form1.cs:line 72
   at Wavepacket.Form1.Form1_Load(Object sender, EventArgs e) in C:\Users\user1748005\Documents\Visual Studio 2010\Projects\Wavepacket\Wavepacket\Form1.cs:line 35
   at System.Windows.Forms.Form.OnLoad(EventArgs e)
   at System.Windows.Forms.Form.OnCreateControl()
   at System.Windows.Forms.Control.CreateControl(Boolean fIgnoreVisible)
   at System.Windows.Forms.Control.CreateControl()
   at System.Windows.Forms.Control.WmShowWindow(Message& m)
   at System.Windows.Forms.Control.WndProc(Message& m)
   at System.Windows.Forms.ScrollableControl.WndProc(Message& m)
   at System.Windows.Forms.Form.WmShowWindow(Message& m)
   at System.Windows.Forms.Form.WndProc(Message& m)
   at System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m)
   at System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m)
   at System.Windows.Forms.NativeWindow.Callback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)

The necessary functions/ constructors for my Cmplx class are relatively straightforward and are as such:

    public Cmplx(double r, double i)
    {
        this.real = r;
        this.imag = i;
    }

    public double Real
    {
        get { return this.real; }
        set { this.real = value; }
    }

    public double Imag
    {
        get { return this.imag; }
        set { this.imag = value; }
    }
    public Cmplx Multiply(Cmplx b)
    {
        return new Cmplx((this.real * b.real - this.imag * b.imag), (b.imag * this.real + this.imag * b.real));
    }

    public Cmplx Divide(Cmplx b)
    {
        return new Cmplx((this.real * b.real + this.imag * b.imag) / (b.real * b.real + b.imag * b.imag), (b.real * this.imag - this.real * b.imag) / (b.real * b.real + b.imag * b.imag));
    }

    public Cmplx Scale(Double b)
    {
        return new Cmplx(this.real * b, this.imag * b);
    }

    public double Mod()
    {
        return Math.Sqrt(this.real * this.real + this.imag * this.imag);
    }

    public Cmplx Sqrt()
    {
        double r, theta;
        r = this.Mod();
        theta = this.Arg();

        return new Cmplx(Math.Sqrt(r) * (Math.Cos(theta / 2)), Math.Sqrt(r) * Math.Sin(theta / 2));
    }

    public Cmplx Exp()
    {
        double x, y, z;
        x = Math.Exp(this.real);
        y = Math.Cos(this.imag);
        z = Math.Sin(this.imag);

        return new Cmplx(x * y, x * z);
    } 

Below are my ZedGraph methods with only the CreateGraph method modified from the Codeproject ZedGraph tutorial:

    public Form1()
    {
        InitializeComponent();
    }

    private void Form1_Resize(object sender, EventArgs e)
    {
        SetSize();
    }

    private void SetSize()
    {
        zedGraphControl1.Location = new Point(10, 10);
        zedGraphControl1.Size = new Size(ClientRectangle.Width - 20,
                                ClientRectangle.Height - 20);
    }

    private void Form1_Load(object sender, EventArgs e)
    {
        CreateGraph(zedGraphControl1);
        SetSize();
    }

    private void CreateGraph(ZedGraphControl schrodinger)
    {
        GraphPane myPane = schrodinger.GraphPane;

        myPane.Title.Text = "Free Space Schrodinger Equation)";
        myPane.XAxis.Title.Text = "Time (s)";
        myPane.YAxis.Title.Text = "Psi";

        double alpha, beta, norm, k0, t;
        double L,N;

        L = 25;
        N = 4096;
        alpha = 0.5;
        beta = 0.5785;  
        k0 = 1;
        t = 0;
        norm = (Math.Exp(-k0 * k0 * alpha)) * (Math.Pow((alpha / (2 * Math.PI)), 0.25));

        PointPairList list1 = new PointPairList();

        for (double i = -L; i <= L; i -= (-2L) / N)
        {
            Cmplx gamma = new Cmplx(alpha, beta * t);
            Cmplx a = new Cmplx(2 * alpha * k0, 0);
            a.Imag = i;
            Cmplx b = a.Multiply(a);
            Cmplx phi = (((b.Divide(gamma.Scale(4))).Exp()).Scale(norm)).Divide(gamma.Sqrt());
            list1.Add(phi.Mod(),i);
        }

        LineItem myCurve = myPane.AddCurve("t=0",
              list1, Color.Red, SymbolType.Default);
        schrodinger.AxisChange();
    }

I've changed the

list1.Add(phi.Mod(), i); 

line within the for loop of the above code block to a

Console.WriteLine("{0}, {1}", phi.Mod(), i); 

and this works as expected albeit within a command-line interface. The Windows Form Application using the ZedGraph library results consumes ~1.7GB of RAM before throwing the aforementioned exception.

I've found an instance where ZedGraph is running out of memory by plotting massive amounts of data points

Charting massive amounts of data

However I'm less inclined that my plot of a meagre 4096 data points would lead to such consumption of memory and would rather fault my (lack of) programming skills

NB: This is an academic assignment so any help provided should take that into account. Cheers!

EDIT: Fixed the initialization of L and N as ints rather than doubles. Problem still persists as aforementioned.

EDIT2 I am an idiot. I changed the initialization of L and N to doubles within my test CLI project but failed to update the source code of the Windows Form Application. Thanks to Jeppe Stig Nielsen for pointing me in the right direction.

Community
  • 1
  • 1

1 Answers1

0

Check your for loop. It looks like there's one minus (-) too many.

Also, your division (-2*L) / N (an asterisk * missing) will give zero because it's an integer division. To fix that, cast one factor to double, or simply write:

2.0 * L / N

Note that .0 denotes a floating-point number (System.Double), and this will force the whole computation of the "step" to be performed with floating-point as desired.

To sum up: If your step is either zero, or goes in the wrong direction, you will keep adding points to list1 until you run out of memory. Maybe this for loop is better (but test it yourself):

for (double i = -L; i <= L; i += (2.0 * L) / N)
Jeppe Stig Nielsen
  • 60,409
  • 11
  • 110
  • 181
  • I assumed the issue was with the for loop i.e. not terminating correctly, but the ouput file from the console application shows otherwise i.e. initial entry: 1.44107617141494E-136, -25 -- final entry: 1.44107617141494E-136, 25 which shows the for loop works fine. Also sorry, I copied the previous version of the initilization of L and N as ints (should be doubles). Updated OP above. Problem still persists with that change regardless. – user1748005 Oct 15 '12 at 19:32
  • @user1748005 As the `for` loop is written above, it will not compile. You miss an asterisk `*`. It is possible that your `for` loop is OK, but that's hard to guess if you don't post **the correct version of your code**. One can easily see from the stack trace you give, that the problem is that you add too many points to `list1`. The underlying `List<>` runs out of memory when it tries to resize to accomodate all those points. – Jeppe Stig Nielsen Oct 15 '12 at 19:54
  • Sorry for the confusion. It's been a long day and my concentration hasn't been quite top-notch thus far - see OP for more information on what mistakes I did. Interestingly the code compiles sans asterisk and performs the similar calculations as that with the asterisks. When I hover over the initialization of variables in VS 2010, it displays it as a System.Int32 when I declare it as an integer and a System.Double when declared as a double; so I see what you're mentioning. I'll certainly adhere to that in the future. – user1748005 Oct 15 '12 at 20:11