#include "grid.h"
#include <stdio.h>

Grid1D 
grid_cons (unsigned int N, double x0, double x1, boundary_condition_types lbt, boundary_condition_types rbt)
{
  double xl, xr;
  if (x0<x1) {xl = x0; xr = x1;}
  else {xl = x1; xr = x0;};
  double h = (xr-xl)/N;

  Grid1D grid;
  grid.iter = 0;
  grid.time = 0;
  grid.lbt = lbt;
  grid.rbt = rbt;
  grid.N = N;
  grid.h = h;
  grid.cells = allocate_memory_for_grid(N);
  // init coordinates
  grid.lbc.x = x0-h/2;
  for (unsigned int i=0; i<N; i++)
    grid.cells[i].x = h/2 + h*i;
  grid.rbc.x = x1+h/2;
  return grid;
};

Cell1D*
allocate_memory_for_grid(unsigned int amount)
{
  Cell1D* cells = (Cell1D*) malloc(amount*sizeof(Cell1D));
  if (cells == NULL)
    {
      perror("Cannot allocate memory for grid\n");
      exit(EXIT_MALLOC_GRID);
    }
  return cells;
};

Grid1D
grid_skel (Grid1D grid)
{
  Grid1D newgrid;
  newgrid = grid;
  newgrid.cells = allocate_memory_for_grid(grid.N);
  for (unsigned int i=0; i<grid.N; i++)
    newgrid.cells[i].x = grid.cells[i].x;
  return newgrid;
}

// output possibilities
int
printGrid(Grid1D const& grid)
{
  char cell_str[1000];
  printf("x\tphi\trho_g\tUg\tUl\tconvergence\n");
  int N = grid.N;
  Cell1D* cells = grid.cells;
  
  sprintf_Cell1D(cell_str, grid.lbc);
  printf("%s\n", cell_str);
  
  for (int i=0; i<N; i++)
    {
      sprintf_Cell1D(cell_str, cells[i]);
      printf("%s\n", cell_str);
    }

  sprintf_Cell1D(cell_str, grid.rbc);
  printf("%s\n", cell_str);

  return 0;
};

int
printGridToFile(Grid1D const& grid)
{
  char filename[20];
  sprintf(filename, "grid%06d", grid.iter);

  FILE* fh = fopen(filename, "w");

  char cell_str[1000];
  fprintf(fh, "x\tphi\trho_g\tUg\tUl\tconvergence\n");
  int N = grid.N;
  Cell1D* cells = grid.cells;
  
  sprintf_Cell1D(cell_str, grid.lbc);
  fprintf(fh, "%s\n", cell_str);
  
  for (int i=0; i<N; i++)
    {
      sprintf_Cell1D(cell_str, cells[i]);
      fprintf(fh, "%s\n", cell_str);
    }

  sprintf_Cell1D(cell_str, grid.rbc);
  fprintf(fh, "%s\n", cell_str);

  fclose(fh);

  return 0;
};