/*
Selah Lynch  hbug.h  Jun 2004
Class HBug declarations

This class is for running a heatbug simulation,
on parallel computers using mpi.
The bugs are emitting heat and wandering
around towards their ideal temperature.
The environment diffuses heat.

The method for splitting this up over parallel 
computers was making each computer in charge of some 
part of the two dimensional grid.

BUGS!!!! (problems)
-if i put too many bugs on a small grid wierd things happen.
-be careful of heat getting cut off because of integers, need to
   use high enough values for heat emission.

*/


#ifndef HBUG_H
#define HBUG_H



#include <fstream.h>
#include "mpi.h"


class HBug{
 public:
  HBug(int size, int numberofbugs, int seed=0);
  //constructor
  //sets cluster variables such as myrank, and sizeofcluster
  //allocates space for grids, and sets grids to zero
  //for now size MUST be larger than the number of computers
  //sets bugs on grid

  ~HBug();

  void Display(int whichgrid, ostream& out=cout, bool forvisual=false);
  static const int BUGS=44, HEAT=33, DELT=22;
  //display options, which grid to display
  //PROBLEM when too many bugs on a grid

  void TimeStep();
  //EmittHeat, Diffuse, MoveBugs, increment time counter

  void SetVar(int hpb, int it, double cc);

  //private:

  void MakeBugs(int howmany, int seed=0);
  //place 'howmany' non overlaping bugs on the grid

  void MakeGrids(int size);

  void AllocGrids();
  //allocates space for all the grids

  int Widthv(int rank);
  //calculates virual width of rank
  //this is because some widths are 1 more than others
  //when the clustersize doesnt divide evenly into the
  //gridsize

  void DisplaySub(int rank, int whichgrid, ostream& out=cout, bool forvisual=false);
  //displays the lines of the grid on computer 'rank'

  char IntToPix(int i, int whichgrid);
  //used by display fn
  //for BUG 0 -> '.', 1->'@'
  //for HEAT  'X'  'x'  '*'  '.'  ' '

  void DisplayLine(int* data, int whichgrid, ostream& out=cout, bool forvisual=false);
  //displays that line of data
  //assumes the line of data is the size of the grid
  //puts a carriage return at the end of it

  void DistrBugs(int& counter);
  //gives the counter a value that randomly distributes how many
  //bugs should be in that section

  void MakeSubBugs(int numbugs);
  //makes numbugs bugs on each subcomputer

  void CoolDown();
  //takes the total heat, divides it by a constant, and for that many
  //spaces it finds a random space and subtracts 1 heat from it, 
  //unless its zero

  void EmittHeat();
  //each bug emitts a constant amount of heat each timestep
  //only on real parts of the

  void Diffuse(double coF=.2);
  //take difference between each pair of adjacent spots
  //multiply by a coefficent
  //transfer that much energy from hot spot to cold spot
  //dont change anything till all transfers have been calculated
  //do fn by looking at each block and summing up its transfers
  //only need to do the real width

  void MoveBugs();
  //trying to reach ideal temperature
  //each bug must move in a direction, cant stand still
  //should be moving towards other bugs
  //assumes no bugs on edges
  //assumes fresh heat values have been copied to edges
  //looks
  //get rid of all bugs currently on edges...can do that at the end
  //depending on how ideal a spot temp is, that is the probability 
  //of the bug moving there

  void MoveABug(int x, int y);

  void MvBg(int x, int y, int dir);

  void ProbMove(int (&prob)[4], int x, int y, int idealtemp);
  //sets prob to values between 0 and 1000 that represent the
  //probibility the bug has to move that way

  void DeleteEdges();

  static const int FROM=78, TO=93;
  void CopyEdges(int whichgrid);
  //edges are the parts of the real grid that are not part of the virtual grid
  //they store one line of overlap from other computers so the grids can interact
  //can copy information from the edges to the virtual graph ...FROM option
  //or copy info from virtal graph to edges ...TO option
  //bugs adds edges values to main grid
  //heat just copies values from main grid to edges

  static const int UP=1, DOWN=2, LEFT=3, RIGHT=0;
  void FindUDLR( int** grid, int x, int y, int* (&dir)[4]);
  //this function's x and y must be within the virtual range!!
  //right and left can return things off the virtual grid
  //wraps around in y direction
  //for use in diffuse and movebugs

  void GatherData();

  double Unhappiness();
  //must be called by all computers at once so they work together

  double TotHeat();


  static void check(bool, char*);

  int** bugrid; //the bug grid on this computer, 1's and 0's only
  int** heatgrid; //the grid of heat values on this computer
  int** dgrid; //used in diffuse, save change to temp
  int** numtomove; //used in movebugs, how many bugs to move from this spot
  int myrank, sizeofcluster;
  int widthv, widthr;
  int length;
  //withv=width virtual, withr= width real
  //withr=widthv+2
  //the sum of all widthv's = sizeofgrid = length

  int err;  //the rank to output error messages from

  int sizeofgrid;
  int howmanybugs;

  int idealtemp;
  int heatperbug;
  double coolcoeff;

  int time;

  ofstream dataout;

  static const int ROOT=0;
  MPI_Status s;
};



#endif
