"Python for Computational Science" Software on Windows/Cygwin

Last update: Mai 10, 2005

Author: Anette Johnsrud (anettej at ifi.uio.no)


1. Introduction

This page contains detailed instructions for installing the sofware you need in for the book "Python Scripting for Computational Science", by H. P. Langtangen, on Windows systems. The simplest way of getting all the recipes in book to work on Windows, especially the mixed language programming examples, is to use Cygwin, which is a Unix/Linux-like environment on Windows. Of course, you may run the scripts from the book directly on Windows, but if you apply Enthought's excellent Python distribution, the binaries are compiled with Visual C++, and if do not have Visual C++ (say only the GNU compiler set for Windows), the Python-C/C++ examples do not work.

If you already have Cygwin installed on your machine, you can still follow the steps below. The setup program, which is used to manage the Cygwin installation, "knows" which packages of Cygwin you have in your previous installation. That is, information on installed packages is kept in the /etc/setup/ directory of your Cygwin installation. So do not worry about starting from scratch.

2. Installing Cygwin

2.1 What is Cygwin

Cygwin is a free collection of libraries and tools, which provides a Unix/Linux like environment to the Windows platform. It works with all x86 versions of Windows since Windows 95. How much disk space Cygwin requires depends on what you choose to install, but a full installation (not including package archives and source code) requires more than 800 MB. The C, C++ and Fortran compilers that we are going to download with Cygwin are the GNU compilers; gcc, g++ and g77. We will also download pre-compiled Python. Go to www.cygwin.com for more information.

2.2 Get the Cygwin Setup program

Click here or go to www.cygwin.com and click on the icon "Install Cygwin Now".
The dialogue asks you to save or run the file. I recommend that you lagre/save it on disk first (NOTE: some of the dialog boxes below are dumped from a Norwegian version of Windows XP - hopefully you can recognize what the icons and the standard buttons mean...):

cygwindownload_1

cygwindownload_2

cygwindownload_3

2.3 Installing Cygwin

Go to the directory where you saved the setup.exe file and run it:

cygwindownload_4

Select Neste/Next and then "Install from Internet":

cygwindownload_5

Select Neste/Next and then specify the directory where you want Cygwin to be installed. Select the options "Install For" Just Me and "Default Text File Type" Unix:

cygwindownload_6

Select Neste/Next and a temporary directory for Cygwin to install the installation-files:

cygwindownload_7

Select Neste/Next and then "Direct Connection":

cygwindownload_8

Select Neste/Next. Choose a mirror site for downloading and select Neste/Next:

cygwindownload_9

2.4 Select packages

Now it's time to choose packages! The setup program creates a window like the one below, which contains all available packages that you can choose to download with Cygwin:

cygwindownloadpackage_1

All packages are grouped into categories (note that many packages are listed in more than one category). By default, the setup program will only install the packages in the Base category which results in a minimal Cygwin installation.
Click on the '+' next to a category to expand it:

cygwindownloadpackage_2

We will not explain the different categories and their contents in detail, but only concentrate on the necessary ones for the INF5660 course. Like shown on the screenshot below, you can easely change the presentation of the packages/categories by clicking on the View button. For more information go to www.cygwin.com.

The C, C++ og Fortran compilers are found under the Devel category:

cygwindownloadpackage_3

Select the C-compiler (gcc-core) by double-clicking on it. You will see that it changes from skip to 3.3.3 (or some other version available at the time of downloading). If you also want the source code, click in the Src field. Follow the same procedure with the C++ and Fortran compilers (gcc and g77, g stands for GNU):

cygwindownloadpackage_4

In the Doc category you can see that setup.exe has selected the cygwin documentation. This contains useful cygwin man-pages. You may unselect it by double-clicking: (it will change from from 1.4.2 (or other version) to Skip ):

cygwindownloadpackage_5

You would propably want some editors. These can be found in the Editors category: (I chose emacs and xemacs)

cygwindownloadpackage_6

Expand the Interpreter category:

cygwindownloadpackage_7

Select Python as shown on the screenshot below:

cygwindownloadpackage_8

Although you can choose many different packages at this stage, we will stick with only the gcc, g++ og g77 compilers under the Devel category and Python under the Interpreter category for the purpose of this guide. If you later want to uninstall, install or upgrade packages you can just follow the steps above. The setup program "knows" which packages you already have within your Cygwin installation.

Select Neste/Next to start the downloading and installation of Cygwin and chosen packages. Be aware that this is a huge amount of data, so it might take a long time (took me 3 hrs on a 1Mb DSL):

cygwindownloadpackage_9

cygwindownloadpackage_10

cygwindownloadpackage_12

When the installation is finally finished, select Create icon on Desktop and Add icon to Start Menu. Then select Fullfoer/Finish:

cygwindownloadpackage_13

cygwindownloadpackage_14

2.5 Test Cygwin and installed packages

Start Cygwin (double click on the Cygwin icon or select it from your Start menu):

cygwindesktopicon

You will see a window (shell) as on the screenshot below:

cygwingui1

Command examples:
$ ls -l     (list files in current directory)
$ cygcheck -c     (list installed packages in alphabetic order)
$ cd c:     (change to C-directory)

Test the C compiler:

cygwinguicc

$ gcc --version     (compiler version)
$ gcc --help     (for a list of options)

Test the C++ compiler:

$ g++ --version     (compiler version)
$ g++ --help     (for a list of options)

Test the Fortran compiler:

$ g77 --version     (compiler version)
$ g77 --help     (for a list of options)

Test Python:

cygwinguipython

Examples code can be found here.

3. Numerical Python on Cygwin

3.1 Installing Numeric

Go to numeric.scipy.org and download Numeric-X.X.tar.gz (check INF5660 for required version), extract the archive to a temporary directory.
Install by starting a Cygwin shell, change to the directory and type:

    $ python setup.py install

cygwinnumeric1

cygwinnumeric3

Numeric is now built and installed to cygwinpath/usr/lib/python2.X/site-packages/, and you can easily import it into your Python script.

3.2 Test Numeric

Start Python from Cygwin and test for example the following:

    >>>from Numeric import sin
    >>>print "sin(1) = ", sin(1)

cygwinnumerictest

Examples code can be found here.

4. F2PY on Cygwin

4.1 Installing F2PY

Go to cens.ioc.ee/projects/f2py2e and download F2PY-2-latest.tar.gz and scipy_distutils-latest.tar.gz. Extract the archives to temporary directories. Install by starting a Cygwin shell, change to the scipy-directory (scipy must be downloaded and packed out) and type:

    $ python setup.py install

cygwinscipy

Follow the same procedure with f2py as for Numeric above:

cygwinf2py

4.2 Test F2PY

Test F2PY by typing $ f2py -ver (f2py -h for options and help):

cygwinf2pytest

Examples code can be found here.

5. SWIG on Cygwin

5.1 Installing SWIG

Go to www.swig.org/download.html and download swig-x.xx.x.tar.gz. Check INF5660 for required version.
Extract the archive, change to the directory and install by typing these commands:

    $ ./configure
    $ make
    $ make install

5.2 Test SWIG

Test SWIG by typing $ swig -version (swig -help for options and help):

cygwinswigtest

6. Example code

6.1 Fortran

Example 1: hello.f:

C file: hello.f:

C Simple fortran example

C Program name:

        program hello

C Variable declaration:

        integer x,n
        real y

C Print Hello from Fortran!, sin(number):

        write(*,*) 'Enter an integer'
        read(*,*) x
        y = sin(float(x))
        write(*,*) 'Hello from Fortran! The sin(',x ,') = ', y

C End of program:

        end
Compile and link: (creates hello.exe in current working directory)

$ g77 -o hello hello.f
Run the file:

$ ./hello
Enter an integer:
2
Hello from Fortran! The sin( 2) = 0.909297407
Example 2: factorial.f:

The program computes the factorial of entered integer. Compile and link as explained in the example above.

Run the file:

$ ./factorial
Enter an integer:
5
5!= 120
Example 3: array.f:

The program computes the sum of the elements in an array, and finds the minimum and maximum values.

6.2 F2PY

Example 1: stringfunction.f, fortranimport.py:

The function takes argument str (type string) to call a specified function:

C file: stringfunction.f

C subroutine myadd:

        SUBROUTINE func_str(a,b,str,sum)
        real*8 a,b,sum
        character*(*) str
Cf2py   intent(in) a
Cf2py   intent(in) b
Cf2py   intent(in) str
Cf2py   intent(out) sum
        external myadd, mysub_r, mysub_l, mymul

        if (str .eq. 'myadd')then
           call myadd(a,b,sum)
        else if (str. eq. 'mysub_r')then
           call mysub_r(a,b,sum)
        else if (str. eq. 'mysub_l')then
           call mysub_l(a,b,sum)
        else if (str. eq. 'mymul')then
           call mymul(a,b,sum)
        end if
        return
        end

C subroutine myadd:

        SUBROUTINE myadd(a,b,sum)
        real*8 a,b,sum
Cf2py   intent(in) a
Cf2py   intent(in) b
        sum = a+b
        return
        end

        SUBROUTINE mysub_r(a,b,sum)
    ... substraction from right: b - a ...

        SUBROUTINE mysub_l(a,b,sum)
    ... substraction from left: a - b ...

        SUBROUTINE mymul(a,b,sum)
    ... multiplication of a and b ...
Run f2py: (creates stringfunction.dll in current working directory)

$ f2py -c -m stringfunction stringfunction.f

Call from Python (python example: fortranimport.py):

>>> import stringfunction
>>> a=1; b=2
>>> print stringfunction.func_str(a,b,"myadd")
3.0
>>> print stringfunction.func_str(a,b,"mysub_r")
1.0
>>> print stringfunction.func_str(a,b,"mymul")
2.0
Example 2: fortranmath.f, fortranmathimport.py:

The script contains 6 functions which all takes an array as argument:

C file: fortranmath.f

SUBROUTINE myreverse(list,n,listout)
... array in reversed order ...

SUBROUTINE mysort_inc(list,n)
... sorts array in increasing order ...

SUBROUTINE mysort_dec(list,n)
... sorts array in decreasing order ...

SUBROUTINE mysum(list,n,sum)
... computes the sum of elements in array ...

SUBROUTINE myaverage(list,n,average)
... computes the average of elements in array ...

SUBROUTINE mymax(list,n,max)
... find the largest value in array ...

SUBROUTINE mymin(list,n,min)
... find the smallest value in array ...
Run f2py as explained in the example abow, and call from Python (python example: fortranmathimport.py):

>>> import fortranmath
>>> import Numeric
>>> a = Numeric.array([10,2,3,9,4,6])
>>> print "Array: ", a
Array: [10 2 3 9 4 6]
>>> print "Average: ", fortranmath.myaverage(a)
Average: 5.66666666667
>>> print "Min value: ", fortranmath.mymin(a)
Min value: 2.0
>>> print "Sorted increasing: ", fortranmath.mysort_inc(a)
Sorted increasing: [ 2. 3. 4. 6. 9. 10.]

6.3 C

Example 1: hello.c:

The program takes an integer as input argument and writes the sin of the value to the screen.

Compile and link (creates hello.app)

gcc -o hello.app -O hello.c -lm
Run:

$ ./hello.app 2
Hello from C!
The sin(2) = 0.909297
Example 2: array.c, array.h:

The program creates an array of entered numbers and writes the sum, average and sorted array to the screen.

Compile and link as explained in the example above. Run:

$ ./array.app 4.5 2.3 7 9 -1.2
You entered 5 elements: 4.5 2.3 7 9 -1.2
Sum of elements: 21.6
Average: 4.32
Sorted array: -1.2 2.3 4.5 7 9

6.3 C++

Example 1: array.cpp:

Compile and link (creates array.app)

$ g++ -o array.app array.cpp -lm
Run:

$ ./array.app
Enter length of array: 4
Enter 4 values:
1.2 5.6 2.3 7.8
Enter value to search for: 2.3
2.3 is index 2 in the array.
Example 2: array2D.cpp:

The program takes row and column dimensions of two arrays and its values from the console and computes the multiplication of these two arrays.

6.4 SWIG

Example1 and Example2 each contains a script called setup.py which uses Python's tool "Distutils" for compiling and linking the extension modules.

Example 1: example.c, example.i, setup.py, cimport.py:

/* file: example.c */

/* Global variables */
double MyDouble = 3.0;
char *MyString = "Hello from C!";

/* compute the sum of two numbers */
double cadd(double n, double m) {
return (n + m);
}

/* compute the average */
double caverage(double n, double m) {
double sum = cadd(n,m);
return (sum/2);
}

/* compute factorial of integer */
int cfact(int n) {
int i = 1;
while(n > 1){
i = i * n;
n = n - 1;
}
return i;
}
/* file: example.i */
%module example
%{
/*include header files here*/
%}

extern double cadd(double n, double m);
extern double caverage(double n, double m);
extern int cfact(int n);
extern double MyDouble;
extern char *MyString;
Run setup.py:

$ python setup.py build_ext
$ python setup.py install-platlib=.
Call from Python:

>>> import example
>>> mystring = example.cvar.MyString
>>> print mystring
Hello from C!
>>> cadd = example.cadd
>>> x = 4.0; y = 2.0;
>>> print cadd(x,y)
6.0
>>>
cimport.py contains tests for computing the cpu-time of factorials in Python vs factorials in C.

Example 2: Point.cpp, Point.h, Point.i, setup.py, classimport.py:

Testing with C++ class; contains different methods and constructors for class Point(x,y).

Call from Python:

>>> from point import *
>>> p1 = Point()
>>> p1.printpoint()
x=0, y=0
>>> p1.set(3.2, 4.5)
>>> p1.printpoint()
x=3.2, y=4.5
>>> p2 = p1;
>>> p1.isequal(p2)
true
>>> p3 = p1.add(p2)
>>> p3.isequal(p2)
false
>>>
Example 3: cnumpy.c, cnumpyimport.py, make_module.sh:

cnumpy contains a function "sumarray" which takes a numpy array as argument and returns the sum of elements in the array.

C code:

#include ‹Python.h›
#include ‹Numeric/arrayobject.h›
#include ‹math.h›

static PyObject *sumarray(PyObject *self, PyObject* args)
{
 PyArrayObject *array; /* C representation of Numeric array */
 int i,n; /* number of array entries */
 double result = 0.0;
 double* a; /* ptr to the NumPy array */

  /* parse the arguments */

  /* check that we have a one-dimensional array */

  /* check that the datatype is NumPy-float, (C double ) */

  /* compute the sum of elements in array */

  return Py_BuildValue("d", result);
}

/* Doc strings: */

/* Method table */

/* init */
Script for linking with the Python Library and building the module:

#file: make_module.sh
#!/bin/sh -x
root=`python -c 'import sys; print sys.prefix'`
ver=`python -c 'import sys; print sys.version[:3]'`
gcc -shared -o cnumpy.dll cnumpy.c -I$root/include/python$ver \
/lib/python$ver/config/libpython$ver.dll.a
Run: (creates cnumpy.dll in current working directory)

$ ./make_module.sh
Call from Python:

>>> from Numeric import *
>>> import cnumpy
>>> print dir(cnumpy)
['__doc__', '__file__', '__name__', 'sumarray']
>>> a = array([1,2,3,4,5,6,7,8], Float)
>>> print a
[ 1. 2. 3. 4. 5. 6. 7. 8.]
>>> sum = cnumpy.sumarray(a)
>>> print sum
36.0
>>>

Valid HTML 4.01!