//******************************************************************************
//
// File: CCASmp.java
// Package: edu.rit.smp.ca
// Unit: Class edu.rit.smp.ca.CCASmp
//
// This Java source file is copyright (C) 2009 by Alan Kaminsky. All rights
// reserved. For further information, contact the author, Alan Kaminsky, at
// ark@cs.rit.edu.
//
// This Java source file is part of the Parallel Java Library ("PJ"). PJ is free
// software; you can redistribute it and/or modify it under the terms of the GNU
// General Public License as published by the Free Software Foundation; either
// version 3 of the License, or (at your option) any later version.
//
// PJ is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
// A PARTICULAR PURPOSE. See the GNU General Public License for more details.
//
// A copy of the GNU General Public License is provided in the file gpl.txt. You
// may also obtain a copy of the GNU General Public License on the World Wide
// Web at http://www.gnu.org/licenses/gpl.html.
//
//******************************************************************************
package edu.rit.smp.ca;
import edu.rit.image.GrayImageRow;
import edu.rit.image.PJGGrayImage;
import edu.rit.image.PJGImage;
import edu.rit.numeric.BigRational;
import edu.rit.pj.BarrierAction;
import edu.rit.pj.IntegerForLoop;
import edu.rit.pj.IntegerSchedule;
import edu.rit.pj.ParallelRegion;
import edu.rit.pj.ParallelTeam;
import edu.rit.util.Range;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
/**
* Class CCASmp is an SMP parallel program that calculates the evolution of a
* continuous cellular automaton and stores the result in a grayscale PJG image
* file. Within each time step, the cells' next states are calculated in
* parallel by K threads, then the cell's current states are written as
* one row of the image file by a single thread.
*
* Usage: java [ -Dpj.nt=K ] edu.rit.smp.ca.CCASmp C S
* A B imagefile
*
K = Number of parallel threads
*
C = Number of cells (>= 1)
*
S = Number of time steps (>= 1)
*
A = Multiplicand in update formula (rational number)
*
B = Addend in update formula (rational number)
*
imagefile = Output PJG image file name
*
* The cellular automaton (CA) consists of an array of C cells. Each
* cell's value is a rational number in the range 0 to 1. A cell's next value is
* computed as follows: Compute the average of the cell itself, the cell's left
* neighbor, and the cell's right neighbor (wraparound boundary conditions);
* multiply by A; add B; and take the fractional part, yielding a
* result in the range 0 to 1. The CA's initial state is all cells 0, except the
* middle cell is 1. The program evolves the CA's initial state for S
* time steps and generates a grayscale image with S+1 rows and C
* columns. The first row of the image corresponds to the CA's initial state,
* and each subsequent row corresponds to the CA's state after the next time
* step. In the image, each pixel's gray value is proportional to the
* corresponding cell's value, with 0 being white and 1 being black. The image
* is stored in a Parallel Java Graphics (PJG) file. For further information
* about the PJG format, see class {@linkplain edu.rit.image.PJGImage}.
*
* @author Alan Kaminsky
* @version 06-Jul-2009
*/
public class CCASmp
{
// Prevent construction.
private CCASmp()
{
}
// Shared variables.
// Constants.
static final BigRational ZERO = new BigRational ("0");
static final BigRational ONE = new BigRational ("1");
static final BigRational ONE_THIRD = new BigRational ("1/3");
// Command line arguments.
static int C;
static int S;
static BigRational A;
static BigRational B;
static File imagefile;
// Old and new cell arrays.
static BigRational[] currentCell;
static BigRational[] nextCell;
// Grayscale image matrix.
static byte[][] pixelmatrix;
static PJGGrayImage image;
static PJGImage.Writer writer;
// One row of the grayscale image matrix.
static byte[] pixelrow;
static GrayImageRow imagerow;
// Main program.
/**
* Main program.
*/
public static void main
(String[] args)
throws Exception
{
// Start timing.
long t1 = System.currentTimeMillis();
// Parse command line arguments.
if (args.length != 5) usage();
int argi = 0;
C = Integer.parseInt (args[0]);
S = Integer.parseInt (args[1]);
A = new BigRational (args[2]) .mul (ONE_THIRD);
B = new BigRational (args[3]);
imagefile = new File (args[4]);
// Allocate storage for old and new cell arrays. Initialize all cells to
// 0, except center cell to 1.
currentCell = new BigRational [C];
nextCell = new BigRational [C];
for (int i = 0; i < C; ++ i)
{
currentCell[i] = new BigRational();
nextCell[i] = new BigRational();
}
currentCell[C/2].assign (ONE);
// Set up pixel matrix, image, and image writer.
pixelmatrix = new byte [S+1] [];
image = new PJGGrayImage (S+1, C, pixelmatrix);
writer =
image.prepareToWrite
(new BufferedOutputStream
(new FileOutputStream (imagefile)));
// Allocate storage for one pixel matrix row.
pixelrow = new byte [C];
imagerow = new GrayImageRow (pixelrow);
imagerow.setInterpretation (PJGGrayImage.ZERO_IS_WHITE);
// Parallel calculation section.
new ParallelTeam().execute (new ParallelRegion()
{
public void run() throws Exception
{
// Do S time steps. Sequential outer loop.
for (int s = 0; s < S; ++ s)
{
final int step = s;
// Calculate next state of each cell. Parallel inner loop.
execute (0, C-1, new IntegerForLoop()
{
public IntegerSchedule schedule()
{
return IntegerSchedule.guided();
}
public void run (int first, int last)
{
for (int i = first; i <= last; ++ i)
{
nextCell[i]
.assign (currentCell[i])
.add (currentCell[(i-1+C)%C])
.add (currentCell[(i+1)%C])
.mul (A)
.add (B)
.normalize()
.fracPart();
}
}
},
// Synchronize threads before next outer loop iteration.
new BarrierAction()
{
public void run() throws Exception
{
// Write current CA state to image file.
writeCurrentCell (step);
// Advance one time step -- swap old and new cell
// arrays.
BigRational[] tmp = currentCell;
currentCell = nextCell;
nextCell = tmp;
}
});
}
}
});
// Write final CA state to image file.
writeCurrentCell (S);
writer.close();
// Stop timing.
long t2 = System.currentTimeMillis();
System.out.println ((t2-t1) + " msec total");
}
// Hidden operations.
/**
* Write the current cell array to the given row of the image file.
*
* @param r Row index.
*/
private static void writeCurrentCell
(int r)
throws IOException
{
// Set image row's gray values based on current cell states.
for (int i = 0; i < C; ++ i)
{
imagerow.setPixel (i, currentCell[i].floatValue());
}
// Set row r of the pixel matrix.
pixelmatrix[r] = pixelrow;
// Write row-r slice of the image to the image file.
writer.writeRowSlice (new Range (r, r));
}
/**
* Print a usage message and exit.
*/
private static void usage()
{
System.err.println ("Usage: java [-Dpj.nt=] edu.rit.smp.ca.CCASmp ");
System.err.println (" = Number of parallel threads");
System.err.println (" = Number of cells (>= 1)");
System.err.println (" = Number of time steps (>= 1)");
System.err.println (" = Multiplicand in update formula (rational number)");
System.err.println (" = Addend in update formula (rational number)");
System.err.println (" = Output PJG image file name");
System.exit (1);
}
}
Ads help maintain this website.