fix npe on boolean operators

fix npe on boolean operators

use Logging, Memory, LibEv, IO, Indexer, Search, Partitions;

// TODO: port to pure chapel
extern proc initialize_socket(port: c_int): c_int;

// trampolines
extern var c_accept_cb: opaque;

extern proc send(sockfd:c_int, buffer: c_string, len: size_t, flags: c_int);

config var port: c_int = 3033;

// TODO: we need to know which client context this is so that we can maintain parsing context
//       is the fd enough?
export proc handle_received_data(fd: c_int, buffer: c_string, read: size_t, buffer_size: size_t) {
  // writeln("from chpl: " + buffer);
  // accumulate string buffer
  var word = buffer;
  var trimmedWord: string = "";
  writeln("word: ", word);
  for i in 1..word.length {
  	var ch = word.substring(i);
  	if (ch != "\r" && ch != "\n") {
	  	writeln("ch: ", word.substring(i));
	  	trimmedWord += word.substring(i);
  	}
  }
//  writeln("trimmedWord: ", trimmedWord);
	if (trimmedWord == "dump") {
		dumpPartition(partitionForWord("dog"));
	} else {
		writeln("<adding>");
	  indexWord(trimmedWord, 1);
		dumpPostingTableForWord(trimmedWord);
		writeln("</adding>");
	}
  send(fd, buffer, read, 0);
}

proc initIndex() {
	writeln("This program is running on ", numLocales, " locales");
	writeln("It began running on locale #", here.id);
	writeln();

  initPartitions();
  initIndices();

  initIndexer();

 //  writeln("adding 3 entries");
	// indexWord("dog", 1);
	// indexWord("cat", 2);
	// indexWord("cat", 3);

 //  writeln("dumping partition holding word: dog");
	// dumpPartition(partitionForWord("dog"));

 //  writeln("dumping posting table for word: cat");
	// dumpPostingTableForWord("cat");

  var infile = open("words.txt", iomode.r);
  var reader = infile.reader();
  var word: string;
  var docId: DocId = 1;
  while (reader.readln(word)) {
    enqueueIndexRequest(word, docId);
    docId = (docId + 1) % 1000 + 1; // fake different docs
  }

  waitForIndexer();

  dumpPostingTableForWord("the");

  // TODO: build execution Tree w/ conj / disj. (operator) nodes
  // test basic boolean operators
  writeln("conjunction");
  var conj = conjunction(["the", "dog"]);
  writeln(conj);

  writeln("disjunction");
  var disj = disjunction(["the", "dog"]);
  writeln(disj);
}

proc conjunction(words: [] string): domain(DocId) {
  writeln("finding conjunction of: ", words);
  var doms: [1..words.size] domain(DocId);

  for j in 1..words.size {
    var word = words[j];
    var entry = entryForWord(word);
    if (entry != nil) {
      on entry {
        for docId in documentIdsForEntry(entry) {
          doms[j] += docId;
        }
      }
    }
  }

  writeln("applying intersection");

  for j in 2..words.size {
    doms[1] = doms[1] & doms[j];
  }

  return doms[1];
}

proc disjunction(words: [] string): domain(DocId) {
  writeln("finding disjunction of: ", words);
  var doms: [1..words.size] domain(DocId);

  for j in 1..words.size {
    var word = words[j];
    var entry = entryForWord(word);
    if (entry != nil) {
      on entry {
        for docId in documentIdsForEntry(entry) {
          doms[j] += docId;
        }
      }
    }
  }

  writeln("applying disjunction");

  for j in 2..words.size {
    doms[1] = doms[1] | doms[j];
  }

  return doms[1];
}

proc writeLocInfo(loc: locale) {
  on loc {
    writeln("locale #", here.id, "...");
    writeln("  ...is named: ", here.name);
    writeln("  ...has ", here.numCores, " processor cores");
    writeln("  ...has ", here.physicalMemory(unit=MemUnits.GB, retType=real), " GB of memory");
    writeln("  ...has ", here.maxTaskPar, " maximum parallelism");
  }
}

proc main() {

	// writeln("creating socket...");
	// var sd: ev_fd = initialize_socket(port);
	// writeln("socket id = ", sd);
	// if (sd == -1) {
	// 	writeln("socket error");
	// 	return -1;
	// }

  writeln("initializing index");
  initIndex();

	// writeln("initializing event loop...");

 //  // port c_accept_cb, c_read_cb
	// var w_accept: ev_io = new ev_io();
	// ev_io_init(w_accept, c_accept_cb, sd, EV_READ);
	// ev_io_start(EV_DEFAULT, w_accept);

	// while (1) {
	// 	ev_loop_fn(EV_DEFAULT, 0);
	// }
}

use Logging, Memory, LibEv, IO, Indexer, Search, Partitions;

// TODO: port to pure chapel
extern proc initialize_socket(port: c_int): c_int;

// trampolines
extern var c_accept_cb: opaque;

extern proc send(sockfd:c_int, buffer: c_string, len: size_t, flags: c_int);

config var port: c_int = 3033;

// TODO: we need to know which client context this is so that we can maintain parsing context
//       is the fd enough?
export proc handle_received_data(fd: c_int, buffer: c_string, read: size_t, buffer_size: size_t) {
  // writeln("from chpl: " + buffer);
  // accumulate string buffer
  var word = buffer;
  var trimmedWord: string = "";
  writeln("word: ", word);
  for i in 1..word.length {
  	var ch = word.substring(i);
  	if (ch != "\r" && ch != "\n") {
	  	writeln("ch: ", word.substring(i));
	  	trimmedWord += word.substring(i);
  	}
  }
//  writeln("trimmedWord: ", trimmedWord);
	if (trimmedWord == "dump") {
		dumpPartition(partitionForWord("dog"));
	} else {
		writeln("<adding>");
	  indexWord(trimmedWord, 1);
		dumpPostingTableForWord(trimmedWord);
		writeln("</adding>");
	}
  send(fd, buffer, read, 0);
}

proc initIndex() {
	writeln("This program is running on ", numLocales, " locales");
	writeln("It began running on locale #", here.id);
	writeln();

  initPartitions();
  initIndices();

  initIndexer();

 //  writeln("adding 3 entries");
	// indexWord("dog", 1);
	// indexWord("cat", 2);
	// indexWord("cat", 3);

 //  writeln("dumping partition holding word: dog");
	// dumpPartition(partitionForWord("dog"));

 //  writeln("dumping posting table for word: cat");
	// dumpPostingTableForWord("cat");

  var infile = open("words.txt", iomode.r);
  var reader = infile.reader();
  var word: string;
  var docId: DocId = 1;
  while (reader.readln(word)) {
    enqueueIndexRequest(word, docId);
    docId = (docId + 1) % 1000 + 1; // fake different docs
  }

  waitForIndexer();

  dumpPostingTableForWord("the");

  // TODO: build execution Tree w/ conj / disj. (operator) nodes
  // test basic boolean operators
  writeln("conjunction");
  var conj = conjunction(["the", "dog"]);
  writeln(conj);

  writeln("disjunction");
  var disj = disjunction(["the", "dog"]);
  writeln(disj);
}

proc conjunction(words: [] string): domain(DocId) {
  writeln("finding conjunction of: ", words);
  var doms: [1..words.size] domain(DocId);

  for j in 1..words.size {
    var word = words[j];
    var entry = entryForWord(word);
    on entry {
      for docId in documentIdsForEntry(entry) {
        doms[j] += docId;
      }
    }
  }

  writeln("applying intersection");

  for j in 2..words.size {
    doms[1] = doms[1] & doms[j];
  }

  return doms[1];
}

proc disjunction(words: [] string): domain(DocId) {
  writeln("finding disjunction of: ", words);
  var doms: [1..words.size] domain(DocId);

  for j in 1..words.size {
    var word = words[j];
    var entry = entryForWord(word);
    on entry {
      for docId in documentIdsForEntry(entry) {
        doms[j] += docId;
      }
    }
  }

  writeln("applying disjunction");

  for j in 2..words.size {
    doms[1] = doms[1] | doms[j];
  }

  return doms[1];
}

proc writeLocInfo(loc: locale) {
  on loc {
    writeln("locale #", here.id, "...");
    writeln("  ...is named: ", here.name);
    writeln("  ...has ", here.numCores, " processor cores");
    writeln("  ...has ", here.physicalMemory(unit=MemUnits.GB, retType=real), " GB of memory");
    writeln("  ...has ", here.maxTaskPar, " maximum parallelism");
  }
}

proc main() {

	// writeln("creating socket...");
	// var sd: ev_fd = initialize_socket(port);
	// writeln("socket id = ", sd);
	// if (sd == -1) {
	// 	writeln("socket error");
	// 	return -1;
	// }

  writeln("initializing index");
  initIndex();

	// writeln("initializing event loop...");

 //  // port c_accept_cb, c_read_cb
	// var w_accept: ev_io = new ev_io();
	// ev_io_init(w_accept, c_accept_cb, sd, EV_READ);
	// ev_io_start(EV_DEFAULT, w_accept);

	// while (1) {
	// 	ev_loop_fn(EV_DEFAULT, 0);
	// }
}


Combined two "modified by" lines into one

git-svn-id: 88467cb1fb04b8a755be7e1ee1026be4190196ef@23052 3a8e244f-b0f2-452b-bcba-4c88e055c3ca

/* The Computer Language Benchmarks Game
   http://benchmarksgame.alioth.debian.org/

   contributed by Casey Battaglino
   modified by Ben Harshbarger and Brad Chamberlain
*/

//
// Use this helper module to get the dynamic iterator
//
use AdvancedIters;

//
// The problem size determines the maximum depth of the trees created
//
config const n = 10;

//
// A simple tree class
//
class Tree {
  const item: int;
  const left, right: Tree;
}

proc main() {
  const minDepth = 4,                      // the shallowest tree
        maxDepth = max(minDepth + 2, n),   // the deepest tree
        depths = minDepth..maxDepth by 2;  // the range of depths to create

  //
  // Create the "stretch" tree, checksum it, print its stats, and free it
  //
  const stretchDepth = maxDepth + 1;
  const stretchTree = buildTree(0, stretchDepth);
  writeln("stretch tree of depth ", stretchDepth, "\t check: ",
          checksum(stretchTree));
  free(stretchTree);

  //
  // Build our long-lived tree
  //
  const longLivedTree = buildTree(0, maxDepth);

  //
  // Declare an array for storing stats for the trees
  //
  var results: [depths] 2*int;

  //
  // Iterate over the depths we're exploring, dynamically mapping out a
  // single iteration per task at a time
  //
  forall depth in dynamic(depths, chunkSize=1) {
    const iterations = 1 << (maxDepth - depth + minDepth);
    var check = 0;

    for i in 1..iterations {
      const posT = buildTree( i, depth),
            negT = buildTree(-i, depth);
      check += checksum(posT) + checksum(negT);
      free(posT);
      free(negT);
    }
    results[depth] = (2*iterations, check);
  }

  //
  // Print out the results for the trees of varying depths
  //
  for depth in depths do
    writeln(results[depth](1), "\t trees of depth ", depth, "\t check: ",
            results[depth](2));

  //
  // Checksum the long-lived tree, print its results, and free it
  //
  writeln("long lived tree of depth ", maxDepth, "\t check: ",
          checksum(longLivedTree));
  free(longLivedTree);
}

//
// Build a tree
//
proc buildTree(item, depth): Tree {
  if depth <= 0 then
    return new Tree(item);
  else
    return new Tree(item, buildTree(2*item-1, depth-1),
                          buildTree(2*item  , depth-1));
}

//
// Compute a simple checksum on a tree
//
proc checksum(T): int {
  if (T.left == nil) then
    return T.item;
  else
    return (T.item + checksum(T.left) - checksum(T.right));
}

//
// Recursively free a tree
//
proc free(T) {
  if (T.left) {
    free(T.left);
    free(T.right);
  }
  delete T;
}

/* The Computer Language Benchmarks Game
   http://benchmarksgame.alioth.debian.org/

   contributed by Casey Battaglino
   modified by Ben Harshbarger
   modified by Brad Chamberlain
*/

//
// Use this helper module to get the dynamic iterator
//
use AdvancedIters;

//
// The problem size determines the maximum depth of the trees created
//
config const n = 10;

//
// A simple tree class
//
class Tree {
  const item: int;
  const left, right: Tree;
}

proc main() {
  const minDepth = 4,                      // the shallowest tree
        maxDepth = max(minDepth + 2, n),   // the deepest tree
        depths = minDepth..maxDepth by 2;  // the range of depths to create

  //
  // Create the "stretch" tree, checksum it, print its stats, and free it
  //
  const stretchDepth = maxDepth + 1;
  const stretchTree = buildTree(0, stretchDepth);
  writeln("stretch tree of depth ", stretchDepth, "\t check: ",
          checksum(stretchTree));
  free(stretchTree);

  //
  // Build our long-lived tree
  //
  const longLivedTree = buildTree(0, maxDepth);

  //
  // Declare an array for storing stats for the trees
  //
  var results: [depths] 2*int;

  //
  // Iterate over the depths we're exploring, dynamically mapping out a
  // single iteration per task at a time
  //
  forall depth in dynamic(depths, chunkSize=1) {
    const iterations = 1 << (maxDepth - depth + minDepth);
    var check = 0;

    for i in 1..iterations {
      const posT = buildTree( i, depth),
            negT = buildTree(-i, depth);
      check += checksum(posT) + checksum(negT);
      free(posT);
      free(negT);
    }
    results[depth] = (2*iterations, check);
  }

  //
  // Print out the results for the trees of varying depths
  //
  for depth in depths do
    writeln(results[depth](1), "\t trees of depth ", depth, "\t check: ",
            results[depth](2));

  //
  // Checksum the long-lived tree, print its results, and free it
  //
  writeln("long lived tree of depth ", maxDepth, "\t check: ",
          checksum(longLivedTree));
  free(longLivedTree);
}

//
// Build a tree
//
proc buildTree(item, depth): Tree {
  if depth <= 0 then
    return new Tree(item);
  else
    return new Tree(item, buildTree(2*item-1, depth-1),
                          buildTree(2*item  , depth-1));
}

//
// Compute a simple checksum on a tree
//
proc checksum(T): int {
  if (T.left == nil) then
    return T.item;
  else
    return (T.item + checksum(T.left) - checksum(T.right));
}

//
// Recursively free a tree
//
proc free(T) {
  if (T.left) {
    free(T.left);
    free(T.right);
  }
  delete T;
}


Refactored initialization to remove repetitive code

git-svn-id: 88467cb1fb04b8a755be7e1ee1026be4190196ef@20711 3a8e244f-b0f2-452b-bcba-4c88e055c3ca

config const debugInit = false;

// Configs if we're init-ing from a file

config const filename = "";
const initFromFile = (filename != "");

// Configs if we're computing the input set

config const elemsPerEdge = 0;
config const initialWidth = 1.125;

// Verify that configs are set appropriately

if initFromFile {
  if elemsPerEdge != 0 then
    writeln("WARNING: --elemsPerEdge has no effect when using an input file");
}  else {
  if elemsPerEdge == 0 then
    halt("you must either set --filename or --elemsPerEdge to run LULESH");
}

// Helper variables for reading from a file

var infile: file;
var reader: channel(false, iokind.dynamic, true);

if initFromFile {
  infile = open(filename, iomode.r);
  reader = infile.reader();
}

// Helper variables for computing the index set

param numDims = 3;

const nodesPerEdge = elemsPerEdge + 1,
      DimNodeRange = 0..#nodesPerEdge,
      DimNodeFace  = {DimNodeRange, DimNodeRange};

// read/compute the problem size

proc getProblemSize() {
  const (numElems, numNodes) = if (initFromFile) then
                                 reader.read(int, int)
                               else
                                 (elemsPerEdge**numDims, nodesPerEdge**numDims);

  if (debugInit) then
    writeln(numElems, " ", numNodes);

  return (numElems, numNodes);
}

// read/compute the coordinates

proc InitializeCoordinates(X, Y, Z) {
  if (initFromFile) {
    for (x,y,z) in zip(X,Y,Z) do
      reader.read(x, y, z);
  } else {
    forall (num, x, y, z) in zip(X.domain, X, Y, Z) {
      const (i,j,k) = nodeIdx1DTo3D(num);
      x = initialWidth * k / elemsPerEdge;
      y = initialWidth * j / elemsPerEdge;
      z = initialWidth * i / elemsPerEdge;
    }
  }

  if debugInit then
    for (x,y,z) in zip(X,Y,Z) do
      writeln(format("%.6f",x), " ", format("%.6f",y), " ", format("%.6f",z));
}

// read/compute the element-to-node mapping

proc initElemToNodeMapping(elemToNode: [?D]) {
  if (initFromFile) {
    param nodesPerElem = elemToNode[D.low].size;
    for nodelist in elemToNode do
      for i in 1..nodesPerElem do
        reader.read(nodelist[i]);

    if debugInit {
      writeln("elemToNode mappings are:");
      for nodelist in elemToNode do
        writeln(nodelist);
    }
  } else {
    forall (num, nodelist) in zip(elemToNode.domain, elemToNode) {
      const (i,j,k) = elemIdx1DTo3D(num);
      nodelist[1] = nodeIdx3DTo1D(i,   j,   k  );
      nodelist[2] = nodeIdx3DTo1D(i,   j,   k+1);
      nodelist[3] = nodeIdx3DTo1D(i,   j+1, k+1);
      nodelist[4] = nodeIdx3DTo1D(i,   j+1, k  );
      nodelist[5] = nodeIdx3DTo1D(i+1, j,   k  );
      nodelist[6] = nodeIdx3DTo1D(i+1, j,   k+1);
      nodelist[7] = nodeIdx3DTo1D(i+1, j+1, k+1);
      nodelist[8] = nodeIdx3DTo1D(i+1, j+1, k  );
    }
  }

  if debugInit then
    for nodelist in elemToNode {
      for i in 1..nodelist.size do
        write(nodelist(i), " ");
      writeln();
    }
}

// read/compute the greek variables

proc initGreekVars(lxim, lxip, letam, letap, lzetam, lzetap) {
  if (initFromFile) {
    for (xm,xp,em,ep,zm,zp) in zip(lxim, lxip, letam, letap, lzetam, lzetap) do
      reader.read(xm,xp,em,ep,zm,zp);
  } else {
    forall num in lxim.domain {
      const (i,j,k) = elemIdx1DTo3D(num);

      lxim[num] = if (k == 0)
                    then num
                    else elemIdx3DTo1D(i,j,k-1);

      lxip[num] = if (k == elemsPerEdge-1)
                    then num
                    else elemIdx3DTo1D(i,j,k+1);

      letam[num] = if (j == 0)
                    then num
                    else elemIdx3DTo1D(i,j-1,k);

      letap[num] = if (j == elemsPerEdge-1)
                    then num
                    else elemIdx3DTo1D(i,j+1,k);

      lzetam[num] = if (i == 0)
                    then num
                    else elemIdx3DTo1D(i-1,j,k);

      lzetap[num] = if (i == elemsPerEdge-1)
                    then num
                    else elemIdx3DTo1D(i+1,j,k);
    }
  }
  if (debugInit) then
    for (xm,xp,em,ep,zm,zp) in zip(lxim, lxip, letam, letap, lzetam, lzetap) do
      writeln(xm, " ", xp, " ", em, " ", ep, " ", zm, " ", zp);
}

// read/compute the X, Y, Z symmetry planes

enum dim { X = 3, Y = 2, Z = 1 };

inline proc initSyms(Sym, dir) {
  if (initFromFile) {
    readNodeset(Sym);
  } else {
    for ij in DimNodeFace do
      Sym += nodeIdx2DTo1D(ij, dir, 0);
  }

  if debugInit {
    writeln(Sym.numIndices);
    for n in Sym do
      writeln(n);
  }

  return (Sym.numIndices, Sym);
}

inline proc initXSyms(XSym) {
  initSyms(XSym, dim.X);
}

inline proc initYSyms(YSym) {
  initSyms(YSym, dim.Y);
}

inline proc initZSyms(ZSym) {
  initSyms(ZSym, dim.Z);
}

// read/compute the free surface

inline proc setupFreeSurface(freeSurface) {
  if (initFromFile) {
    readNodeset(freeSurface);
    reader.assertEOF("Input file format error (extra data at EOF)");
  } else {
    for ij in DimNodeFace do
      freeSurface += nodeIdx2DTo1D(ij, dim.X, nodesPerEdge-1);

    for ij in DimNodeFace do
      freeSurface += nodeIdx2DTo1D(ij, dim.Y, nodesPerEdge-1);

    for ij in DimNodeFace do
      freeSurface += nodeIdx2DTo1D(ij, dim.Z, nodesPerEdge-1);
  }

  if debugInit {
    use Sort;

    const size = freeSurface.size;
    var sortedSurface: [0..#size] int;

    for (a,b) in zip(sortedSurface, freeSurface) do a = b;
    QuickSort(sortedSurface);

    writeln(size);
    for b in sortedSurface do
      writeln(b);
  }
  return (freeSurface.numIndices, freeSurface);
}

// Helper routines for reading from a file

/* This is a helper routine to read a size and array from a file and
   return it */

proc readNodeset(nodeset) {
  const arrSize = reader.read(int);

  for a in 0..#arrSize do
    nodeset += reader.read(int);
}

// Helper routines for computing the cube input set

inline proc idx3DTo1D((i,j,k), len) {
  return i*len*len + j*len + k;
}

inline proc nodeIdx3DTo1D(i,j,k) {
  return idx3DTo1D((i, j, k), nodesPerEdge);
}

inline proc elemIdx3DTo1D(i,j,k) {
  return idx3DTo1D((i,j,k), elemsPerEdge);
}

inline proc idx1DTo3D(ind, len) {
  return (ind/(len*len), (ind/len)%len, ind%len);
}

inline proc nodeIdx1DTo3D(ind) {
  return idx1DTo3D(ind, nodesPerEdge);
}

inline proc elemIdx1DTo3D(ind) {
  return idx1DTo3D(ind, elemsPerEdge);
}

/* Turn a 2D node index into a 3D index by inserting the value
   'newval' in diemnsion 'newdim' */

inline proc nodeIdx2DTo1D(ij, newdim, newval) {
  var ijk: 3*int;
  for i in 1..numDims do
    ijk[i] = if (i==newdim) then newval else ij[i - (i>newdim):int];
  return nodeIdx3DTo1D((...ijk));
}

config const debugInit = false;

// Configs if we're init-ing from a file

config const filename = "";
const initFromFile = (filename != "");

// Configs if we're computing the input set

config const elemsPerEdge = 0;
config const initialWidth = 1.125;

// Verify that configs are set appropriately

if initFromFile {
  if elemsPerEdge != 0 then
    writeln("WARNING: --elemsPerEdge has no effect when using an input file");
}  else {
  if elemsPerEdge == 0 then
    halt("you must either set --filename or --elemsPerEdge to run LULESH");
}

// Helper variables for reading from a file

var infile: file;
var reader: channel(false, iokind.dynamic, true);

if initFromFile {
  infile = open(filename, iomode.r);
  reader = infile.reader();
}

// Helper variables for computing the index set
const        nodesPerEdge = elemsPerEdge + 1;

const DimNodeRange = 0..#nodesPerEdge,
      DimNodeFace  = {DimNodeRange, DimNodeRange};

// read/compute the problem size

proc getProblemSize() {
  param        numDims = 3;
  const (numElems, numNodes) = if (initFromFile) then
                                 reader.read(int, int)
                               else
                                 (elemsPerEdge**numDims, nodesPerEdge**numDims);

  if (debugInit) then
    writeln(numElems, " ", numNodes);

  return (numElems, numNodes);
}

// read/compute the coordinates

proc InitializeCoordinates(X, Y, Z) {
  if (initFromFile) {
    for (x,y,z) in zip(X,Y,Z) do
      reader.read(x, y, z);
  } else {
    forall (num, x, y, z) in zip(X.domain, X, Y, Z) {
      const (i,j,k) = nodeIdx1DTo3D(num);
      x = initialWidth * k / elemsPerEdge;
      y = initialWidth * j / elemsPerEdge;
      z = initialWidth * i / elemsPerEdge;
    }
  }

  if debugInit then
    for (x,y,z) in zip(X,Y,Z) do
      writeln(format("%.6f",x), " ", format("%.6f",y), " ", format("%.6f",z));
}

// read/compute the element-to-node mapping

proc initElemToNodeMapping(elemToNode: [?D]) {
  if (initFromFile) {
    param nodesPerElem = elemToNode[D.low].size;
    for nodelist in elemToNode do
      for i in 1..nodesPerElem do
        reader.read(nodelist[i]);

    if debugInit {
      writeln("elemToNode mappings are:");
      for nodelist in elemToNode do
        writeln(nodelist);
    }
  } else {
    forall (num, nodelist) in zip(elemToNode.domain, elemToNode) {
      const (i,j,k) = elemIdx1DTo3D(num);
      nodelist[1] = nodeIdx3DTo1D(i,   j,   k  );
      nodelist[2] = nodeIdx3DTo1D(i,   j,   k+1);
      nodelist[3] = nodeIdx3DTo1D(i,   j+1, k+1);
      nodelist[4] = nodeIdx3DTo1D(i,   j+1, k  );
      nodelist[5] = nodeIdx3DTo1D(i+1, j,   k  );
      nodelist[6] = nodeIdx3DTo1D(i+1, j,   k+1);
      nodelist[7] = nodeIdx3DTo1D(i+1, j+1, k+1);
      nodelist[8] = nodeIdx3DTo1D(i+1, j+1, k  );
    }
  }

  if debugInit then
    for nodelist in elemToNode {
      for i in 1..nodelist.size do
        write(nodelist(i), " ");
      writeln();
    }
}

// read/compute the greek variables

proc initGreekVars(lxim, lxip, letam, letap, lzetam, lzetap) {
  if (initFromFile) {
    for (xm,xp,em,ep,zm,zp) in zip(lxim, lxip, letam, letap, lzetam, lzetap) do
      reader.read(xm,xp,em,ep,zm,zp);
  } else {
    forall num in lxim.domain {
      const (i,j,k) = elemIdx1DTo3D(num);

      lxim[num] = if (k == 0)
                    then num
                    else elemIdx3DTo1D(i,j,k-1);

      lxip[num] = if (k == elemsPerEdge-1)
                    then num
                    else elemIdx3DTo1D(i,j,k+1);

      letam[num] = if (j == 0)
                    then num
                    else elemIdx3DTo1D(i,j-1,k);

      letap[num] = if (j == elemsPerEdge-1)
                    then num
                    else elemIdx3DTo1D(i,j+1,k);

      lzetam[num] = if (i == 0)
                    then num
                    else elemIdx3DTo1D(i-1,j,k);

      lzetap[num] = if (i == elemsPerEdge-1)
                    then num
                    else elemIdx3DTo1D(i+1,j,k);
    }
  }
  if (debugInit) then
    for (xm,xp,em,ep,zm,zp) in zip(lxim, lxip, letam, letap, lzetam, lzetap) do
      writeln(xm, " ", xp, " ", em, " ", ep, " ", zm, " ", zp);
}

// read/compute the X, Y, Z symmetry planes

inline proc initXSyms(XSym) {
  if (initFromFile) {
    readNodeset(XSym);
  } else {
    for ((i,j),ind) in zip(DimNodeFace, 0..) do
      XSym += nodeIdx3DTo1D(i,j,0);
  }

  if debugInit {
    writeln(XSym.numIndices);
    for x in XSym do
      writeln(x);
  }

  return (XSym.numIndices, XSym);
}

inline proc initYSyms(YSym) {
  if (initFromFile) {
    readNodeset(YSym);
  } else {
    for ((i,j),ind) in zip(DimNodeFace, 0..) do
      YSym += nodeIdx3DTo1D(i,0,j);
  }

  if debugInit {
    writeln(YSym.numIndices);
    for x in YSym do
      writeln(x);
  }

  return (YSym.numIndices, YSym);
}

inline proc initZSyms(ZSym) {
  if (initFromFile) {
    readNodeset(ZSym);
  } else {
    for ((i,j),ind) in zip(DimNodeFace, 0..) do
      ZSym += nodeIdx3DTo1D(0,i,j);
  }

  if debugInit {
    writeln(ZSym.numIndices);
    for x in ZSym do
      writeln(x);
  }

  return (ZSym.numIndices, ZSym);
}

// read/compute the free surface

inline proc setupFreeSurface(freeSurface) {
  if (initFromFile) {
    readNodeset(freeSurface);
    reader.assertEOF("Input file format error (extra data at EOF)");
  } else {
    for (i,j) in DimNodeFace do
      freeSurface += nodeIdx3DTo1D(i,j,nodesPerEdge-1);

    for (i,j) in DimNodeFace do
      freeSurface += nodeIdx3DTo1D(i,nodesPerEdge-1,j);

    for (i,j) in DimNodeFace do
      freeSurface += nodeIdx3DTo1D(nodesPerEdge-1,i,j);
  }

  if debugInit {
    use Sort;

    const size = freeSurface.size;
    var sortedSurface: [0..#size] int;

    for (a,b) in zip(sortedSurface, freeSurface) do a = b;
    QuickSort(sortedSurface);

    writeln(size);
    for b in sortedSurface do
      writeln(b);
  }
  return (freeSurface.numIndices, freeSurface);
}

// Helper routines for reading from a file

/* This is a helper routine to read a size and array from a file and
   return it */

proc readNodeset(nodeset) {
  const arrSize = reader.read(int);

  for a in 0..#arrSize do
    nodeset += reader.read(int);
}

// Helper routines for computing the cube input set

inline proc idx3DTo1D((i,j,k), len) {
  return i*len*len + j*len + k;
}

inline proc nodeIdx3DTo1D(i,j,k) {
  return idx3DTo1D((i, j, k), nodesPerEdge);
}

inline proc elemIdx3DTo1D(i,j,k) {
  return idx3DTo1D((i,j,k), elemsPerEdge);
}

inline proc idx1DTo3D(ind, len) {
  return (ind/(len*len), (ind/len)%len, ind%len);
}

inline proc nodeIdx1DTo3D(ind) {
  return idx1DTo3D(ind, nodesPerEdge);
}

inline proc elemIdx1DTo3D(ind) {
  return idx1DTo3D(ind, elemsPerEdge);
}