ILNumerics for Science – Computation and Visualization

How did you do that? – The Computation

Wrapping up our series of ILNumerics and science we take a closer look at computation and science. Easily code your science into a robust, reliable program with high-speed performance.

Science of Function Rules

Now that we’re 3 posts in this series I have to address something our support team and our development team told me to: Function Rules. These are important for computation in science because they speed things up.

We encourage everybody to follow these rules because it makes your code faster and more readable. If you follow the function rules you give the computation engine more information about the intended use of the arrays you declare. There are four types:

  1. Local arrays: They are declared and used only in the function scope. After leaving the function the memory is released and can be reused.
  2. Input arrays: These are the input parameters to a function. They are immutable and should be used only once when copied to a local array.
  3. Output arrays: With this option many different arrays can be returned to the calling function. In the calling function an array must be declared and passed to the called function.
  4. Return arrays: These arrays are the return values of functions. They are erased immediately after usage.

What I found most interesting are the output arrays. In the header of the function I can declare a number of output arrays. However, they are optional. When I call this function I don’t need to pass any of these to the function. If an output array is omitted that means that I’m not interested in this particular array. The function will then only calculate the arrays that I’m interested in and omit the rest of the code. This is a powerful tool to save development time and run time – and gets you back to science quicker.

Computation Module

Now, let’s get back to our 2D particle in a box. We still need to add the computation module. This is easily done by right-clicking on your WindowsFormsApplication in the solution explorer and adding the computation module. This will create a class called Computing_Module1 that is derived from ILMath. It comes with a few example functions where you can see some examples of the function rules.

Here is again the code that will calculate the wave function on a grid:

public static ILRetArray<double> CalcWF(int EVXID, int EVYID, double LX, double LY, int MeshSize)
{
   ILArray<double> X = linspace<double>(0, LX, MeshSize);
   ILArray<double> Y = linspace<double>(0, LY, MeshSize);
   ILArray<double> Y2d = 1;
   ILArray<double> X2d = meshgrid(X, Y, Y2d);
   ILArray<double> Z = sqrt(4.0 / LX / LY) * sin(EVXID * pi * X2d / LX) * sin(EVYID * pi * Y2d / LY);
   return Z.Concat(X2d,2).Concat(Y2d,2);
}

I put everything in one function here but will now separate the code into more than one function to show how the function rules should be applied. I’ll keep the CalcWF function and will add two more functions. One function will calculate the meshgrid and the other function will actually calculate the wave function values on the grid.

public static void getGrid(ILInArray<double> inX, ILInArray<double> inY, ILOutArray<double> outX2d = null, ILOutArray<double> outY2d = null)
{
   using (ILScope.Enter(inX, inY))
   {
      ILArray<double> X = check(inX);
      ILArray<double> Y = check(inY);
      outY2d.a = 1;
      outX2d.a = meshgrid(X, Y, outY2d);
      return;
   }
}

This piece of code generates the grid over which the wave function will be calculated. I obeyed all function rules here. Obviously, this is not really necessary for such a small problem but I wanted to show the best practice here. This function basically gives back two arrays, outX2d and outY2d. This is only possible with ILOutArray as functions can only return one object.

public static ILRetArray<double> getWF(int EVXID, int EVYID, double LX, double LY, ILInArray<double> inX2d, ILInArray<double> inY2d)
{
   using (ILScope.Enter(inX2d, inY2d))
   {
      ILArray<double> X2d = check(inX2d);
      ILArray<double> Y2d = check(inY2d);
      return sqrt(4.0 / LX / LY) * sin(EVXID * pi * X2d / LX) * sin(EVYID * pi * Y2d / LY);
   }
}

This function will calculate the values of the wave function on a given grid. Declaring the return value as ILRetArray will make sure that the array that is calculated in the last line will be thrown away after the function is executed.