/* $Id: Mesh.java,v 1.1 2000/03/14 14:36:48 thomasj Exp $ */

/******************************************************************************
* Mesh - Discretization in one dimension
******************************************************************************/
class Mesh {

  /** Coordinates */    double[] x;
  /** Interval sizes */ double[] dx;

  /** Gridfunction
    @return Gridfunction(in [0,1]) at x(in [0,1]) */

  private double gridfunction(double x){
    int        n = 2;
    double     p = 0.;
    double[] w_1 = new double[n];
    double[] x_1 = new double[n];

    w_1[0]= .1;
    x_1[0]= .6;
    w_1[1]= .05;
    x_1[1]= .2;

    double tan1=0;
    double tan2=0;
    for (int j=0; j<n; j++){
      tan1+=Math.atan((x-x_1[j])/w_1[j]) + Math.atan(x_1[j]/w_1[j]);
      tan2+=Math.atan((1-x_1[j])/w_1[j]) + Math.atan(x_1[j]/w_1[j]);
    }
    double fun = p*x + (1-p)*tan1/tan2;

    return fun;
  } // gridfunction

  public Mesh(Data runData) {
    int    nbrPts_ = runData.getInt(Data.NPTS);            //Parameters
    double start_  = runData.getDouble(Data.BOX0);
    double end_    = runData.getDouble(Data.BOXLEN);

    int N_dummy=200*nbrPts_;          // Number of sub-mesh points.
    double[] dummy;
    dummy = new double[N_dummy];      // The sub-mesh.
    x     = new double[nbrPts_];      // The mesh.
    dx    = new double[nbrPts_];      // Distance to the next mesh-point.


    double dx0=1./((double)(N_dummy));
    for (int j=0; j<N_dummy; j++)
      dummy[j]=gridfunction((j+1)*dx0);

    int n=0;
    int flag;
    double dx1=1./((double)(nbrPts_));
    x[0]=start_;
    for (int j=1; j<nbrPts_; j++) {
      flag=0;
      while (flag==0){
	if (dummy[n]>j*dx1){
	  x[j]=(end_-start_)*(double)(n)*dx0+start_;
	  dx[j-1]=x[j]-x[j-1];
	  flag=1;
	}
	else
	  n++;
      }
    }
    dx[nbrPts_-1]=end_-x[nbrPts_-1];
  }
  
  /** Grid Size
      @return Number of mesh points */
  public int size() { return x.length; }
    
  /** Coordinate values 
      @return An Array with coordinates */
  public double[] points() { return x; }

  /** Coordinate value
      @return The value of a coordinate */
  public double   point(int i) { return x[i]; }

  /** Spacing between mesh points
      @return An Array with the interval sizes */
    public double[] intervals() { return dx; }
    
  /** Space to next grid point
      @return The interval size */
    public double   interval(int i) { return dx[i]; }

  /** Coordinate boundaries
      @return {min(x), max(x) */
  public double[] limits() {
    double[] lim = {x[0], x[0]};
    for (int i=1;i<x.length;i++) {
      if (x[i]<lim[0]) {lim[0]=x[i];};
      if (x[i]>lim[1]) {lim[1]=x[i];};
    }
    return lim;
  }
    
  /** For debugging */
  public String toString() {
    StringBuffer str = new StringBuffer();
    str.append("RegularMesh[").append(Double.toString(x[0]))
      .append(" , ").append(Double.toString(x[2]))
      .append(" .. ").append(Double.toString(x[x.length-1]))
      .append("]");
    return str.toString();
  }

}//End of Mesh
