void Godunov::MultiPhase(const double & CFL, unsigned phase) {
	double t = 0;
	Cell leftCell;
	Cell rightCell;
	bool phaseInteraction;
	while (t < getMax()) {
		BoundaryConditions();
		for (unsigned i = 0; i < getCell().size(); ++i) {
            phaseInteraction = false;
			leftCell = getCell()[i % getCell().size()];
			rightCell = getCell()[(i + 1) % getCell().size()];
			if (i == getCell().size() - 2)
				continue;
			for (unsigned j = 0; j < phase; ++j)
				if (leftCell.getPhase()[j].getPhi()
						!= rightCell.getPhase()[j].getPhi()) {
					phaseInteraction = true;
					break;
				}
			if (!phaseInteraction) {
				for (unsigned j = 0; j < phase; ++j)
					detachedRiemann(leftCell, rightCell, i, j);
			}
		}
		computeDT(CFL);
		timeIntegration();
		for (unsigned i = 0; i < getCell().size(); ++i) {
			setCell()[i].computeScalFromCons();
		}
		t += getDt();
	}
}
void Godunov::Solve(const double& CFL) {
	//dt_ = 0.00005;
	computeDT(CFL);
	if (getCell()[0].getPhase().size() == 1)
		SinglePhase(CFL);
	else
		MultiPhase(CFL, getCell()[0].getPhase().size());
	BoundaryConditions();
}
Beispiel #3
0
PetscErrorCode IFunction(TS ts,PetscReal t,Vec X,Vec Xdot,Vec F,void *ctx)
{
  PetscErrorCode ierr;
  AppCtx         *user=(AppCtx*)ctx;
  DM             cda;
  DMDACoor2d     **coors;
  PetscScalar    **p,**f,**pdot;
  PetscInt       i,j;
  PetscInt       xs,ys,xm,ym,M,N;
  Vec            localX,gc,localXdot;
  PetscScalar    p_adv1,p_adv2,p_diff;

  PetscFunctionBeginUser;
  ierr = DMDAGetInfo(user->da,NULL,&M,&N,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL);
  ierr = DMGetCoordinateDM(user->da,&cda);CHKERRQ(ierr);
  ierr = DMDAGetCorners(cda,&xs,&ys,0,&xm,&ym,0);CHKERRQ(ierr);

  ierr = DMGetLocalVector(user->da,&localX);CHKERRQ(ierr);
  ierr = DMGetLocalVector(user->da,&localXdot);CHKERRQ(ierr);

  ierr = DMGlobalToLocalBegin(user->da,X,INSERT_VALUES,localX);CHKERRQ(ierr);
  ierr = DMGlobalToLocalEnd(user->da,X,INSERT_VALUES,localX);CHKERRQ(ierr);
  ierr = DMGlobalToLocalBegin(user->da,Xdot,INSERT_VALUES,localXdot);CHKERRQ(ierr);
  ierr = DMGlobalToLocalEnd(user->da,Xdot,INSERT_VALUES,localXdot);CHKERRQ(ierr);

  ierr = DMGetCoordinatesLocal(user->da,&gc);CHKERRQ(ierr);

  ierr = DMDAVecGetArray(cda,gc,&coors);CHKERRQ(ierr);
  ierr = DMDAVecGetArray(user->da,localX,&p);CHKERRQ(ierr);
  ierr = DMDAVecGetArray(user->da,localXdot,&pdot);CHKERRQ(ierr);
  ierr = DMDAVecGetArray(user->da,F,&f);CHKERRQ(ierr);

  user->disper_coe = PetscPowScalar((user->lambda*user->ws)/(2*user->H),2)*user->q*(1.0-PetscExpScalar(-t/user->lambda));
  for (i=xs; i < xs+xm; i++) {
    for (j=ys; j < ys+ym; j++) {
      if (i == 0 || j == 0 || i == M-1 || j == N-1) {
        ierr = BoundaryConditions(p,coors,i,j,M,N,f,user);CHKERRQ(ierr);
      } else {
        ierr = adv1(p,coors[j][i].y,i,j,M,&p_adv1,user);CHKERRQ(ierr);
        ierr = adv2(p,coors[j][i].x,i,j,N,&p_adv2,user);CHKERRQ(ierr);
        ierr = diffuse(p,i,j,t,&p_diff,user);CHKERRQ(ierr);
        f[j][i] = -p_adv1 - p_adv2 + p_diff - pdot[j][i];
      }
    }
  }
  ierr = DMDAVecRestoreArray(user->da,localX,&p);CHKERRQ(ierr);
  ierr = DMDAVecRestoreArray(user->da,localX,&pdot);CHKERRQ(ierr);
  ierr = DMRestoreLocalVector(user->da,&localX);CHKERRQ(ierr);
  ierr = DMRestoreLocalVector(user->da,&localXdot);CHKERRQ(ierr);
  ierr = DMDAVecRestoreArray(user->da,F,&f);CHKERRQ(ierr);
  ierr = DMDAVecRestoreArray(cda,gc,&coors);CHKERRQ(ierr);

  PetscFunctionReturn(0);
}
void Godunov::SinglePhase(const double & CFL) {
	double t = 0;
	while (t < getMax()) {
		BoundaryConditions();
		for (unsigned i = 0; i < getCell().size(); ++i) {
			if (i == getCell().size() - 2)
				continue;
			RiemannSolver riemann(getCell()[i % getCell().size()],
					getCell()[(i + 1) % getCell().size()], 1);
			riemann.solve();
			riemann.phase_star_[0].Sample(0, setCell()[i].setPhase()[0].setU_half(),
					setCell()[i].setPhase()[0].setP_half(),
					setCell()[i].setPhase()[0].setD_half(), riemann.phase_star_[0].pstar[0]
                                                          , riemann.phase_star_[0].ustar[0]);
			setCell()[i].setPhase()[0].InterCellFlux();
		}
		computeDT(CFL);
		timeIntegration();
		for (unsigned i = 0; i < getCell().size(); ++i) {
			setCell()[i].setPhase()[0].computeScalFromCons();
		}
		t += getDt();
	}
}
Beispiel #5
0
long MoveDT(long part, double majorant, double minxs, long *cell, double *xs0, 
	    double *x, double *y, double *z, double *l0, double *u, double *v, 
	    double *w, double E, long id)
{
  long ptr, type, mat, mat0, bc;
  double totxs, l, wgt;

  /* Check particle pointer */

  CheckPointer(FUNCTION_NAME, "(part)", DATA_ARRAY, part);

  /* Check coordinates and direction cosines */

  CheckValue(FUNCTION_NAME, "x", "", *x, -INFTY, INFTY);
  CheckValue(FUNCTION_NAME, "y", "", *y, -INFTY, INFTY);
  CheckValue(FUNCTION_NAME, "z", "", *z, -INFTY, INFTY);
  CheckValue(FUNCTION_NAME, "u", "", *u, -1.0, 1.0);
  CheckValue(FUNCTION_NAME, "v", "", *v, -1.0, 1.0);
  CheckValue(FUNCTION_NAME, "w", "", *w, -1.0, 1.0);

  /* Get particle type */

  type = (long)RDB[part + PARTICLE_TYPE];  

  /* Add to DT fraction counter */
		
  ptr = (long)RDB[RES_DT_TRACK_FRAC];
  CheckPointer(FUNCTION_NAME, "(ptr)", DATA_ARRAY, ptr);
  AddBuf1D(1.0, 1.0, ptr, id, 2 - type);
  
  /* Check cross section and sample path length */
  
  CheckValue(FUNCTION_NAME, "majorant", "", majorant, ZERO, INFTY);
  l = -log(RandF(id))/majorant;

  /* Move particle to collision site */
		  
  *x = *x + *u*l;
  *y = *y + *v*l;
  *z = *z + *w*l;

  /* Set path length */
      
  *l0 = l;

  /* Reset previous material pointer and total xs */

  mat0 = -1;
  totxs = 0.0;

  /* Find location */

  *cell = WhereAmI(*x, *y, *z, *u, *v, *w, id);
  CheckPointer(FUNCTION_NAME, "(cell)", DATA_ARRAY, *cell);

  /* Check if point is outside the geometry */

  if ((long)RDB[*cell + CELL_TYPE] == CELL_TYPE_OUTSIDE)
    {
      /* Check if track is stopped at outer boundary */
		  
      if ((long)RDB[DATA_STOP_AT_BOUNDARY] == NO)
	{
	  /* Set weight to test that albedo boundary conditions were not */
	  /* applied */

	  wgt = 1.0;

	  /* Apply repeated boundary conditions */

	  bc = BoundaryConditions(cell, x, y, z, u, v, w, &wgt, id);

	  /* Check that condition was applied */
	  
	  if (bc != YES)
	    Die(FUNCTION_NAME, "Repeated bc not apllied");
 
	  /* Check change in weight */

	  if (wgt != 1.0)
	    Die(FUNCTION_NAME, "Change in weight (albedo)");

	  /* Find location */

	  *cell = WhereAmI(*x, *y, *z, *u, *v, *w, id);
	  CheckPointer(FUNCTION_NAME, "(cell)", DATA_ARRAY, *cell);
	}
      else 
	{
	  /* Stop track at boundary */

	  StopAtBoundary(cell, x, y, z, l0, *u, *v, *w, id);

	  /* Set cross section */

	  *xs0 = -1.0;

	  /* Check distance */

	  CheckValue(FUNCTION_NAME, "l0", "", *l0, ZERO, INFTY);

	  /* Return surface crossing */
      
	  return TRACK_END_SURF;
	}
    }

  /* Get material pointer */

  mat = (long)RDB[*cell + CELL_PTR_MAT];
  mat = MatPtr(mat, id);
  
  /* Check pointer */
  
  if (mat != mat0)
    {
      /* Get total cross section */
      
      totxs = TotXS(mat, type, E, id);
      
      /* Remember material */
      
      mat0 = mat;
    }
  
  /* Check total xs */
  
  CheckValue(FUNCTION_NAME, "totxs", "", totxs, 0.0, INFTY);
  
  /* Compare to minimum value */
  
  if (totxs > minxs)
    {
      /* Sample between real and virtual collision */
      
      if (RandF(id) < totxs/majorant)
	{
	  /* Set cross section */
	  
	  *xs0 = totxs;
	  
	  /* Add to success counter */
	  
	  ptr = (long)RDB[RES_DT_TRACK_EFF];
	  CheckPointer(FUNCTION_NAME, "(ptr)", DATA_ARRAY,ptr);
	  AddBuf1D(1.0, 1.0, ptr, id, 2 - type);
	  
	  /* Check distance */

	  CheckValue(FUNCTION_NAME, "l0", "", *l0, ZERO, INFTY);

	  /* Return collision */
	  
	  return TRACK_END_COLL;
	}
      else
	{
	  /* Set cross section */
	  
	  *xs0 = -1.0;
	  
	  /* Add to failure counter */
	  
	  ptr = (long)RDB[RES_DT_TRACK_EFF];
	  CheckPointer(FUNCTION_NAME, "(ptr)", DATA_ARRAY,ptr);
	  AddBuf1D(1.0, 1.0, ptr, id, 4 - type);
	  
	  /* Check distance */

	  CheckValue(FUNCTION_NAME, "l0", "", *l0, ZERO, INFTY);

	  /* Return virtual */
	  
	  return TRACK_END_VIRT;
	}
    }
  else
    {
      /* Sample scoring */
      
      if (RandF(id) < minxs/majorant)
	{
	  /* Set cross section */
	  
	  *xs0 = minxs;
	  
	  /* Sample between real and virtual collision */
	  
	  if (RandF(id) < totxs/minxs)
	    {
	      /* Add to success counter */
	      
	      ptr = (long)RDB[RES_DT_TRACK_EFF];
	      CheckPointer(FUNCTION_NAME, "(ptr)", DATA_ARRAY,ptr);
	      AddBuf1D(1.0, 1.0, ptr, id, 2 - type);
	      
	      /* Check distance */

	      CheckValue(FUNCTION_NAME, "l0", "", *l0, ZERO, INFTY);

	      /* Return collision */
	      
	      return TRACK_END_COLL;
	    }
	  else
	    {
	      /* Add to failure counter */
	      
	      ptr = (long)RDB[RES_DT_TRACK_EFF];
	      CheckPointer(FUNCTION_NAME, "(ptr)", DATA_ARRAY,ptr);
	      AddBuf1D(1.0, 1.0, ptr, id, 4 - type);
	      
	      /* Check distance */

	      CheckValue(FUNCTION_NAME, "l0", "", *l0, ZERO, INFTY);
	  
	      /* Return virtual */
	      
	      return TRACK_END_VIRT;
	    }
	}
      else
	{
	  /* Set cross section */
	  
	  *xs0 = -1.0;
	  
	  /* Add to failure counter */
	  
	  ptr = (long)RDB[RES_DT_TRACK_EFF];
	  CheckPointer(FUNCTION_NAME, "(ptr)", DATA_ARRAY,ptr);
	  AddBuf1D(1.0, 1.0, ptr, id, 4 - type);
	  
	  /* Check distance */

	  CheckValue(FUNCTION_NAME, "l0", "", *l0, ZERO, INFTY);

	  /* Return virtual */
	  
	  return TRACK_END_VIRT;
	}
    }
}
int main (int nNumberofArgs,char *argv[])
{
  
  //Test for correct input arguments
	if (nNumberofArgs!=7)
	{
		cout << "FATAL ERROR: wrong number of inputs. The program needs the path (with trailing slash), the filename prefix, window radius, "; 
    cout << "basin order, a switch to use or exclude floodplains and a switch to write rasters if desired." << endl;
		exit(EXIT_SUCCESS);
	}
  
  //load input arguments
  string path = argv[1];
	string filename = argv[2];
  float window_radius = atof(argv[3]); //6
  int BasinOrder = atoi(argv[4]);  //2
  int FloodplainSwitch = atoi(argv[5]);
  int WriteRasters = atoi(argv[6]);  //0 (do not write rasters) or 1 (write rasters) 
  
  //set boundary conditions
  vector<string> BoundaryConditions(4, "No Flux");

  //load dem
  LSDRaster DEM((path+filename+"_dem"), "flt");  
  
  //Fill 
  float MinSlope = 0.0001;
  LSDRaster FilledDEM = DEM.fill(MinSlope);
  
  //surface fitting
  vector<int> raster_selection;
  
  raster_selection.push_back(0);
  raster_selection.push_back(1); //slope 
  raster_selection.push_back(1); //aspect
  raster_selection.push_back(1); //curvature
  raster_selection.push_back(1); //plan curvature
  raster_selection.push_back(0); 
  raster_selection.push_back(0);
  raster_selection.push_back(0);

  vector<LSDRaster> Surfaces = FilledDEM.calculate_polyfit_surface_metrics(window_radius, raster_selection);
  LSDRaster slope = Surfaces[1];
  LSDRaster aspect = Surfaces[2];   
  
  cout << "\nGetting drainage network and basins\n" << endl;

  // get a flow info object
	LSDFlowInfo FlowInfo(BoundaryConditions,FilledDEM);
  
  //get stream net from channel heads
  vector<int> sources = FlowInfo.Ingest_Channel_Heads((path+filename+"_dem_CH"), "flt"); //swap to csv? 
  LSDJunctionNetwork ChanNetwork(sources, FlowInfo);
  LSDIndexRaster StreamNetwork = ChanNetwork.StreamOrderArray_to_LSDIndexRaster();

  //load floodplain and merge with the channel network if required, otherwise the 
  //floodplain mask will only contain the channel data
  LSDIndexRaster ChannelAndFloodplain;

  if (FloodplainSwitch == 1){
    LSDIndexRaster Floodplains((path+filename+"_FloodPlain"), "flt");
    ChannelAndFloodplain = StreamNetwork.MergeChannelWithFloodplain(Floodplains);
  }
  else{
    ChannelAndFloodplain = StreamNetwork;
  }
                                                         
  //Extract basins based on input stream order
  vector< int > basin_junctions = ChanNetwork.ExtractBasinJunctionOrder(BasinOrder, FlowInfo);
  LSDIndexRaster Basin_Raster = ChanNetwork.extract_basins_from_junction_vector(basin_junctions, FlowInfo);
  
  cout << "\nExtracting hilltops and hilltop curvature" << endl;
  
  // extract hilltops - no critical slope filtering is performed here
  LSDRaster hilltops = ChanNetwork.ExtractRidges(FlowInfo);   
     
  //get hilltop curvature using filter to remove positive curvatures         
  LSDRaster cht_raster = FilledDEM.get_hilltop_curvature(Surfaces[3], hilltops);
  LSDRaster CHT = FilledDEM.remove_positive_hilltop_curvature(cht_raster);  
  
  //get d infinity flowdirection and flow area
  Array2D<float> dinf = FilledDEM.D_inf_FlowDir();
  LSDRaster dinf_rast = FilledDEM.LSDRasterTemplate(dinf);
  LSDRaster DinfArea = FilledDEM.D_inf_units();
  
  cout << "Starting hilltop flow routing\n" << endl;
  
  //start of Hilltop flow routing
  string prefix = (path+filename+"_dreich_");  //set a path to write the hillslope length data to, based on the input path and filename given by the user
  
  // these params do not need changed during normal use of the HFR algorithm
  bool print_paths_switch = false;
  int thinning = 1;
  string trace_path = "";
  bool basin_filter_switch = false;                          
  vector<int> Target_Basin_Vector;

  //run HFR    
  vector< Array2D<float> > HFR_Arrays = FlowInfo.HilltopFlowRouting(FilledDEM, hilltops, slope, ChannelAndFloodplain, aspect, prefix, Basin_Raster, Surfaces[4], print_paths_switch, thinning, trace_path, basin_filter_switch, Target_Basin_Vector);
   
  LSDRaster HFR_LH = hilltops.LSDRasterTemplate(HFR_Arrays[1]);
  LSDRaster HFR_Slope = hilltops.LSDRasterTemplate(HFR_Arrays[2]);
  LSDRaster relief = hilltops.LSDRasterTemplate(HFR_Arrays[3]);
  //end of HFR 

  //create lsdbasin objects in a loop over each junction number
  vector< LSDBasin > Basins;

  //slope area plotting parameters - these defaults are usually fine
  float log_bin_width = 0.1;
  int SplineResolution = 10000;
  int bin_threshold = 0;
  float CriticalSlope = 1.2; //this needs modified to generate proper E*R* data
  
  cout << "\nCreating each LSDBasin" << endl;
  
  //loop over each basin, generating an LSDBasin object which contains that basin's measurements
  for (int w = 0; w < int(basin_junctions.size()); ++w){
    
    cout << (w+1) << " / " << basin_junctions.size() << endl;
    
    LSDBasin Basin(basin_junctions[w], FlowInfo, ChanNetwork);
    Basin.set_FlowLength(StreamNetwork, FlowInfo);
    Basin.set_DrainageDensity();
    Basin.set_all_HillslopeLengths(FlowInfo, HFR_LH, slope, DinfArea, log_bin_width, SplineResolution, bin_threshold);
    Basin.set_SlopeMean(FlowInfo, slope);
    Basin.set_AspectMean(FlowInfo, aspect);
    Basin.set_ElevationMean(FlowInfo, FilledDEM);
    Basin.set_ReliefMean(FlowInfo, relief);
    Basin.set_CHTMean(FlowInfo, CHT);
    Basin.set_EStar_RStar(CriticalSlope);
    
    Basins.push_back(Basin);
                             
  }
 
  //create a filestream to write the output data
  // use the input arguments to generate a path and filename for the output file
  ofstream WriteData;                 
  stringstream ss;
  ss << path << filename << "_dreich_PaperData.txt";                
  WriteData.open(ss.str().c_str());

  //write headers
  WriteData << "BasinID HFR_mean HFR_median HFR_stddev HFR_stderr HFR_Nvalues HFR_range HFR_min HFR_max SA_binned_LH SA_Spline_LH LH_Density Area Basin_Slope_mean Basin_Slope_median Basin_Slope_stddev Basin_Slope_stderr Basin_Slope_Nvalues Basin_Slope_range Basin_Slope_min Basin_Slope_max Basin_elev_mean Basin_elev_median Basin_elev_stddev Basin_elev_stderr Basin_elev_Nvalues Basin_elev_Range Basin_elev_min Basin_elev_max Aspect_mean CHT_mean CHT_median CHT_stddev CHT_stderr CHT_Nvalues CHT_range CHT_min CHT_max EStar RStar HT_Slope_mean HT_Slope_median HT_Slope_stddev HT_Slope_stderr HT_Slope_Nvalues HT_Slope_range HT_Slope_min HT_Slope_max HT_relief_mean HT_relief_median HT_relief_stddev HT_relief_stderr HT_relief_Nvalues HT_relief_range HT_relief_min HT_relief_max" << endl;

  cout << "\nWriting data to file\n" << endl;

  //write all data to the opened file, ensuring that there are data points to be written in each basin                                         
  for (int q = 0; q < int(Basins.size()); ++q){
    // only work where we have data points
    if (Basins[q].CalculateNumDataPoints(FlowInfo, HFR_LH) != 0 && Basins[q].CalculateNumDataPoints(FlowInfo, slope) != 0 && Basins[q].CalculateNumDataPoints(FlowInfo, FilledDEM) != 0 && Basins[q].CalculateNumDataPoints(FlowInfo, CHT) != 0 && Basins[q].CalculateNumDataPoints(FlowInfo, HFR_Slope) != 0 && Basins[q].CalculateNumDataPoints(FlowInfo, relief) != 0){
      
      // BasinID
      WriteData << Basins[q].get_Junction()<< " ";
      
      //HFR
      WriteData << Basins[q].get_HillslopeLength_HFR() << " " << Basins[q].CalculateBasinMedian(FlowInfo, HFR_LH) << " " << Basins[q].CalculateBasinStdDev(FlowInfo, HFR_LH) << " " << Basins[q].CalculateBasinStdError(FlowInfo, HFR_LH) << " " << Basins[q].CalculateNumDataPoints(FlowInfo, HFR_LH) << " " << Basins[q].CalculateBasinRange(FlowInfo, HFR_LH) << " " << Basins[q].CalculateBasinMin(FlowInfo, HFR_LH) << " " << Basins[q].CalculateBasinMax(FlowInfo, HFR_LH)<< " ";         
      
      //SA_Bins
      WriteData << Basins[q].get_HillslopeLength_Binned()<< " ";
      
      //SA_Spline
      WriteData << Basins[q].get_HillslopeLength_Spline()<< " ";
      
      //Density
      WriteData << Basins[q].get_HillslopeLength_Density()<< " ";
      
      //Area
      WriteData << Basins[q].get_Area()<< " ";
      
      //Slope_Basin
      WriteData << Basins[q].get_SlopeMean() << " " << Basins[q].CalculateBasinMedian(FlowInfo, slope) << " " << Basins[q].CalculateBasinStdDev(FlowInfo, slope) << " " << Basins[q].CalculateBasinStdError(FlowInfo, slope) << " " << Basins[q].CalculateNumDataPoints(FlowInfo, slope) << " " << Basins[q].CalculateBasinRange(FlowInfo, slope) << " " << Basins[q].CalculateBasinMin(FlowInfo, slope) << " " << Basins[q].CalculateBasinMax(FlowInfo, slope)<< " ";
      
      //Elev_Basin
      WriteData << Basins[q].get_ElevationMean() << " " << Basins[q].CalculateBasinMedian(FlowInfo, FilledDEM) << " " << Basins[q].CalculateBasinStdDev(FlowInfo, FilledDEM) << " " << Basins[q].CalculateBasinStdError(FlowInfo, FilledDEM) << " " << Basins[q].CalculateNumDataPoints(FlowInfo, FilledDEM) << " " << Basins[q].CalculateBasinRange(FlowInfo, FilledDEM) << " " << Basins[q].CalculateBasinMin(FlowInfo, FilledDEM) << " " << Basins[q].CalculateBasinMax(FlowInfo, FilledDEM)<< " ";
      
      //Aspect_Basin
      WriteData << Basins[q].get_AspectMean()<< " ";
      
      //CHT
      WriteData << Basins[q].get_CHTMean() << " " << Basins[q].CalculateBasinMedian(FlowInfo, CHT) << " " << Basins[q].CalculateBasinStdDev(FlowInfo, CHT) << " " << Basins[q].CalculateBasinStdError(FlowInfo, CHT) << " " << Basins[q].CalculateNumDataPoints(FlowInfo, CHT) << " " << Basins[q].CalculateBasinRange(FlowInfo, CHT) << " " << Basins[q].CalculateBasinMin(FlowInfo, CHT) << " " << Basins[q].CalculateBasinMax(FlowInfo, CHT) << " ";
      
      //EStar
      WriteData << Basins[q].get_EStar()<< " ";
      
      //RStar
      WriteData << Basins[q].get_RStar()<< " ";
      
      //Slope_mean
      WriteData << Basins[q].CalculateBasinMean(FlowInfo, HFR_Slope) << " " << Basins[q].CalculateBasinMedian(FlowInfo, HFR_Slope) << " " << Basins[q].CalculateBasinStdDev(FlowInfo, HFR_Slope) << " " << Basins[q].CalculateBasinStdError(FlowInfo, HFR_Slope) << " " << Basins[q].CalculateNumDataPoints(FlowInfo, HFR_Slope) << " " << Basins[q].CalculateBasinRange(FlowInfo, HFR_Slope) << " " << Basins[q].CalculateBasinMin(FlowInfo, HFR_Slope) << " " << Basins[q].CalculateBasinMax(FlowInfo, HFR_Slope)<< " ";
      
      //Relief_mean
      WriteData << Basins[q].get_ReliefMean() << " " << Basins[q].CalculateBasinMedian(FlowInfo, relief) << " " << Basins[q].CalculateBasinStdDev(FlowInfo, relief) << " " << Basins[q].CalculateBasinStdError(FlowInfo, relief) << " " << Basins[q].CalculateNumDataPoints(FlowInfo, relief) << " " << Basins[q].CalculateBasinRange(FlowInfo, relief) << " " << Basins[q].CalculateBasinMin(FlowInfo, relief) << " " << Basins[q].CalculateBasinMax(FlowInfo, relief)<< "\n";
  
    }    
  } 
   
  // close the output file
  WriteData.close();

  //if the user requests the raster to be written, write the rasters
  if (WriteRasters == 1){
    cout << "Writing Rasters\n" << endl;                                   
   // FilledDEM.write_raster((path+filename+"_Fill"), "flt");
    Surfaces[1].write_raster((path+filename+"_dreich_Slope"),"flt");
    //Surfaces[2].write_raster((path+filename+"_Aspect"),"flt");
    //Surfaces[3].write_raster((path+filename+"_Curvature"),"flt");
    //StreamNetwork.write_raster((path+filename+"_STNET"), "flt"); 
    //Basin_Raster.write_raster((path+filename+"_Basins"), "flt"); 
    CHT.write_raster((path+filename+"_dreich_CHT"),"flt");
    HFR_LH.write_raster((path+filename+"_dreich_HFR_LH"),"flt"); 
    HFR_Slope.write_raster((path+filename+"_dreich_HFR_SLP"),"flt");
    relief.write_raster((path+filename+"_dreich_Relief"),"flt");
    
    //perform a hillshade
    //LSDRaster Hillshade = FilledDEM.hillshade(45.0,315.0,1.0);
    //Hillshade.write_raster((path+filename+"_HS"),"flt");
  
  }
}
int main (int nNumberofArgs,char *argv[])
{

  //Test for correct input arguments
	if (nNumberofArgs!=7)
	{
		cout << "FATAL ERROR: wrong number of inputs. The program needs the path (with trailing slash), the filename prefix, the DEM file format, the window radius, ";
    cout << "basin order, and a switch to write rasters if desired." << endl;
		exit(EXIT_SUCCESS);
	}

  //load input arguments
  string Path = argv[1];
	string Prefix = argv[2];
  string DEM_Format = argv[3];
  float window_radius = atof(argv[4]); //6
  int BasinOrder = atoi(argv[5]);  //2
  int WriteRasters = atoi(argv[6]);  //0 (do not write rasters) or 1 (write rasters)

  //set up writers to write the output data
  stringstream ssLH;
  stringstream ssR;
  ssLH << Path << Prefix << "_LHResData_variable.txt";
  ssR << Path << Prefix << "_RResData_variable.txt";

  ofstream WriteLHData;
  WriteLHData.open(ssLH.str().c_str());
  ofstream WriteRData;
  WriteRData.open(ssR.str().c_str());

  //write headers
  WriteLHData << "resolution 2pc 25pc median mean 75pc 98pc minimum maximum" << endl;
  WriteRData << "resolution 2pc 25pc median mean 75pc 98pc minimum maximum" << endl;

  //set boundary conditions
  vector<string> BoundaryConditions(4, "No Flux");

  //array of resolutions to load
  int Resolutions[] = {2, 3, 4, 5, 6, 7, 8, 9, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30};

  for (int a = 0; a < 19; ++a){
	  cout << "Processing DEM " << a+1 << " of " << "19" << endl;

    //create an output filename based on the dem name and the resolution
    stringstream ss;
    ss << Path << Prefix << "_" << Resolutions[a];
    string Filename = ss.str();

    //load dem
    LSDRaster DEM((Filename + "_DEM"), DEM_Format);

    stringstream ssa;
    ssa << Path << Prefix << "_" << Resolutions[a] << "_variable";
    string Filename_variable = ssa.str();

    //Fill
    float MinSlope = 0.0001;
    LSDRaster FilledDEM = DEM.fill(MinSlope);

    //surface fitting
    vector<int> raster_selection;

    raster_selection.push_back(0);
    raster_selection.push_back(1); //slope
    raster_selection.push_back(1); //aspect
    raster_selection.push_back(1); //curvature
    raster_selection.push_back(1); //plan curvature
    raster_selection.push_back(0);
    raster_selection.push_back(0);
    raster_selection.push_back(0);

    int CurrentWindowSize = window_radius;

    vector<LSDRaster> Surfaces = FilledDEM.calculate_polyfit_surface_metrics(CurrentWindowSize, raster_selection);
    LSDRaster slope = Surfaces[1];
    LSDRaster aspect = Surfaces[2];

    cout << "\nGetting drainage network and basins\n" << endl;

    // get a flow info object
  	LSDFlowInfo FlowInfo(BoundaryConditions,FilledDEM);

    //get stream net from channel heads
    stringstream ss_ch;
    ss_ch << Path << "Pelletier/" << Prefix << "_" << Resolutions[a] << "_CH";

    vector<int> sources = FlowInfo.Ingest_Channel_Heads(ss_ch.str(), "bil");
    LSDJunctionNetwork ChanNetwork(sources, FlowInfo);
    LSDIndexRaster StreamNetwork = ChanNetwork.StreamOrderArray_to_LSDIndexRaster();

    //Extract basins based on input stream order
    vector< int > basin_junctions = ChanNetwork.ExtractBasinJunctionOrder(BasinOrder, FlowInfo);
    LSDIndexRaster Basin_Raster = ChanNetwork.extract_basins_from_junction_vector(basin_junctions, FlowInfo);

    cout << "\nExtracting hilltops and hilltop curvature" << endl;

    // extract hilltops - no critical slope filtering is performed here
    LSDRaster hilltops = ChanNetwork.ExtractRidges(FlowInfo);

    //get hilltop curvature using filter to remove positive curvatures
    LSDRaster cht_raster = FilledDEM.get_hilltop_curvature(Surfaces[3], hilltops);
    LSDRaster CHT = FilledDEM.remove_positive_hilltop_curvature(cht_raster);

    cout << "Starting hilltop flow routing\n" << endl;

    // these params do not need changed during normal use of the HFR algorithm
    bool print_paths_switch = false;
    int thinning = 1;
    string trace_path = "";
    bool basin_filter_switch = false;
    vector<int> Target_Basin_Vector;

    //run HFR
    vector< Array2D<float> > HFR_Arrays = FlowInfo.HilltopFlowRouting(FilledDEM, hilltops, slope, StreamNetwork, aspect, Filename_variable, Basin_Raster, Surfaces[4], print_paths_switch, thinning, trace_path, basin_filter_switch, Target_Basin_Vector);

    LSDRaster HFR_LH = hilltops.LSDRasterTemplate(HFR_Arrays[1]);
    LSDRaster relief = hilltops.LSDRasterTemplate(HFR_Arrays[3]);

    //Filter Relief and LH data to remove any values < 2 pixels, as in Grieve et al (2015)
    LSDRaster LH1 = HFR_LH.RemoveBelow(2.0*Resolutions[a]);
    LSDRaster Relief1 = relief.RemoveBelow(2.0*Resolutions[a]);

    //Filter Relief and LH data to remove any values > 10000
    //These are created due to using 1m channel heads on low res data, and inadvertantly
    //sampling nodata values, which gives us massive relief values
    LSDRaster LH = LH1.RemoveAbove(10000);
    LSDRaster Relief = Relief1.RemoveAbove(10000);

    //go through the lh raster and get every value into a 1D vector
    vector<float> LH_vec = Flatten_Without_Nodata(LH.get_RasterData(), LH.get_NoDataValue());
    vector<float> Boxplot = BoxPlot(LH_vec);

    //write the values to the output file
    WriteLHData << Resolutions[a] << " " << Boxplot[0] << " " << Boxplot[1] << " " << Boxplot[2] << " " << Boxplot[3] << " " << Boxplot[4] << " " << Boxplot[5] << " " << Boxplot[6] << " " << Boxplot[7];

    WriteLHData << endl;

    stringstream ss3;
    ss3 << Path << Prefix << "_" << Resolutions[a] << "_Hist_LH_variable.txt";
    print_histogram(LH_vec, 1, ss3.str());

    //go through the relief raster and get every value into a 1D vector
    vector<float> R_vec = Flatten_Without_Nodata(Relief.get_RasterData(), Relief.get_NoDataValue());
    vector<float> Boxplot_R = BoxPlot(R_vec);

    //write the values to the output file
    WriteRData << Resolutions[a] << " " << Boxplot_R[0] << " " << Boxplot_R[1] << " " << Boxplot_R[2] << " " << Boxplot_R[3] << " " << Boxplot_R[4] << " " << Boxplot_R[5] << " " << Boxplot_R[6] << " " << Boxplot_R[7];

    WriteRData << endl;

    stringstream ss4;
    ss4 << Path << Prefix << "_" << Resolutions[a] << "_Hist_R_variable.txt";
    print_histogram(R_vec, 1, ss4.str());

    //if the user requests the rasters to be written, write the rasters
    if (WriteRasters == 1){
      cout << "Writing Rasters\n" << endl;

      Surfaces[1].write_raster((Filename + "_Slope_variable"), DEM_Format);
      CHT.write_raster((Filename + "_CHT_variable"), DEM_Format);
      LH.write_raster((Filename + "_HFR_LH_variable"), DEM_Format);
      Relief.write_raster((Filename + "_Relief_variable"), DEM_Format);

    }
  }
    WriteLHData.close();
    WriteRData.close();
}
int main(int nNumberofArgs, char *argv[])
{
  //Test for correct input arguments
	if (nNumberofArgs!=5)
	{
		cout << "FATAL ERROR: wrong number of inputs. The program needs the path (with trailing slash), the filename prefix, the DEM file format, the window size in spatial units.";
		exit(EXIT_FAILURE);
	}

  //get input args
  string path = argv[1];
  string Prefix = argv[2];
  string DEM_Format = argv[3];
  int WindowSize = atoi(argv[4]);

  //surface fitting
  vector<int> raster_selection;
  raster_selection.push_back(0);
  raster_selection.push_back(1); //slope
  raster_selection.push_back(0);
	raster_selection.push_back(1); //curvature

  //set up a writer to write the output data
  ofstream WriteData;

  //create an output filename based on the dem name
  stringstream ss;

  ss << path << Prefix << "_ChtResData.txt";
  WriteData.open(ss.str().c_str());

  //write headers
  WriteData << "resoulution 2pc 25pc median mean 75pc 98pc minimum maximum" << endl;

  //array of resolutions to load
  int Resolutions[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};

  // vectors to hold the stats about the fitted surface
  vector<float> Curv_vec;

	//set boundary conditions
  vector<string> BoundaryConditions(4, "No Flux");

  for (int a = 0; a < 10; ++a){

	  cout << "Processing DEM " << a+1 << " of " << "10" << endl;

		//load the DEM
    //build the string of the filename to load
		stringstream ss2;
		ss2 << path << Prefix << "_" << Resolutions[a] << "_DEM";
		LSDRaster DEM(ss2.str(), DEM_Format);

		//Fill
		float MinSlope = 0.0001;
		LSDRaster FilledDEM = DEM.fill(MinSlope);

	  int CurrentWindowSize = WindowSize;
	  vector<LSDRaster> Surfaces = FilledDEM.calculate_polyfit_surface_metrics(CurrentWindowSize, raster_selection);

		// get a flow info object
	  LSDFlowInfo FlowInfo(BoundaryConditions,FilledDEM);

	  //get stream net from channel heads
	  vector<int> sources = FlowInfo.Ingest_Channel_Heads((path+Prefix+"_CH"), "csv", 2);

	  LSDJunctionNetwork ChanNetwork(sources, FlowInfo);

		// extract hilltops
    LSDRaster hilltops = ChanNetwork.ExtractRidges(FlowInfo);
    LSDRaster Hilltops = ChanNetwork.ExtractHilltops(hilltops, Surfaces[1], 0.4);


    //get hilltop curvature using filter to remove positive curvatures
    LSDRaster cht_raster = FilledDEM.get_hilltop_curvature(Surfaces[3], Hilltops);
    LSDRaster CHT = FilledDEM.remove_positive_hilltop_curvature(cht_raster);

	  //go through the landscape and get every curvature value into a 1D vector
    Curv_vec = Flatten_Without_Nodata(CHT.get_RasterData(), CHT.get_NoDataValue());

    stringstream ss3;
    ss3 << path << Prefix << "_" << Resolutions[a] << "_Hist_CHT.txt";

    print_histogram(Curv_vec, 0.01, ss3.str());

    vector<float> Boxplot = BoxPlot(Curv_vec);

	  //write the values to the output file
	  WriteData << Resolutions[a] << " " << Boxplot[0] << " " << Boxplot[1] << " " << Boxplot[2] << " " << Boxplot[3] << " " << Boxplot[4] << " " << Boxplot[5] << " " << Boxplot[6] << " " << Boxplot[7];

		WriteData << endl;

  }
  WriteData.close();

}