UIC USER'S LOCAL GUIDE TO

NCSA TMC CONNECTION MACHINES CM-5

MASSIVELY PARALLEL PROCESSOR

Version 4.02

F. B. Hanson

Laboratory for Advanced Computing

Department of Mathematics, Statistics, and Computer Science

University of Illinois at Chicago

851 S. Morgan; Room 322 SEO, MC 249

Chicago, IL 60607-7045

Electronic addresses:


WWWEB HomePage:

UIC Fall 1995 Course:

Web Source:

Table of Contents


Introduction to NCSA Connection Machine CM-5

The Guide

This User's Guide is intended to be a minimal, hands-on introduction to the University of Illinois at Urbana, National Center for Supercomputing Applications massively parallel Connection Machine CM-5 system.

The Massively Parallel Processor CM-5

The CM-5 are made by the Thinking Machines Corporation of Cambridge, Massachusetts. The CM-5 is the new generation model after the CM-2, so new that it the model names CM-3 and CM-4 were skipped over. The CM-5 has many SPARC based nodes with four proprietary vector units attached per node, using a ``Fat Tree'' architecture. The CM-5 was first installed in April 1992, but has been upgraded since.

CM-5 Organization

The CM-5 architecture is quite different from the CM-2, in that it can do computations using either SIMD and MIMD execution models. In terms of connections, the CM-5 is a ``Fat Tree'', with connections becoming thicker with distance from the processors.

CM-5 Processing Nodes and Vector Units

The CM-5 does not have weak bit processors like the CM-2, but the NCSA CM-5 has 512 powerful SPARC (Sun RISC, Reduced Instruction Set Computer) processors (32 MHz clock rate, 22 MIPS performance and 32MB RAM). There are 4 vector units (VUs) attached to each Sparc node, called a PN. There is 8MB memory per vector unit (comprising each node's 4X8MB=32MB; i.e., the VUs are also accelerators and the node MUs (Memory Units or Banks for both instruction and data spaces)). The VUs operate at 32MHz floating point as accelerators, but at 16MHz as memory units. The VUs actually come in pairs on proprietary chips, and each VU of a chip pair can access both memory units attached to the chip in one cycle so that the effective memory rate is 2X16 = 32MHz to match the computational rate. The PNs with 4 VUs each have a peak performance rating 128 MFLOPS per node and the 32MB RAM per node. The node peak bandwidth is 512MB/sec. Thus the NCSA CM-5 with 512 PNs and 2K VUs has a peak performance rating of 16 GFLOPS and total of 16 GB RAM memory. The CM-5 nodes have the ability to perform either 32-bit or 64-bit arithmetic. Each VU has 128 data registers if a 32-bit word size is used, but only 64 data register pairs for the 64 bit word size, i.e., 512KB data register memory per VU. Hence each VU can be configured as a vector register of length 16 single precision elements or 8 double precision elements. The CM Fortran and C* compilers automatically configure and use the VUs without explicit programming from the user. See the section on floating point arithmetic below for a description of the IEEE precision arithmetic.

CM-5 System Networks

The network tree has 4.5 levels at NCSA to accommodate 512 processing nodes (PNs). At the lowest level (Level 0), are the individual nodes (4**0=1). At the first level (Level 1), sets of four PNs (4**1=4) are connected via a Network Interface (NI) to the Control Network (CN) and Data Network (DN). The Control Network handles interprocessor (PN) synchronization, scans and broadcasting. The Data Network handles system I/O. A major feature of the CM-5 is the separation of the system network into Control and Data Networks to enhance performance. There is also a third network called the Diagnostic Network, implementing fault tolerance advances. The Control Processors (CPs) handle system work for the networks and the PNs. The CPs are more powerful SPARCs with 64MB RAM and 840MB HD memory. At each successive network level, sets of four lower levels are connected, up to the partial fifth level since 4**{4.5}=512 nodes. Specification from TMC indicate there can be as many as 16K nodes or 7 network levels. The network bandwidth increases with level in order to maintain the ``Fat Tree'' connectivity property. For more information, see NCSA CM-5 Technical Summaries .

CM-5 CMOST/UNIX Operation System

The CMOST CM-5 operating system is an enhanced UNIX system, that is time-shared as well as space-shared. The space-sharing is set by the system administrators at the NCSA console, by programming special CPs called Partitioned Managers (PMs) that manage the partitions of the 512 PNs. The partitioning is typical into sets such as {32,64,128,256} nodes or a single {512} node partition for dedicated, grand challenge level applications. Each PM manages one partition and also handles time-sharing of several jobs on the same partition. At NCSA the partitions accessed as the five Internet nodes cm5a, cm5b, cm5c, cm5d, cm5e. The PMs and other CPs also serve some of the functions of the Front/Ends (FEs) on the CM-2, e.g., by storing Front-End Arrays or subscripted arrays and by doing the some of the scalar computations. Sometimes the name (FE) is still attached to a (PM) in job output as an artifact left over from the CM-2. At NCSA, you are requested to use the Distributed Job Manager (DJM) script to execute CM-5 codes (DJM is a simpler to use job queueing script than NQS used on the C90.

CM-5 Compilation Server

At NCSA, your codes should be edited, linked and compiled on the designated compile server at Internet node cm5.ncsa.uiuc.edu. Do not even try compile on the partition managers (PMs) cm5a, cm5b, cm5c, cm5d, cm5e. Once compiled and linked, DJM using the jsub command should be used to schedule execution on a PM from the compile server cm5 scratch disk. (See the CM-5 file ). The message-passing model uses the CM message-passing communications library CMMD. The primary physical execution models are the node and vector unit models, which are turned on by either the -sparc or -vu node options of the cmf or cs commands, i.e., either disabling the vector units or using them.

CM-5 UniTree Hard Disk Storage System

The hard disk memory system on the CM-5 is the UniTree system, related to the Andrew File System (AFS). For more information, see
NCSA File Systems.

CM-5 Scalable Disk Array Mass Storage System

In addition, the CM-5 has a 130 GB Scalable Disk Array (SDA). The SDA is a parallel file system or high performance, expandable RAID (Redundant Array of Independent Disks) mass storage system. The SDA has a sustained performance rate of 12MB/sec. The SDA is scalable since the storage capacity and bandwidth scale linearly with the number of Disk Nodes. The Scalable File System (SFS) provides access to SDA.

CM Fortran CMF and Scientific Library

The Fortran cmf compiler is version 2.0, consisting of Fortran 77 with powerful Fortran 90 extensions to array notation and CM compiler directives on the CM-5. The cmf source must have an .fcm extension. The current compiler is slicewise-oriented, i.e., oriented toward array sections with direct access to the floating point units, rather than pure array oriented as with the prior PARIS, Parallel Instruction Set, fieldwise compiler that relies on both bit processors and the floating point units. Slice-wise compiling minimizes or eliminates the communication overhead between the floating point units and the bit processors, thus resulting in faster execution. The slice-wise oriented model is the model that carries over transparently to the CM-5 execution models. However, many PARIS features are still used in slicewise processing. The Scientific Library CMSSL is version 6.0.

CM Array Rules

For programming the CM-5, the important thing to remember is the fact that the CM-5 prefers processing arrays, which implies the primary programming rule: Scalar constructs are computed on the PM (Partition Manager front-end machines, while Fortran 90 array constructs are communicated from the PM machine to the PN (CM Processing Nodes) for computation. Hence, for optimizing performance on the Connection Machine, the programmer should transform as much of the code to Fortran 90 array constructs (there are some exceptions like ForAll loops, but array constructs are the most important optimizing feature of the CM-5. For more general information on the NCSA CM-5, see NCSA CM Users Guide.

NCSA Excellent Programming Recommendations

The goals in programming for the massively parallel processing CM-5 are In general, this instructor would prioritize these in the reverse order for most class applications.

Some NCSA Student CM-5 Rules

User Guide Hints

For those who are already familiar with Professor Hanson's UIC User's Guide to the NCSA Cray Vector Multiprocessors, you will find that the current guide is similar to the Cray guide, because the systems are basically UNIX systems. You need concentrate on the CM-5 UNIX extensions, mainly.
This mini-guide is meant to indicate "what works" primary for access through the IBM/CMS system by way of IBM Telnet. The guide also gives alternate methods for access from UNIX systems.
Connection Machine, CM, CM-2, CM-5, Scalable Disk Array, Data Vault, Paris, C*, CM Fortran *Lisp, CMMD, CMSSL, CMX11, CMost, Prism and CMAX are all trademarks of Thinking Machines Corporation. UNIX is a trademark of UNIX System Laboratories. Sun and Sun-4 are trademarks of Sun Microsystems, Inc. SPARC is a trademark of SPARC International, Inc. X Window System is a trademark of the Massachusetts Institute of Technology.
Computer prompts or broadcasts will be enclosed in double quotes (``,''), background comments will be enclosed in curly braces ({,}), commands cited in the comments are highlighted by single quotes (`,') {do not type the quotes when typing the commands}, and optional or user specified arguments are enclosed in square brackets ([,]) {however, do not enter the square brackets}. The symbol (CR) will denote an immediate carriage return or enter {ignore the blanks that precede it as in `[command] (CR)', making it easier to read; Warning: Do not type any of these notational symbols in an actual computer session}.

Return to TABLE OF CONTENTS?


Background References

  1. NCSA Connection Machine User's Guide, CM-5 Edition, October 1994. Click This NCSA user's-guide tells about the CM-5, access, documentation, use, programming, application software and other items.
  2. NCSA CM-5 Frequently Asked Questions (FAQ), Click These include FAQs on Hardware, Programming Writing, Timing, Performance, and Running Code.
  3. NCSA Other Information, Click
  4. MCS 572 CM-5 Class Code Examples, Click:
  5. Thinking Machines Corporation Manuals. For users, the following TMC manuals could be useful:
    • Connection Machine Model CM-5 Technical Summary
    • Connection Machine Parallel Instruction Set (CMD-PAR2)
    • Connection Machine Programming in C/Paris (CMD-C/PAR2)
    • CM-5 User's GUIDE or CM User's Guide (CMD-UG2)
    • Getting Started in CM Fortran (CMD-GSFOR)
    • CM Fortran Reference Manual (CMD-FOR-RM)
    • Getting Started in C* (CMD-GSC)
    • C* Programming Guide (CMD-C2)
    The TMC are probably very difficult to get from TMC these days due to financial difficulties. Professor Hanson some copies of some of the documents for browsing or short term loans and many can be found online.
  6. /usr/doc online document directories on CM5 Compile Server. These directories contain much documentation from TMC, but selectively installed by NCSA for users. These documents usually are more up to date than those on the CM-5 and more are available in better form, especially if in the Postscript format. Click
    Online compile server cm5 Documents in /usr/doc Links
    • cmfortran-postscript (main postscript directory)
      1. getstarted-jan1993 (Getting Started in CM Fortran, an introductory tutorial)
      2. usersguide-2.0-beta (CM Fortran User's Guide, a more advanced manual)
      3. refman-2.0-beta (CM Fortran Reference Manual, an even more advanced and detailed manual; see also the release notes in the same directory)
      4. utilref-2.0-beta (CM Fortran Utility Library Reference Manual, an even more advanced and detailed manual that lists the special CM Utilities)
    • cstar-7.1 (main Cstar or CM C directory)
      1. GETTING_STARTED (Getting Started in C*, an introductory tutorial)
      2. USERS_GUIDE (CM C* User's Guide, a more advanced user's manual)
      3. PROGRAMMING_GUIDE (CM C* Programming Guide, a more advanced programming manual)
    • djm_userguide (Distributed Job Management User's Guide form Minnesota, for using batch scheduling.)
    • dtm (Distributed Transfer Mechanism (DTM) Manual, for transfer large amount of data from NCSA back to the local site.)
    • cmax (CMAX manual for converting f77 to CM Fortran code.)
    • cmssl (CMSSL CM Scientific Subroutine Library, 2 volumes.)
  7. /usr/examples: online CM-5 examples directories on Compile Server. These directories contain many of the Getting Started and other examples. (Does not appear to be directly available through WWWeb, so you can just change to the directory given and copy (cp) to to your home directory or ftp to another computer for modification.) Here is a small selection of its subdirectories:
    • cmf (CMF Fortran Examples)
    • cstar (C* Examples)
    • cmssl (CMSSL Scientific Library Examples)
  8. W. Daniel Hillis, The Connection Machine, MIT Press, Cambridge, MA, 1985, (QA267.H487 1985 Math).
  9. W. D. Hillis and G. L. Steele, Data-Parallel Algorithms, Comm. ACM, vol. 29 (12), pp. 1170-1183, December 1986.
  10. D. Waltz, Applications of the Connection Machine, IEEE Computer Magazine, vol. 20 (1), pp. 85-97, January 1987.
  11. D. Waltz, C. Stanfill, S. Smith and R. Thau, Very Large DataBase Applications of the Connection Machine System, National Computer Conference 1987 and TMC Technical Report Series DR87-3, pp. 160-165, 1987.
  12. S. Karin and N. P. Smith, The Supercomputer Era, Harcourt Brace Jovanovich, 1987 {QA76.5 .K356 1987}.
  13. L. W. Tucker and G. G. Robertson, Architecture and Applications of the Connection Machine, IEEE Computer Magazine, vol. 21 (8), pp. 26-38, August 1988.
  14. D. C. Douglas, B. A. Kahle and A. Vasilevsky, The Architecture of the CM-2 Data Processor, TMC Technical Report Series HA88-1, 19 pages, 1988.
  15. K. K. Mathur and L. S. Johnsson, The Finite Element Method on a Data Parallel Computing System, Int. J. High Speed Computing, vol. 1 (1), pp. 29-44, 1989.
  16. R. G. Brickner and C. F. Baillie, Pure Gauge QCD on the Connection Machine, Int. J. High Speed Computing, vol. 1 (2), pp. 303-320, 1989.
  17. Guy E. Blelloch, Vector Models for Data-Parallel Computing, MIT Press, Cambridge, MA, 1990. (QA76.5.B5456 1990 Main).
  18. L. S. Johnsson, Data Parallel Supercomputing, Topics in Atmospheric and Oceanic Sciences, Springer, NY, pp. 231-259, 1990.
  19. P. Olsson and S. L. Johnsson, A DataParallel Implementation of an Explicit Method for the Three-Dimensional Compressible Navier-Stokes Equations, Parallel Computing, vol. 14, pp. 1-30, 1990.
  20. S. L. Johnsson and K. K. Mathur, Experience with the Conjugate Gradient Method for Stress Analysis on a Data Parallel Supercomputer, Int. J. Num. Methods in Engr., vol. 27, pp. 523-546, 1989.
  21. R. G. Brickner, CMIS Arithmetic and Multiwire NEWS for QCD on the Connection Machine, Nuclear Physics B, Proceedings Supplements Section, for Proc. Int. Conf. Lattice Field Theory, LATTICE '90, 4 pages, 1990.
  22. S. L. Johnsson and K. K. Mathur, Data Structures and Algorithms fo the Finite Element Method on a Data Parallel Supercomputer, Int. J. Num. Methods in Engr., vol. 29, pp. 881-908, 1990.
  23. J. Bailey, Implementing Fine-Grained Scientific Algorithms on the Connection Machine SuperComputer, TMC Technical Report Series TR90-1, 63 pages, 1990.
  24. P. J. Hatcher and M. J. Quinn, Data-Parallel Programming on MIMD Computers, MIT Press, Cambridge, MA, 1991 (QA76.5 H42 1991).
  25. H. H. Xu, F. B. Hanson and S.-L. Chung, Optimal data parallel methods for stochastic dynamic programming, in Proc. 1991 Int. Conf. on Parallel Processing, Vol. III Algorithms and Applications, pp. 142-146, August 1991.
  26. H. H. Xu, F. B. Hanson and S.-L. Chung, Data parallel solutions of dimensionality problems in stochastic dynamic programming, in Proc. 30th IEEE Conf. on Decision and Control, vol. 2, pp. 1717-1723, December 1991.
  27. Connection Machine Model CM-5 Technical Summary, Thinking Machines Corp. Document CMD-TS5, 1991.
  28. W. D. Hillis, What is Massively Parallel Computing, and Why is It Important, Daedalus: J. Amer. Acad. Arts and Sci., vol. 121 (1), pp. 1-15, Winter 1992.
  29. F. B. Hanson, D. J. Jarvis and H. H. Xu, Applications of FORALL-Formed Computations in Large Scale Stochastic Dynamic Programming, Proc. Scalable High Perf. Comp. Conf.: SHPCC-92, IEEE Computer Society, pp. 182-185, April 1992.
  30. H. H. Xu, D. J. Jarvis and F. B. Hanson, Parallel Data Vault Methods for Larger Scale Stochastic Dynamic Programming, in Proc. 1992 Amer. Control Conf., vol. 1, pp. 142-146, June 1992.
  31. C. J. Pratico, F. B. Hanson, H. H. Xu, D. J. Jarvis and M. S. Vetter, Visualization for the Management of Renewable Resources in an Uncertain Environment, Proc. Supercomputing '92, pp. 258-266, color plates p. 843, November 1992.
  32. G. Bell, Ultracomputers: A Teraflop Before Its Time, Comm. ACM, vol. 35 (8), pp. 26-47, August 1992.
  33. G. Zorpette, issue editor, Supercomputing: Teraflops Galore, IEEE Spectrum, vol. 29 (9), pp. 26-76 {see especially The Power of Parallelism, pp. 28-33}, September 1992.
  34. W. J. Kaufmann III and L. L. Smarr, Supercomputing and the Transformation of Science, W. H. Freeman and Co., 1992 {ISBN 0-7167-5038-4}.
  35. F. B. Hanson, C. J. Pratico, M. S. Vetter, and H. H. Xu, Multidimensional visualization applied to renewable resource management, Proc. Sixth SIAM Conference on Parallel Processing for Scientific Computing, vol. 2, pp. 1033-1036, March 1993.
  36. W. D. Hillis and B. M. Boghosian, Parallel Scientific Computation, Science, vol. 261 pp. 856-863, 13 August 1993.
  37. F. B. Hanson, J.-D. Mei, C. Tier and H. H. Xu, PDAC: A data parallel algorithm for the performance analysis of closed queueing networks, Parallel Computing, vol. 19, to appear, 14 pages in galleys, August 1993.
  38. W. D. Hillis and L. W. Tucker, The CM-5 Connection Machine: A Scalable Supercomputer, Comm. ACM, vol. 36 (11), pp. 30-40, November 1993.

Return to TABLE OF CONTENTS?


Sample Login to the NCSA CM-5 from UIC


rlogin Login from UNIX to CM-5)

For those students who have accounts on a Unix or other workstation computer, the remote login command `rlogin' will be a better way to access the NCSA CM-5 Compile Server `cm5', because using `rlogin' gives a better terminal emulation than `telnet' The format of the command is for the CM-5. has a UNIX operating system, it is essential that lower case be used here a in the Unix system you are accessing from; cm5.ncsa.uiuc.edu is the full Internet name for the NCSA CM-5 Compile Server (also a Sun Sparc Workstation); [ncsa-user-id] will be the NCSA user-id on the CM Compile Server cm5; the option `-l [ncsa-user-id]' in not necessary when a Unix account has the same name as the remote host account; when the option is omitted and the names are different, so just return and enter your correct `[ncsa-user-id]' to the `logni:' prompt and ignore the awkward situation the systems complaints; either way, the user will supply the password:}


PC telnet Login from the PC-Labs to the NCSA CM-5 The UIC computer center has PC-Labs in 2249f SEL, BGRC, BSB, SRC or in the Dorms (the latter with longer hours; in CMS type inform schedule consulting introduction phone for further information). The PCs in the PC-Labs have a PC version of telnet that will allow the user to communicate directly with NCSA or the ACRF and avoid the 3270 bottleneck on the IBM 3090 mainframe. Assuming that the PC is turned on and you have the DOS (Disk Operating System) hard disk drive (C) prompt and you want to access the NCSA CM-5 Compile Server (cm5) then enter:


Go next to Annotated NCSA CM-5 Sample Session.


Return to TABLE OF CONTENTS?



IBM Telnet Login from CMS to the NCSA CM-5

The logon procedure assumes you are successfully logged onto the CMS system on the UIC IBM 3090-300J Vector Facility running CMS/SP and MVS/SP under VM/XA. A fast and convenient line to the National Center for Supercomputing Applications (NCSA) in Urbana is the NSFNET (56K Baud speed) connection between UIC and UIUC using IBM TELNET (currently the IBMNET version) communications. This IBM Telnet connection will be in line edit mode rather than full screen transparent mode, because the connection is between an IBM/VM machine and an non-VM UNIX 4.3 BSD machine without a IBM 3270 type display terminal. The 3270 problem is complex: IBM places the non-universal terminal requirement on its system and the university or computer center does not have the resources to offer a 3270 telnet, called `tn3270', or proper terminals on the IBM system to solve the IBM created problem. This means that the UNIX full screen editor vi will not work, but that the UNIX line editor ex will work. Also, certain control sequences have to be modified (e.g. use \c (CR) and not Ctrl-c for UNIX interrupt; use the BACKSPACE key and not the Delete key). Follow this procedure: If you are going to be using IBM Telnet for CM-5 sessions frequently, you might consider defining some available Pf-keys in your CMS PROFILE EXEC and automatically getting the Telnet disk. In order to do this, `XEDIT' your `PROFILE EXEC A' (if it exists) by entering in CMS:

Return to TABLE OF CONTENTS?


Annotated NCSA CM-5 Sample Session


Login to the CM-5 Compile Server as before, for example, or use if it work on your UIC system, entering your `[NCSA-id]' and `[NCSA-password]' again. You might have to look ahead at Section UNIX and CM-SUNs Command Dictionary to more completely understand the following session. In this session, you will compile a code on one of your scratch disks and then execute the executalble module via the DJM (Distributed Job Manager queueing script system) and will get your output back on the Compile Server Scratch Disk. The suggested source code is the modified ``laplace.fcm'' Laplace Equation Solver program
      program laplace
code:  LaPlace solver sample program 
code:    From "getting Started in CM Fortran".
code:    Solution of LaPlace's equation on unit square.
code:    BC: f(x,1)=1, f(0,y)=f(x,0)=f(1,y)=2, 0<{x,y}>1.
code:    Initial interior starting iterate: f(x,y) = 0.
comment:  Need to include CMF timer utilities:
      include '/usr/include/cm/timer-fort.h'
      parameter(maxx=32,maxy=maxx)
      real f(maxx,maxy),df(maxx,maxy)
      real rms_error,max_error
      logical cmask(maxx,maxy)
      integer iteration

comment:  Clear and start timer 0.
      call cm_timer_clear(0)
      call cm_timer_start(0)
comment:  Initialize the mask for the interior points.
      cmask = .false.
      cmask(2:maxx-1,2:maxy-1) = .true.
comment:  Initialize f
      f = 2.
      f(:,maxy) = 1.
      where (cmask) f = 0.
comment:  Set dummy value for max_error.
      max_error = 1.
      iteration = 0
comment:  Iterate until max_error < 1.e-3 stopping criterion.
      do while (max_error.gt.1.e-3)
         iteration = iteration + 1
comment:  Compute df, the change at each iteration, and udate.
         df = 0.
         where (cmask)
            df = 0.25*(cshift(f,1,1) + cshift(f,1,-1)
     &         + cshift(f,2,1) + cshift(f,2,-1)) - f
         f = f + df
         endwhere
comment:  Compute RMS and Maximum errors.
         rms_error = sqrt(sum(df*df)/((maxx-2)*(maxy-2)))
         max_error = maxval(df,mask=cmask)
comment:  Output errors every 10th iteration
         if(mod(iteration,10).eq.0) then
            write(6,*) iteration,rms_error,max_error
         endif
      enddo
comment:  Stop and Print timer
      call cm_timer_stop(0)
      print*,'total CM5 time'
      call cm_timer_print(0)
comment:  Output final iteration count and errors (stopping criteria).
      write(6,*) iteration,rms_error,max_error
      stop
      end

is (re)run by first copying the source code from the file to the user's #2 scratch disk,say, as a dummy source file, because there is much more memory on the CM-5 scratch disks than on the home directory disks. This Laplace source code can also be obtained by clicking The primary CM-5 Sun Sparc Compile Server memory quota of 10MB, while CM executables or object files can be very multiple megabytes. If the 1MB is too small for you, you must use your scratch disk (limited to 400MB and files of 1MB or more can stay for 48 hours), the Archival System (UniTree) for short periods, or your UICVM disk or Unix disk for alternate storage.} {Here `~[NCSA-id]' is UNIX shorthand for [NCSA-id]'s home disk, while plain `~' without any '[NCSA-id]' is shorthand for your own disk. You can simplify the typing and remembering of your scratch disk by using the command:} {so that `${SCR}' is the environment value of the user's 2nd scratch disk which used to be in the default profile and infact the above command can be placed in the user's `.cshrc' C-Shell resource configuration file. Note that the reference `~/scratch2' is actually a link to the address `/scratch2/[NCSA-Login]'. You will also need a DJM script }
#!/bin/csh
#JSUB-nproc 32 
#JSUB-cpu 16sec
#JSUB-mem 32m
#JSUB-project rnk
#JSUB-stdout pgm.out
#
#  CAUTION:  JOB MUST BE SUBMITTED FROM A SRATCH DIRIECTORY
#            HOME DIRECTORY IS NOT BIG ENOUGH FOR *.o OR EXECUTABLE run
# This runs executable run from scratch directory in batch by DJM 
run
#  Look for stdout output pgm.out in scratch directory where submitted

{for executing the generic executable `run' in the user scratch directory. This DJM job script can also be obtained by clicking Caution: DJM is funny about paths, so has problem with the short-hand forms `~/scratch2' and `${SCR}' for the scratch directory, although the full path form `/scratch2/[NCSA-Login]' is fine. This DJM job script can be obtained by placing a copy to the user's CM5 home directory:} {Next, change directories to the scratch disk:} {Compile and Link the code by the CM Fortran command cmf:} {Check for finished job:} {When the compile job is done, the user gets the message "Done" if successful or "Exit" if not, in which case use must view with the vi editor (or your favorite UNIX editor) the compile listing (which is always a good idea anyway):} {When all errors are corrected and compiling again with `cmf' is successful, then send the batch job for execution on the CM5 by using the DJM job submit command `jsub' on the home directory copy of the DJM script:} {View the output file (defined as the stdout output `pgm.out' in the `cm5jsub.run' DJM script):} {Note that `cat vi pgm.out' can also be used to get a terminal listing, but the output will usually be too large. Finally, send what output you desire back to your more permanent home directory for saving:} {for instance), but you may also want to save the current source `pgm.fcm' and compiler listing `pgm.lis' in the same manner.

Some remarks: Use `cmf -cm5 -vu -O -c pgm.fcm' to only compile the CM Fortran source code `pgm.fcm' to optimized object code `pgm.o', but without the `-c' option no object file 'pgm.o' remains after compilation. For most scientific application the switch `-double_precision' should be used so that 64-bit precision arithmetic is implemented with single-precision (32-bit) code automatically converted by the compiler {note: there is no need to convert `real' to `real*8' or `double precision' statements.} The listing `pgm.lis' can be checked to determine if the code arrays have been stored in the CM (Connection Machine) or in the FE (Partition Manager (PM) Front-End) {the former is desirable, of course} by searching for the string `ARRAY', or for checking about communication allocation by searching for `COMMUNICATION'. If you had errors at this point you can use `ex pgm.fcm' or `vi pgm.fcm' to edit of or correct the source with the UNIX line editor EX (see below in Subsection EX Editor. You can remove files with `rm pgm.lis pgm.o run (CR)' if you wish. With PCLAB or Unix, the `vi' full screen editor in Subsection VI Editor can be used). Finally, you can log out of the CM-5 using:}

Return to TABLE OF CONTENTS?


ftp File Transfer between NCSA CM-5 and UIC


The fastest way to transfer files between UIC and NCSA is using the file transfer protocol, FTP, for transfers from UIC. The CM-5 Compile Server shares the same scratch Hard Disk file systems.

ftp File Transfers at UIC

At UIC the IBMNET version of FTP is used on CMS and it uses the following commands:
An alternate method of sending files is to use the CMS NOTE command and reading in the CMS file using the CMS GET command. This BITNET file transfer method can produce variable results, because CMS SENDFILE does not work for this purpose, BITNET expects a blank first line in the message and it depends on all the computer links between here and there. Also, since NCSA expects you to forward all your mail to the local site with a `.forward' file on all your NCSA accounts, your mail would bounce right back to you. Otherwise, begin with:

ftp File Transfers at NCSA CM-5 Compile Server

The file transfer protocol program on CM-5 (cm5) is a somewhat different version than the one on CMS. They are basically the same, but differ somewhat in syntax and vocabulary as follows (we use cm5 as an example):

ftp File Transfers from the PC-Labs

File transfer protocol (ftp) on a PC-Lab PC may not be practical for must users, due to lack of permanent storage. Transfer between CMS or UNIX and the may be more practical when you are accessing them with `telnet' from the PCs. The nearest Xerox PostScript printer to 2249f is SEL2263, while others are SEL2265, SEL2058 and SEO327. However, if the PC is your favorite medium, then use it as in the following subsection.

ftp File Transfers from UNIX

The file transfer protocol program at UNIX is a similar to file transfers at the NCSA cm5[?], because both have UNIX or extended UNIX operating systems, as discussed in the previous section. Also there are no IBM CMS to UNIX communications problems, except that the communication lines between UIC and NCSA go through the Computer Center computers.

Return to TABLE OF CONTENTS?


UNIX and CM SUNs Command Dictionaries

The CM Suns (UNIX+) manual is mostly on line `man - [command] (CR)' will yield information. This abridged CM Suns (UNIX+) dictionary is only intended to be a short enough list to get you started without being bewildered by the enormous UNIX manuals, but with enough commands to be able to do something useful. For more information use the `man' command or refer to the CM Suns manuals or refer to some of the UNIX texts. This guide assumes that the UNIX shell used is the common user shell called the C-SHELL or Command Shell with resource configuration file `.cshrc'. For other shells like `sh', 'ksh' and `bash' please refer to the man pages to verify that listed commands actually exist in those shells. Many of the following commands will work in UNIX. UNIX is a trademark of Bell Laboratories.
The format is ``[command] [generic operand] : [Definition.]'', along with a carriage return {(CR)} for each command. DO NOT FORGET that almost all UNIX commands must be in lower case. Do not attempt to learn all of this at once, but read some of it and try it out at an actual computer session.

UNIX Log In and Out Commands

UNIX Information Commands

CM Fortran CMF Compile and Execution Commands

UNIX Directory Commands

UNIX File Commands

UniTree Mass Storage System Subcommand Dictionary

The UniTree is a FTP Archive Server for the mass storage system of UNICOS. It is not a CM or Cray product, but comes from General Atomic Corporation. Also the root directory for the user `userid' is `/userid'. The maximum size UniTree file is currently a super 1GB for a soft quota and 1.2GB for the hard, or temporary (7 days) overflow, quota.
IMPORTANT CAUTION: If you have been given a UniTree password separately, then the first thing you should do before you ftp to the UniTree node `mss.ncsa.uiuc.edu' is change your UniTree (Andrew File System (AFS)) password at the password computer `space.ncsa.uiuc.edu' (also 'landrew.ncsa.uiuc.edu' can be used for changing your password):
``cm5>'' `rlogin space (CR)'
and just follow the same procedure at you did not the YMP. Note you must do this even if you originally assigned passwords were the same on UniTree and the CM. For accounts older than Unitree and no assigned UniTree password, then the user must go through the above password procedure in order to use UniTree ftp storage, and if still using the old userid number then the user must be prepared to switch to the new name.
Use
``cm5>'' `ftp mss (CR)'
to FTP from the NCSA mass store and works just like the UNIX version of FTP, except when removing files, the files not erased right away, but are put in the users UniTree trash directory `/u/ncsa/[userid]/.trash' and are erased after a number of minutes as determined by the command `quote site GTRSH' command below. When using ftp not at NCSA, such as ftp directly from a UIC computer then the full internet address `mss.ncsa.uiuc.edu' must be used.
A short list of UniTree FTP subcommands (Caution: many of the special subcommand of the UniTree FTP subcommands are in capitals) are given below: More information on UniTree can be obtained using `man unitree' on `uy' or the more complete NCSA UniTree User's Guide can be FTPed using `ftp ftp.ncsa.uiuc.edu' on your local site computer.

UNIX User Library Commands

The commands in this subsection are invoked by the user to save a set of compiled object files in a user library file, called an archive file, so that they can be called from a fortran or other program with out re-compiling.

UNIX Pipe and Redirection Commands

The commands in this subsection embody some of the powerful advantages of UNIX.

UNIX Mail Commands

UNIX Control-Key Commands

UNIX Terminal Environment Commands

UNIX Process Commands

UNIX Editor Commands


Return to TABLE OF CONTENTS?


The EX Editor


`Ex' is the UNIX line editor (`ed' is another UNIX line editor) and `vi' is the full screen editor that is disabled by IBM TELNET. The prompt is `:', but the user enters input at the bottom of the screen with IBM TELNET line mode. In `ex' `.' means the current line, `$' means the last line, and `%' means the whole range of lines `1,$'. `[L1],[L2]' denotes the range from line `[L1]' to line `[L2]'. The user may want to do major editing on the CMS multi-line editor XEDIT and send the file to the CM Suns using the FTP file transfer protocol. Some students may have had experience with this editor (or the similar `ed' editor) from EECS courses. These `ex' commands can be used within the `vi' editor by typing a colon `:' in front of the `ex' command, which is another reason for learning `ex' with `vi' when you have an account where `vi' can be used.

Return to TABLE OF CONTENTS?


The VI Editor


The UNIX full screen editor vi is a tightly designed editing system in which almost every letter has a function and the function is different for lower and upper case. However, a letter and its actual function are usually closely related. It is important to remember that the `Esc' escape key ends most functions and a `Esc,Esc' double application certainly ends the function with the ring of a bell. The subcommand `u' undoes the last function (presumably an error). Use `:q! (CR)' to end with out saving, especially in hopeless situations. Use `:wq (CR)' to resave and end {`ZZ' also resaves and ends, but will not resave if the file has been saved in another file and no further changes have been made}, or `:w (CR)' to only resave. The character `:' prompts the UNIX line editor `ex' which you can think of as being embedded in `vi'. Some of the above critical `vi' subcommands are repeated below with others. Most `vi' subcommands are not displayed when used and do not take a carriage return `(CR)'. The fact that most keys have a meaning both as single characters and as concatenations of several characters has many benefits, but has disadvantages in that mistakes can turn out to be catastrophic {remember that `Esc, Esc, u' key sequence!}. Some `ex' editor commands that are useful in `vi' follow the `:' prompt. See the previous subsection on `ex' for more commands.

Return to TABLE OF CONTENTS?


Interrupts Dictionaries for CMS and IBM Telnet


When you get `hung up' in a session it is extremely helpful to know which interrupts or mode change commands that can most effectively get you back to a normal session. Part of developing good skills for working with supercomputers is becoming ``super-killer'' of errant processes. This is particularly true for the IBM TELNET `pass-through' when most CMS terminal properties pass through in a top-down hierarchy from CMS to IBM TELNET to UNIX.

CMS Interrupts Dictionary

IBM Telnet Interrupts Dictionary

The default control character is `\'. Enter `?' or `help' after the `telnet:' prompt for more functions, such as commands for changing the defaults.
  • PF4-key {Interrupt an CM process and return to IBM TELNET; PF-5 to PF-15 also work; the command you will usually want to respond with is `quit (CR)'.}
  • (CR) {Re-connect to CM session from IBM TELNET, depending on what intervened after aborting a session.}
  • \d (CR) {Restart(?) login to CM if you made an error in `Username' or `Password' and receive the message ``User Authorization Failure''; really UNIX, but note placed here for convenience since you need to know it before the UNIX session.}

Return to TABLE OF CONTENTS?


Distributed Job Manager DJM for CM Batch Scheduling


The Distributed Job Manager (DJM) is a new job control system used for running batch or background job and also for interactive job management. It was developed by the AHPCRC and the Minnesota Supercomputing Center. It supercede the older and difficult to use Network Queuing System (NQS). With DJM, the user no longer has to figure out which queue to use. Batch scheduling is VERY IMPORTANT, because ordinary development runs are allowed weekdays from 9am to 7am and 12pm to 5pm on Saturdays. At other times you must use batch. For more information user `man [command]' or consult laplace.fcm for any user submitting from a scratch disk after copying it to the scratch disk:
---------------
cm5%  jsub cm5jsub.run
---------------
on the CM-5 Compile Server, `cm5'. In this script all the lines with a leading `#' not followed by a blank are shell commands, while the lines with `# ' denote lines of comments (blank alert!). The first line, with the `!' shell activator, identifies that the C-Shell will be used to interpret the shell. Lines 2-4 specify the `jsub' options of `32' sparc processors, a 5 minute CPU time limit, `128'MB of memory, that the accounrnk `rnk' should be charged, and that the output will be directed to the scratch disk of user `hanson' into the file `pgm.out'. The next 3 lines are comments, because a blank follows each leading `#'. The last line is gives the executable command for the job. The script can be converted to your use, by changing the user scratch directory `/scratch2/hanson' to your own scratch directory and the user account `rnk' to your own NCSA account, along with the output name `pgm.out' and executable name `run' to your own names. You can also change the options to any legitimate options. The user can also place the statement `setenv PSN [ncsa-account-number]' near the `alias' statements in the user's C-SHell resource configuration file `~/.cshrc'.
  • jdel -jid [jstat-job-id] (CR) : The `jdel' job delete command deletes or kills the user's own DJM batch job whose job-id `[jstat-job-id]' is shown by the `jstat' command.
  • job [DJM-job-command] (CR) : The `job' command can also be used to delete a DJM batch job, but it can do many other functions as can be seen from `man job'. {See also other DJM commands `jconnect' and `jwait'.}

    Return to TABLE OF CONTENTS?


    CM Fortran CMF Compile and Execution


    The CM-5 has its own extended version of the UNIX CM Fortran command called `cmf' rather than the standard SunOS UNIX `f77'. See the CM-5 manuals for more extensions, standard options and examples. See the manuals for complete information. To use CM timing subroutines and CM Utilities, you must include the following `include' statement in each CM Fortran program unit:
           include '/usr/include/cm/timer-fort.h'
    
    If CMF utilities will also be used, then the user must also
           include '/usr/include/cm/CMF_defs.h'
    

    CMF Compiler Options

    The format of the CM Fortran compiler command,
      `cmf [options] [input files] (CR)',
    permits a number of options that are preceded by a `-' sign and some of these are extensions for massively data parallel computations that are not available with the UNIX `f77'. The `cmf' command determines the type of a filename argument from its suffix and invokes an appropriate compiler or the linker. The CM Fortran compiler, the Sun Fortran compiler `f77', the Sun C compiler `cc', and the Sun assembler `as' are accessible. The linker `ld' combines object files with libraries to form an executable load module called `a.out'. The CM-5 compiler has two compiler modes or version, the vector unit version using the option `-cm5 -vu', the default, or the node version using the option `-cm5 -sparc' which disable the vector units except for the memory management function.
    • -c : Compiles, but suppresses the link step producing an object file like `pgm.o', without an executable file like `a.out' or `run'. Similarly, `cmf [fn1].o [fn2].o', without any option, only does the linking step for a set of object files. `cmf [fn].fcm' only does a non-optimized `f77' compile and link, producing a generic executable `a.out' and deleting the object file at the end, unless `cmf' fails before the link step.
    • -cm5 -vu : CM-5 vector unit (VU) compilation permits use of both vector unit functions of accelerating the computations and managing the 32MB node RAM memory; the problem arrays are automatically mapped to the VUs, at 4 VUs per node.
    • -cm5 -sparc : CM-5 processing node (PN) compilation disables use of vector unit function of accelerating the computations, but the VUs still manage the 32MB node RAM memory; the problem arrays are automatically mapped to the PNs, resulting is less distribution of the arrays.
    • -O : Perform optimization during compilation. (This takes effect in the CM Fortran compiler even if the `-g' option is also specified.)
    • -o [executable] : Name the executable file produced by the linker `output' rather than the default `a.out'. Note the space between `-o' and [executable].
    • -S : Produce an assembly language representation of each source file.
    • -[no]double_precision : Indicate whether to interpret the type specification REAL as double-precision data or single-precision data, if without `[no]'. The default `-nodouble_precision' is to regard REAL as single-precision data.
    • -[no]list : Species that a compiler informational source listing `[file].lis' will be produced for the source code `[file].fcm' if `-list', rather than the default `-nolist' option. The listing `[file].lis' is not as helpful as the Cray informational listing, but searching for the string `ARRAY' can show which code arrays have been stored in the CM (Connection Machine) or in the FE (Front-End) {the former is desirable, of course} and searching for the string `COMMUNICATION' can show information about communication allocation. If run-time-system errors have been directed to the listing file, they will be of the form:
        *** RTS-FATAL-UNIX: [error-message]
      and the `Traceback' should indicate the path to the place where the error occurred. See also the `cmdebug' option below.
    • -l[lib] : Add [lib] to the list of libraries to be searched during linking. All user libraries are searched before any system libraries; user libraries are searched in the order in which they appear on the command line. The arguments are passed to the `ld' linker, which searches the standard path (/usr, /usr/local, /usr/local/lib) for a library with the name [lib] to add to the list.
    • -g : Produce additional symbol table information for use by the `cmdbx' debugger. If you are not knowledgeable in the use of debuggers, then running subsets of your program can help you locate errors.
    • -pg : Produce profiling code. A run-time routine accumulates counts and a `gmon.out' file is produced. The linker searches profiling libraries instead of the standard libraries. An execution profile can then be generated by using `gprof'.
    • -[no]cmdebug : Produce additional symbol table information for use by the `cmdbx' debugger without `[no]'. When used with `-paris' switch, the `-cmdebug' acts just like `-g' switch. See a unusually readable section on `cmdebug' in Chapter 3 of the CM Fortran User's Guide or look in on the NCSA CM-5 Compile Server.
    • -q : Suppress messages describing the progress of the compilation or link.
    • -continuations=[number] : Specifies the maximum number of continuation lines in a Fortran statement. The number must be an integer value in the range 0 through 99; by default, a Fortran statement can be continued on up to 19 lines.
    • -[no]directive : Indicate whether comment lines that have the syntax of compiler directives should be processed as directives, or should be regarded as comments (i.e., if non-default `-nodirective' is used).
    • -fecommon : Specifies the default allocation of common arrays. Normally, the CM Fortran compiler allocates common arrays in CM memory. This switch changes the default allocation of common arrays to be in Front-End memory. Note a common array that has been allocated in Front-End memory cannot be used in an array operation.
    • -[no]extend_source : Extends the source line length to 132 characters from 72 characters. The default is `-noextend-source'.
    • -[no]implicit_none : The effect of this option is to require explicit declaration of all variable names appearing in the program. This option overrides IMPLICIT statements appearing in the program unit. The default is `-noimplicit_none'
    • -release_number : Indicate that release number of the compiler is to be used. This is useful when comparing the behavior of the current release of the compiler with the previous release.
    • -version : Print compiler and drive version.
    • -safety=[number] : This switch causes code be generated that performs some runtime checking. At level safety zero no runtime checking is performed. At level safety 10 all runtime safety checks are enabled. The default is
    • -serial-for-all : Force FORALL statements to be executed serially on the Front-End computer.
    • -show=include : Specify that the listing file is to contain text from INCLUDE statements in the source code. Normally, included text does not appear in the listing file.
    Note that compiled `C' code can be mixed with `CMF' code as long as the C variables are compiled as pointers in lower case. C compiling is done with the standard C `cc' command or the C* `cs' command. A sample correspondence between the two are:
           CMF                     C
         real R                  float* r
         double precision D      double* d
         integer I               int* i
         complex C               struct(float real, imag;)* c
         double complex CD       struc(double real, imag;)* cd
         call _SUB               sub
    

    Note the extra pre-underscore for a CMF reference to a C procedure. A Sun C passed procedure must also have a post-underscore in C.

    CMF Array Constructs and Constructors

    CMF Fortran includes Fortran77 plus array extensions, special CMF intrinsic functions, and CMF utilities. Recall that a computation must be in array notation to be calculated on the CM (except for FORALL statements), else the computation is performed on the Front-End. Also the left-hand-side array or section of an array and the terms in the right-hand-side expression of an assignment must be conformable, which means all terms must be an array of the same shape or must be an additive constant or a constant times a conformable array. In general, CMF referencing of an array element in an expression means that the expression will be computed on the slower Front-End. Note that array can be reference as array sections which are also arrays in which a least one subscript of an existing array is an subscript triplet of the form:
      [start]:[stop]:[stride]
    where `[start]' is the beginning subscript, `[stop]' is the ending subscript and `[stride]' is the step, which is optional if it is the default stride of unity. For instance
    c --------------------
         integer, parameter :: m=64,n=256 ! integer declaration with parameter
                                          ! attribute, i.e., 2 statements in one.
           ! a `!' in a CMF statement implies an inline comment to its right;
           ! except when in column 6 when it is the usual continuation character.
         real, array(m,n) :: a,b,p  ! real declaration with array attribute;
                                    ! the arrays declared to have the same shape.
         integer, array(5) :: c,d
         integer, array(3), data :: v=[-3,4,-5] ! array, data and constructor
          ! a(1,2) is a scalar element, to be computed on the FE.
          ! a(1,2:2) is an array section with shape [1], however.
          ! a(2,1:n) is an array section with shape [n].
          ! a(2:2,1:n) is an array section with shape [1,n].
            !  ****assume that the following areas are initialized.****
         b=a(1:m,1:n) ! a full array with shape [m,n], `a' is same as `a(1:m,1:n)'.
         a = 3.8*b + 5.7 ! conformable array expression => a(i,j)=3.8*b(i,j)+5.7
                         ! for all i,j.
         p = a**2 + 3*b ! conformable expression => p(i,j)=a(i,j)**2+3*b(i,j)
                        ! for all i,j.
         p = a*b ! conformable array expression => p(i,j)=a(i,j)*b(i,j)
                 ! for all i,j; note the element, not matrix, multiplication.
         do 1 i=1,m
           do 1 j=1,n
    1    a(i,j)=i+2*j  !subscript reference => Front-End calculation, entirely.
         c=[1,5,3,6,7] ! array constructor gives elements of c values 1,5,3,6,7.
         d=[1:10:2]    ! array constructor gives elements of d values 1,3,5,7,9.
         d=[1,[7:9],3] ! array constructors give elements of d values 1,7,8,9,3.
         d=[1,v,3]  ! array constructors give elements of d values 1,-3,4,-5,3.
         c=[1,2[3,5]] ! constructor with multiple giving d values 1,3,5,3,5.
         c=a(51:55,83) ! array c set equal to same shape array section of a.
         a = 5.1  ! Broadcast 5.1 from Front End to all elements of a.
         call subr(a(1:20,v)) ! Call subroutine `subr' with section a(1:20,v)
                              ! as subroutine arguments (note vector subscript).
         print*,c  ! => print*,(c(i),i=1,5)
    c --------------------
    

    CMF Fortran Intrinsic Functions

    The familiar Fortran77 intrinsic functions perform elementary numerical and mathematical operations on both scalars and arrays. Some of them are: MAX(A1,A2,...), MOD(A,P), SIN(X), COS(X), TAN(X), EXP(X), LOG(X), SQRT(X), ... . Some examples are:
    c --------------------
         real, array(256,512) :: a,b  ! real declaration with array attribute;
                                      ! assume that a and b are initialized
         b = sin(2.*a) + 4.5*exp(3*b) ! b(i,j)=sin(2.*a(i,j))+4.5*exp(3*b(i,j))
                                      ! for all i,j.
         b = sqrt(a) ! b(i,j)=sqrt(a(i,j)) for all i,j.
    c --------------------
    
    Note that expressions and their left-hand-sides must be conformable.

    CMF Array Reduction Functions: Sum, Product, Maxval

    All these functions are applied to a whole array or part of the array and give a scalar result. Some of them are:
         [Ans]=ALL([MASK],[DIM]) ! Determine if all values are .true. in
                                 ! [MASK] along dimension [DIM].
         [Ans]=ANY([MASK],[DIM]) ! Determine if any value is .true. in
                                 ! [MASK] along dimension [DIM].
         [Ans]=DOTPRODUCT([VECTOR_1],[VECTOR_2]) ! Dotproduct of two vectors.
         [Ans]=MAXVAL([ARRAY],[DIM],[MASK]) ! Computes the maximum value of the
                                            ! elements of [ARRAY] along dimension
                                            ! [DIM] corresponding to the true
                                            ! elements of the [MASK].
         [Ans]=MINVAL([ARRAY],[DIM],[MASK]) ! Computes the minimum value of the
                                            ! elements of [ARRAY] along dimension
                                            ! [DIM] corresponding to the true of
                                            ! elements the [MASK.]
         [Ans]=PRODUCT([ARRAY],[DIM],[MASK]) ! Product of all the elements of
                                             ! [ARRAY] along dimension [DIM]
                                             ! corresponding to the true elements
                                             ! of [MASK].
         [Ans]=SUM([ARRAY],[DIM],[MASK]) ! Sum of all the elements of [ARRAY] along
                                         ! dimension [DIM] corresponding to the
                                         ! true elements of [MASK].
    
    In the above, the answer `[Ans]' must be declared as the same shape and type as the expected output of the CM function. For 2D arrays or array sections, `DIM=1' is the vertical dimension (i.e., variation of the first array subscript) and `DIM=2' is the horizontal dimension (i.e., variation of the second array subscript). The `MASK=[MASK]' is an array conditional that must be compatible with the shape of array `[ARRAY]'. In these array reduction functions, the dimension and mask arguments are optional. CAUTIONS: keywords `DIM=', `MASK=', etc., must be used for all keyword arguments or for none; keyword and non-keyword arguments can not be mixed in any function; if no keywords are used then the arguments should follow the default order; Cray CF77v6.0 array intrinsic functions do not take keywords. The type of communication used in functions like SUM is yet another type of communication on the CM, called Scan Communication. Here are some examples (note: these examples are much too small for the CM and are just for illustration):
    c --------------------
          integer b(2,3),s2(2),s3(3)
          b(1,1:3) = [1, 3, 5]  ! initialize first row, along dimension 2.
          b(2,1:3) = [2, 4, 6]  ! initialize second row, along dimension 2.
    c --------------------
          isum = sum(b) ! => isum = 21; i.e., Front-End scalar.
          isum = sum(b(:,1:3:2)) ! => isum = 14; sole `:' means all values `1:2'.
          s2 = sum(b,dim=2) ! => s2 = [9,12]; row sums; note result must be
                            ! declared with the correct array section shape.
          s3 = sum(b,dim=1) ! => s3 = [3,7,11]; column sums.
          isum = sum(b,mask=b.gt.3) ! =>isum = 18; i.e., add only elements
                                    ! that are greater than three.
          s3 = sum(b,dim=1,mask=b.gt.3) ! => s3 = [0,4,11]; conditional col. sum.
    c --------------------
          imax = maxval(b) ! => imax = 6; array maximum value.
          s3 = maxval(b,dim=1) ! => s3 = [2,4,6]; column maximums.
          s2 = maxval(b,dim=2) ! => s2 = [5,6]; row maximums.
    c --------------------
          imin = minval(b) ! => imin = 1; array minimum value.
    c --------------------
          s2 = product(b,dim=2) ! => s2 = [15,48]; products of column elements.
    c --------------------
          idot = dotproduct(b(1,:),b(2,:)) ! => idot = 44; dot product of row
                                           ! vectors of b.
    c --------------------
    

    CMF Array Functions Only: MatMul and Transpose

    There are also some CMF functions whose input and output are just arrays, and `matmul' and `transpose' are defined and illustrated below:
    c --------------------
          integer c(2,2),ct(3,2)
          ! assuming array b of the previous section.
          ![Ans] = matmul([Array_1],[Array_2]) ! computes matrix multiplication
                                               ! of two rank two matrices.
          c = matmul(b(:,1:2),b(:,2:3)) ! => c(1,:)=[15,23];c(2,:)=[22,34].
          ![Ans] = transpose([Array]) ! transforms an array to its transpose.
          ct = transpose(b) ! => ct(1,:)=[1,2];ct(2,:)=[3,4];ct(3,:)=[5,6].
             ! a useful application of transpose is for printing arrays properly:
          print66,c   ! prints out the transpose of c since Fortran is column-wise.
          print66,transpose(c)  ! prints out matmul output c properly, row by row:
    66    format(1x,2i6)    ! format repeats last top level group for each row.
    c --------------------
    

    CMF Array Shift Functions: Cshift and EOshift

    There are two kinds of communications in CM Fortran, one is called Grid-Based or NEWS communications, and another is called General Communications. Let us assume a, b and c be defined of size mXn. Thus a(1:m-1,1)=b(2:m,1) is to shift last (m-1) elements on first column of b to first (m-1) elements on first column of a. This is an example of Grid-Based communication. Similarly, a(1:m,1:4)=b(2:m,2:5) and a(1:3,3:6)=a(2:4,1:4) are Grid-Based communications. CM Fortran also defines special intrinsic functions to perform Grid-Based data motion, called CSHIFT and EOSHIFT, with format: performs an end-off shift along certain dimension.
    • [Ans] = CSHIFT([Array],[DIM],[SHIFT]) : The function `CSHIFT' performs a circular shift of array elements along dimension `[DIM]' and with shift `[SHIFT]', which can be an array.
    • [Ans] = EOSHIFT([Array],[DIM],[SHIFT],[BOUNDARY-VALUES]) : The function `EOSHIFT' performs an end-off shift along dimension `[DIM]' and with shift `[SHIFT]', which can be an array. Differently from `CSHIFT', `EOSHIFT' fills vacated values with zeros, unless alternate values are specified with the argument `boundary=[BOUNDARY-VALUES]'.
    In both cases, only the `[Array]' argument is essential, while `[DIM]' and `[SHIFT]' should be consistent with the shape of the array. CAUTION: the argument order in CMF shift functions is different from those of Cray CF77v.6.0 shift functions. For instance:
    c --------------------
          integer, array(2,3) :: a,b,c
            ! assume b is again initialized as
            !        b =  1 3 5
            !             2 4 6
          a = cshift(a,dim=2,shift=1)  ! => a = 3 5 1
                                       !        4 6 2
            ! i.e., b(i,j+shift) -> a(i,j) for j=1:2, etc.;
            ! i.e., the result is computed from shifting subscript in specified
            ! dimension of the source array by the specified shift.
          a = cshift(b,dim=2,shift=-1)  ! => a = 5 1 3
                                        !        6 2 4
            ! i.e., b(i,j+shift) -> a(i,j) for j=2:3, etc.
          a = cshift(b,2,[1,2])  ! a = 3 5 1
                                 !     6 2 4
            ! i.e., an array-valued shift, or shift per row.
    c --------------------
          logical inmask(64,64)
          real u(64,64),du(64,64),us(8,8),diffav
           ! Jacobi Iteration for a 5-star discretization of
            !        2D Laplace's equation:
          u = 0
          u(1,:)=2
          u(64,:)=2
          u(:,1)=2
          u(:,64)=1
          inmask = .FALSE.
          inmask(2:63,2:63) = .TRUE.
          diffav = 1
          iter=0
          do while (diffav.gt.5.e-3.and.iter.lt.100)
             iter=iter+1
             du = 0
             where(inmask)
                du = 0.25*(cshift(u,1,1)+cshift(u,1,-1)+cshift(u,2,1)
         &          +cshift(u,2,-1)) - u
                u = u + du
             end where
             du = du*du
             diffav = sqrt(sum(du)/(62*62))
          end do
            ! which is the main program fragment of laplace.fcm.
          us = u(1:64:9,1:64:9)
          us=transpose(us)
          print66,'u = laplace-shift(u)= ; iter=',iter,'; av-diff ='
         &       ,diffav,us
    66    format(1x,a36,i3,a7,e10.3/(8f7.3))
    c --------------------
          a = eoshift(b,1,-1) ! a = 0 0 0  ! note default boundary value is 0.
                              !     1 3 5
          a = eoshift(b,dim=2,shift=[-1,0],boundary=[7,8]) ! => a = 7 1 3
                                                           !        2 4 6
          a = eoshift(b,2,2) ! => a = 5 0 0
                             ! =>     6 0 0
    c --------------------
    
    respectively. In contrast, General communications are either performed by FORALL statement, mentioned previously, such as
    c --------------------
          integer, parameter :: m=128,n=256
          integer array(m,n) :: b,c
          integer a(7),v(7),x(m),y(n)
          a=[1,2,3,4,5,6,7] ! initialize vector a by a constructor.
          v=[2,3,4,4,1,4,5] ! initialize vector v by a constructor.
          a=a(v) ! new a=[a(2),a(3),a(4),a(4),a(1),a(4),a(5)]=[2,3,4,4,1,4,5]
             ! note the vector subscript duplications above.
             ! assume appropriate array initializations for b,c,x,y:
          forall(i=1:m,j=1:n) c(i,j) = b(x(i,j),y(i,j)) ! vector-valued subscripts.
    c --------------------
    
    See the sample program `laplace.fcm' on the CM Suns for an illustration of using the `cshift' Circular Shift for solving Laplace's equation. Similarly, the CM code `FE-util.fcm' gives an application of the `eoshift' End-Off shift.

    CMF Array Replication Functions: Spread and Replicate

    These functions construct new arrays from the elements of existing arrays. They are:
         [Ans]=SPREAD([ARRAY],[DIM],[NCOPIES]) ! Replicate an array by adding a
                                      ! dimension before [DIM].
         [Ans]=REPLICATE([ARRAY],[DIM],[NCOPIES]) ! Replicate an array by
                                      ! increasing the size of a dimension [DIM].
         [Ans]=MERGE([T-Array],[F-Array],[MASK]) ! Merges arrays two arrays
                    ! using an element of `[T-Array]' if that element of `[MASK]'
                    ! is `.true.' and that of `[F-Array]' if it is `.false.'.
                    ! All three arrays must have the same shape, `[T-Array]' and
                    ! must have the same type, while `[MASK]' must be logical.
    
    The arguments `[ARRAY]', `[DIM]' and `[MASK]' have the same meaning as before, but `[NCOPIES]' is the number of copies to be replicated. Suppose that array a=[2,3,4], then the following example CM Fortran statements give the following array shapes:
    c --------------------                  |c --------------------
          integer b(2,3),cst(3,4)           |      integer b(2,3),d(2,9)
          b(1,:) = [1,3,5]                  |      b(1,:) = [1,3,5]
          b(2,:) = [2,4,6]                  |      b(2,:) = [2,4,6]
          cst=replicate(b,dim=1,ncopies=2)  |      d=replicate(b,DIM=2,NCOPIES=3)
            ! contents of cst:              |        ! contents of d:
            !        1 3 5                  |        !     1 3 5 1 3 5 1 3 5
            !        2 4 6                  |        !     2 4 6 2 4 6 2 4 6
            !        1 3 5                  |      d(:,2:4) = replicate(b,2,1)
            !        2 4 6                  |        ! contents of d(:,2:4) is b
    c ---------------------------------------------------------------------------
    ! i.e., b=replicate(a,d,c)  =>
    ! a(n_1,n_2,...,n_(d-1),n_d,...,n_r) -> b(n_1,n_2,...,n_(d-1),c*n_d,...,n_r)
    ! where r is the rank of source array a and n_i is the size of dimension i;
    ! noting that only the size of dimension d changes:  n_d -> c*n_d.
    c --------------------                  |c --------------------
          integer as(4),cs(4,4)             |      integer at(3),cs(4,4)
          as=[2,3,4,5]                      |      at=[2,3,4]
          cs=spread(as,DIM=1,ncopies=3)     |      cs=spread(at,DIM=2,NCOPIES=4)
            ! contents of cs:               |        ! contents of cs:
            !        2 3 4 5                |        !        2 2 2 2
            !        2 3 4 5                |        !        3 3 3 3
            !        2 3 4 5                |        !        4 4 4 4
    c ---------------------------------------------------------------------------
    ! i.e., b=spread(a,d,c)  =>
    ! a(n_1,n_2,...,n_(d-1),n_d,...,n_r) -> b(n_1,n_2,...,n_(d-1),c,n_d,...,n_r)
    ! where r is the rank of source array a and n_i is the size of dimension i;
    ! noting that a new dimension of size c is added before dimension d.
    c ---------------------------------------------------------------------------
    See also the application of the Spread function to the elemental matrix
    multiplication for Forward Gaussian Elimination
    in the Getting Started in CM Fortran document.
    

    CMF Parallel Statements: Forall and Where

    In addition, there are two basic CM Fortran statements, FORALL and WHERE, support the array computations.
    • forall([subscript-triplets],[scalar-mask]) [array-element-statement] : The `forall' is a CM parallel statement and must be a single statement rather that a block. The list `[subscript-triplets]' is a set of triplets of the form `[i1]:[i2][:[i3]]', which optional stride if the unit default. The conditional mask `[scalar-mask]' is optional, but must be scalar if present and with enough conditions to match the triplet list range. The single target `[array-element-statement]' must also conform to the triplet range and mask, but also can not have any data dependencies, i.e., no element over-writes, because they would violate the parallel execution. The `forall' statement is an exception to the rule that Fortran references to array elements are always computed on the Front-End.
    • where([MASK]) [assignment-else-list] : The conditional array construct `where' generalizes the scalar construct `IF' statement to arrays. The `where' statement has two principal forms, the single statement:
             where ([MASK]) [Array] = [Array-Expression]
      
      and the `where-elsewhere' block:
             where ([MASK])
                   [Array-1] = [Array-Expression-1] ! compute if [MASK]_i=.true.
             elsewhere
                   [Array-2] = [Array-Expression-2] ! compute if .not.[MASK]_i=.true.
             end where
      
      The `[MASK]', arrays and array-expressions must have the same shape, but the computation is done element by element according to the mask or inverse mask. The `[MASK]_i' is meant to denote an element of the mask. The `where-elsewhere' block constructs can be nested.
    They are illustrated in the following example.
    c --------------------
             integer, parameter :: m=256,n=512
             real, array (m,n) :: a, b, c
             real d(m,m)
                  :
       comment:  assume that a, b and c are initialized.
                  :
             FORALL (i=1:m,j=1:m,i.gt.j) d(i,j) = 0.0 ! Clear lower triangular part
                                                      ! of array d in parallel.
             FORALL (i=1:m) a(i,:)=i   ! Elements on ith column get value i.
    c --------------------
             WHERE (a.ne.0.0) c = b/a  ! c(i,j)=b(i,j)/a(i,j), if a(i,j).ne.0.
                                       ! for each i,j; caution: a.ne.0. is not
                                       ! wise for reals; see next example.
                 ! You can also use a logical array mask,
                 ! i.e., with statement `where ([mask])', where [mask]=a.ne.0.0
             WHERE (abs(b).gt.0.5e-5) ! block where-elsewhere construct.
                 c = a/b         ! c(i,j)=a(i,j)/b(i,j), if abs(b(i,j)).gt..5e-5
             ELSEWHERE
                 c = 1.0e30      ! c(i,j)=1.0e30 if .not.(abs(b(i,j)).gt..5e-5)
             END WHERE
    c --------------------
    
    Remember that the IF statement only allows scalar logical expressions.

    CMF Random Number Functions

    Good random number generators are essential for running numerical simulation of problems and for constructing general sample arrays to test out code under development. Several essential CMF random subroutines are given below. See also the matrix multiplications testing program `mm.fcm' illustrating the random number subroutines listed below in
      /cm/EXAMPLES/CMF/doc-examples
    {In addition, the sample random value filling subroutine `paris/random.fcm' in the same directory, uses other non-standard random number generators.} Use the `man cmf_random' command for further documentation. The following CMF utility random subroutine requires the included header file:
      include '/usr/include/cm/CMF_defs.h'
    in every program unit that it is used, as do any other CMF utilities.
    • call cmf_random([CM-Array],[integer-limit]) : This subroutine call initialize the array `[CM-Array]' with pseudo-random values from 0 to `[integer-limit]' for integer arrays and with pseudo-random values uniformly distributed on [0.0,1.0) for real or double precision arrays, ignoring the integer upper limit. For complex arrays, the subroutine does a similar initialization. Wolfram's Rule 30 Cellular Automaton is used as the random number generator algorithm.
    • call cmf_randomize([Seed]) : This subroutine call changes the integer value `[Seed]' that initializes the random number generator `cmf_random'. The same seed will repeat the same set of pseudo-random numbers.

    CM C* Extensions to C

    The CM extended C language is called C* (CSTAR). C* contains standard C, but adds extensions for parallel variable operations, array `shape' declarations, `with' shape selections, and `where' conditional constructs. See Getting Started with C* and the C* Programming Guide for more information. The compile and link command for C* source files of the form `[file-name].cs' is
    • cs -O -[other options] [name].cs [other files] -o [exec-name] (CR) : Compiles and links optimizable CM C* source files `[name].cs' and `[other files]', producing an object file `[name].o' (use option `-c') and executable file `[exec-name]'. On the CM-5, the option `-vu' selects for VU computational acceleration.
      CSTAR (cs) Options for the CM-5 Data Parallel Extension of C
      
      Option      Function
      
      -cm5        Execute on CM-5 hardware.
      
      -cmdebug    Compile for debugging; faster then -g option, but less precise.
      
      -cmprofile  Produce peformance analysis, viewable using Prism.
      
      -dirs       Form "cs -cm5 -dirs" produces a list of directories where the 
                  compiler searches for binary, include and temporary files. 
      
      -force      Force "cc" *.c files to be compiled with C* compiler.
      
      -h          Print summary of available command line switches without compiling,
      	    i.e., "cs -h"; synonym for -help.
      
      -keep       Form "cs -cm5 -keep [tempfile] [file].cs", for instance causes
                  assembly ([file].s), object ([file].o) and DPEAC ([file].pe.dp) 
                  files when "[tempfile]" = "s", "o" and "dp", repectively.
      
      -node       Copies of code are executed on each node; serial instructions on 
                  node; parallel instructions on vector units of node; necessary
                  when using the CMMD message passing mode; only supported when 
                  options -cm5 -vu are also used.
      
      -O          Enable code optimizations in all compilers.
      
      -sparc      Compile to run on sparc nodes, and without vector units; same as
      	    -cm5 -sparc option.
      
      -veccode    Produce DPEAC assembly code with extension *.pe.dp for 
      	    execution on vector units.
      
      -version    Print C* compiler version number.
      
      -vu         Compile to run on vector units; synonym for -vecunit; same as -cm5
      	    -vu option; typical default for -cm5 option without -sparc.
      
      Options in common with standard cc compiler.
      
      -c          Compile only; produce object file; suppress linking phase.
      
      -g          Produce symbol table for debugging, for Prism on CM-5.
      
      -I[dir]     Seek #include file in this directory.
      
      -l[X]       Look for library lib[X].a.
      
      -o[exec]    Name excutable file [exec].
      
      -pg         Produce gprof profile code.
      
      -S          Produce rough assembly code [file].s for partition manager code
                  and [file].pe.s for node code; can not be used with -c or -o 
                  options.
      
      For more information on compiling C* code, see the CM-5 C* User's Guide, Chapter 3 Compiling a C* Program. The chapter also explains how to combine CMF and C* programs.
    Some language extensions in C* are as follows:
    • shape [[shape-dimensions]][shape-name]; : Declares the shape with shape name `[shape-name]' with dimensions `[shape-dimensions]' in square brackets for parallel data. Shapes can also be used in `struct' structure declarations and shape pointers can be declared. For example, `shape [65536]ShapeA;' declares a 65K element vector with locations `0' to `64K-1', while `shape [4][32768]ShapeB;' declared a two dimensional shape `ShapeB' with 256K positions `0' to `3' by `0' to `32K-1'.
    • [type]:[shape-name] [parallel-variable-list]; : Declares parallel variables `[parallel-variable-list]' with shape `[shape-name]' of type `[type]'. Parallel variables can also have pointers. For example,
            shape [16384]ShapeB;
            int:ShapeB p1,p2,p3,p4,p5,p6;
            int sum_p = 0;
            main()
                {
                 /* Some Initialization Code */
                 p1 = 1;  /* assigns all elements of p1 to 1 */
                 p2 = 3;  /* assigns all elements of p2 to 3 */
                 p3 = p2;  /* assigns each element of p2 to element of p3 */
                 p4 = p1 + p2; /* adds elements of p1 and p2 to p3 */
                 sum_p += p3;  /* sums all elements of p3 into scalar sum_p */
                 p5 += p2; /* adds element of p2 to corresponding element of p5 */
                 p6 = (p3 >= p1);  /* assigns an element of p3 to p4 only
                                   if it is bigger than that of p1; else 0 */
                 p5 = (p4 < 3) ? p2 : p1; /* element of p2 is assigned to p5
                              if corresponding element of p4 is less than 3,
                                   else element of p1 is assigned to p5  */
             }
      
    • with ([shape-name]) [parallel-code] : Indicates the current shape `[shape-name]' for the C* code `[parallel-code]' that follows. For example, `with (ShapeB)'.
    • where ([array-condition]) [parallel-code] : Restrictions the context for the following `[parallel-code]' according to the `[array-condition]'. The `where' statement is the are array generalization of the scalar `if' statement. It also can take an `else' clause and can be nested. There is also a `everywhere' statement that makes all positions of the current shape active. For example,
            shape [16384]ShapeW;
            int:ShapeW worker wage;
            main()
            {with(ShapeW)
                 where(wage > 999) {
                       /* Some Parallel Code if condition true */
                 }
                 else {
                       /* Some other Parallel Code if condition false */
                 }
             }
      
    • allocate_shape(&[shape-name],[shape-dim],[dimensions]); : Dynamically allocates the shape `[shape-name]' the `[shape-dim]' dimension with dimensions that follow. See also `palloc' and `pfree' for allocating storage and freeing storage, respectively. For example, `allocate_shape(&All_Shape,2,3,4096);' allocates a `3' by `4K' two dimensional shape.
    • deallocate_shape(&[shape-name]); : Deallocates the shape `[shape-name]'.
    • spread([arguments]); : Spreads parallel operation results to a parallel variable. See the C* Parallel Programming Guide for more information on CM communication functions like `scan', `rank', `pcoord' and `dimof'.

    CMF and C* Timer Functions

    The timer records program execution time, both the total elapsed time and the the total CM time when CM processors are active. The cm_timer facility counts idle cycles in microseconds, but elapsed time (i.e., wall clock time) is measured on the Front-End in milliseconds, with
      CM_active_time = FE_RT --- CM_idle_cycles * time_per_cycle
    so that the result should not be used for times less than 1 second because the accuracy is polluted by the coarse Front-End clock and corresponding interference my UNIX multiprocessing. For a similar reason, any timing should be the average of 3 to 5 samples. The CMF timer facility is accessed by CM Fortran programs through calls to the four library subroutines CM_TIMER_CLEAR, CM_TIMER_START, CM_TIMER_STOP, CM_TIMER_PRINT. Timing information is maintained in two double-precision real variables CM_TV_CM and CM_TV_REAL in the common block CMVAL. To use CM timing subroutines, you must include the following `include' statement in any CM Fortran program unit using the timer:
           include '/usr/include/cm/timer-fort.h'
    
    If CMF utilities will also be used, then the user must also
           include '/usr/include/cm/CMF_defs.h'
    
    In particular, the latter `include' statement is needed for special CM utilities, so it is essential to have both near the beginning of each program unit that references both the CM-Timers and CMF-Utilities. In fact, it is good practice to put them in all or most program unit, just in case.

    For C* programs, the statement `#include <cm/timers.h>' is needed `cm_timer' needs to be replaced by the more case specific `CM_timer'. For more accurate wall clock times, the CM-5 C* Performance Guide suggests using the UNIX microsecond wall timer gettimeofday() (see the class example for usage: primes.cs).
    • subroutine CM_TIMER_CLEAR([n]) : Clears the real-time clock and the accumulated timing information, but does not restart the clock. Both CM_TV_CM and CM_TV_REAL are reset to 0.0. It is not necessary to call this subroutine before the first call to CM_TIMER_START.
    • subroutine CM_TIMER_START([n]) : Starts the independent timer `[n]' and begins (or resumes) accumulating timing information, with microsecond precision. The timer number argument [n] can be an integer between 0 and 64. This timer subroutine is used in pairs with `cm_timer_stop([n])', and the pairs can be nested.
    • subroutine CM_TIMER_STOP([n]) : Stops the independent timer `[n]' and updates the values of the real variables in the common block CMVAL with the accumulated timing information. The timer number argument [n] can be an integer between 0 and 64. This timer subroutine is used in pairs with `cm_timer_start([n])', and the pairs can be nested. It is also must be called to stop the clock before `cm_timer_print([n])' is called to print out timing information.
    • subroutine CM_TIMER_PRINT([n]) : Prints out timing information for time `[n]', including ``Elapsed time'' on the Front-End CM Suns and ``CM busy time'' that the CM is active, in seconds. The following is an example of two nested timers for the CM-5:
               program timing       ! sample timing template
                 ! `!' can be used for inline comments, except in column 6.
               include '/usr/include/cm/timer-fort.h'
                    :
               call cm_timer_clear(0)      ! clear outer timer 0 (optional)
               call cm_timer_start(0)      ! start outer timer 0
                    :                        ! do some computations
               call cm_timer_start(1)      ! start inner timer 1
                    :                        ! do some more computations
               call cm_timer_stop(1)       ! stop inner timer 1
               print*, 'first inner time:'
               call cm_timer_print(1)      ! print inner timer 1 results
                    :                        ! do some more computations
               call cm_timer_clear(1)      ! clear inner timer 1
               call cm_timer_start(1)      ! restart inner timer 1
                    :                        ! do some more computations
               call cm_timer_stop(1)       ! re-stop inner timer 1
               print*, 'second inner time:'
               call cm_timer_print(1)      ! print inner timer 1 results
                    :                        ! do some more computations
               call cm_timer_stop(0)       ! stop outer timer 0
               print*, 'total outer time:'
               call cm_timer_print(0)      ! print outer timer 0 results
                    :                        ! do some more computations
               stop
               end
      

    More CM-5 timing Information:


    The best way to learn these commands is to use them in an actual computer session. Please report to Professor Hanson (e-address: u12688 at uicvm.cc.uic.edu or Hanson@uic.edu or hanson@math.uic.edu) any problems or inaccuracies. Good luck.

    Return to TABLE OF CONTENTS?