bool BracketIsValid(avtPoincareIC *poincare_ic)
{
  Vector xzplane(0,1,0);
  FieldlineLib fieldlib;
  avtPoincareIC *_a = poincare_ic->a_IC;
  avtPoincareIC *_b = poincare_ic;
  avtPoincareIC *_c = poincare_ic->c_IC;        
  std::vector<avtVector> a_puncturePoints;
  std::vector<avtVector> b_puncturePoints;
  std::vector<avtVector> c_puncturePoints;
  fieldlib.getPunctures(_a->points,xzplane,a_puncturePoints);
  fieldlib.getPunctures(_b->points,xzplane,b_puncturePoints);
  fieldlib.getPunctures(_c->points,xzplane,c_puncturePoints);
                
  // Need to get distances for each a, b & c
  int a_i = FindMinimizationIndex(_a);
  int b_i = FindMinimizationIndex(_b);
  int c_i = FindMinimizationIndex(_c);

  if (3 <= RATIONAL_DEBUG)
    {
      std::cerr << "LINE " << __LINE__ << "  " << "a_i, b_i, c_i: "             <<a_i;
      if (a_i > -1)
        std::cerr <<"\n"<< VectorToString(a_puncturePoints[a_i])<<",\n"<<b_i;
      if (b_i > -1) 
        std::cerr << VectorToString(b_puncturePoints[b_i])<<",\n"<<c_i;
      if (c_i > -1)     
        std::cerr << VectorToString(c_puncturePoints[c_i]);
      std::cerr << std::endl;
    }
      
  return !(a_i == -1 || b_i == -1 || c_i == -1);
}
double FindMinimizationDistance( avtPoincareIC* ic)
{
  if (4 <= RATIONAL_DEBUG)
    cerr << "Finding Minimization Distance...\n";

  std::vector<avtVector> puncturePoints;
  FieldlineLib fieldlib;
  fieldlib.getPunctures(ic->points, avtVector(0, 1, 0), puncturePoints);

  if (puncturePoints.size() < 2*ic->properties.toroidalWinding)
    {
      cerr << "Not enough puncture points to find correct Rational Surface Minimization distance. Failing.\n";
      cerr << "need "<<2*ic->properties.toroidalWinding<<" puncture pts at least.\n";
      return -1;
    }

  int ix = FindMinimizationIndex(ic);

  avtVector puncture1 = puncturePoints[ix];
  avtVector puncture2 = puncturePoints[ix + ic->properties.toroidalWinding];

  double dist = (puncture1 - puncture2).length();

  return dist;
}
//*******************
// To start the minimization, we need to define three points
// If the middle point ('b) is already lower than the
// other two we can go straight to
// minimization. Otherwise, we have to bracket the
// minimum.  First things first, setup the two new
// points (b & c) and send them off
bool PrepareToBracket(avtPoincareIC *seed,
                      avtVector &newA,
                      avtVector &newB,
                      avtVector &newC)
{
  if (5 <= RATIONAL_DEBUG)
    std::cerr<< "Line: " << __LINE__ <<" Preparing to bracket the minimum"<<std::endl;
  
  Vector xzplane(0,1,0);
  FieldlineLib fieldlib;
  
  std::vector<avtVector> seed_puncture_points;
  fieldlib.getPunctures( seed->points, xzplane,
                         seed_puncture_points);
  avtVector maxPuncture;
  avtVector origPt1 = seed->properties.rationalPt1;
  avtVector origPt2 = seed->properties.rationalPt2;
  int ix = FindMinimizationIndex(seed);
  if (1 <= RATIONAL_DEBUG)
    cerr <<"Line: "<<__LINE__<< " Bracketing inside Original Rational Pts:\n"<<VectorToString(origPt1)<<"\n"<<VectorToString(origPt2)<<std::endl;
  if (ix < 0)
    return false;  

  maxPuncture = seed_puncture_points[ix];
  
  avtVector origChord = origPt2 - origPt1;
  avtVector perpendicular = -origChord.cross(avtVector(0,1,0));

  double xa = (origPt1 - maxPuncture).dot(perpendicular);
  perpendicular.normalize();
  
  double minDist = 2 * MAX_SPACING;
  if (xa < minDist)
    xa = minDist;

  avtVector intersection = maxPuncture + xa * perpendicular;

  cerr << "Max Puncture: "<<VectorToString(maxPuncture)<<"\nxa: "<<xa<<"\nintersection: "<<VectorToString(intersection)<<"\n";
  
  avtVector newPt1 = intersection;
  avtVector newPt2 = maxPuncture + GOLD * (newPt1 - maxPuncture);

  newPt1[1] =  Z_OFFSET;
  newPt2[1] =  Z_OFFSET;
  
  newA = maxPuncture;
  newB = newPt1;
  newC = newPt2;

  if (1 <= RATIONAL_DEBUG)
    cerr<<"LINE "<<__LINE__<<"New A,B,C:\n"<< VectorToString(newA) <<"\n"<< VectorToString(newB) <<"\n"<< VectorToString(newC) <<"\n";

  seed->properties.analysisMethod = FieldlineProperties::RATIONAL_SEARCH;
  seed->properties.searchState = FieldlineProperties::MINIMIZING_A;
  
  return true;
}
bool NeedToMinimize(avtPoincareIC *poincare_ic)
{
  Vector xzplane(0,1,0);
  FieldlineLib fieldlib;

  std::vector<avtVector> seed_puncture_points;
  fieldlib.getPunctures( poincare_ic->points, xzplane,
                         seed_puncture_points);

  std::vector<avtVector> orig_puncture_points;
  fieldlib.getPunctures( poincare_ic->src_rational_ic->points, xzplane,
                         orig_puncture_points);

  // Need to get distances for each a, b & c
  int _i = FindMinimizationIndex(poincare_ic);
  // Find distance between puncture points
  double _dist = PythDist(seed_puncture_points[_i],seed_puncture_points[_i+poincare_ic->properties.toroidalWinding]);

  return (_dist >  MAX_SPACING);
}
bool PrepareToMinimize(avtPoincareIC *poincare_ic, avtVector &newPt, bool &cbGTba)
{
  // Have bracketed the minimum
  Vector xzplane(0,1,0);
  FieldlineLib fieldlib;
  avtPoincareIC *_a = poincare_ic->a_IC;
  avtPoincareIC *_b = poincare_ic;
  avtPoincareIC *_c = poincare_ic->c_IC;        
  std::vector<avtVector> a_puncturePoints;
  std::vector<avtVector> b_puncturePoints;
  std::vector<avtVector> c_puncturePoints;
  fieldlib.getPunctures(_a->points,xzplane,a_puncturePoints);
  fieldlib.getPunctures(_b->points,xzplane,b_puncturePoints);
  fieldlib.getPunctures(_c->points,xzplane,c_puncturePoints);
                
  // Need to get distances for each a, b & c
  int a_i = FindMinimizationIndex(_a);
  int b_i = FindMinimizationIndex(_b);
  int c_i = FindMinimizationIndex(_c);

  _a->properties.searchState = FieldlineProperties::MINIMIZING_X0;
  _c->properties.searchState = FieldlineProperties::MINIMIZING_X3;
  _a->properties.analysisMethod = FieldlineProperties::RATIONAL_MINIMIZE;
  _c->properties.analysisMethod = FieldlineProperties::RATIONAL_MINIMIZE;
  _a->properties.rationalPt1 =_b->properties.rationalPt1;
  _a->properties.rationalPt2 =_b->properties.rationalPt2;
              
  double bx_ax,cx_bx;
  double a_x,a_z,b_x,b_z,c_x,c_z;
  a_x = a_puncturePoints[a_i][0];
  a_z = a_puncturePoints[a_i][2];
  b_x = b_puncturePoints[b_i][0];
  b_z = b_puncturePoints[b_i][2];
  c_x = c_puncturePoints[c_i][0];
  c_z = c_puncturePoints[c_i][2];
  bx_ax = PythDist(a_puncturePoints[a_i],b_puncturePoints[b_i]);
  cx_bx = PythDist(b_puncturePoints[b_i],c_puncturePoints[c_i]);
                
  avtVector va = a_puncturePoints[a_i];
  avtVector vb = b_puncturePoints[b_i];
  avtVector vc = c_puncturePoints[c_i];

  if (3 <= RATIONAL_DEBUG)
    {
      std::cerr<<"Line: "<<__LINE__<<"Prepare to minimize: "<<"\n\t"<<VectorToString(a_puncturePoints[a_i])<<"\n\t"<<VectorToString(b_puncturePoints[b_i])<<"\n\t"<<VectorToString(c_puncturePoints[c_i])<<"\n";
    }
  double new_x,new_z;
  if (cx_bx > bx_ax)
    {
      cbGTba = true;
      _b->properties.searchState = FieldlineProperties::MINIMIZING_X1;
      _b->properties.analysisMethod = FieldlineProperties::RATIONAL_MINIMIZE;
      
      newPt = vb + golden_C * (vc-vb);

      if (2 <= RATIONAL_DEBUG)
        std::cerr << "LINE " << __LINE__ << " New Minimization pt:\t"<<VectorToString(newPt)<< std::endl; 
    }
  else
    {
      cbGTba = false;
      _b->properties.searchState = FieldlineProperties::MINIMIZING_X2;
      _b->properties.analysisMethod = FieldlineProperties::RATIONAL_MINIMIZE;
      
      newPt = vb + golden_C * (va-vb);
      
      if (2 <= RATIONAL_DEBUG)   
        std::cerr << "LINE " << __LINE__  << " New Minimization pt:\t"<< VectorToString(newPt) << std::endl; 
    }

  newPt[1] = Z_OFFSET;

    return true;
}
bool UpdateBracket(avtPoincareIC *poincare_ic, bool &swapped, avtVector &C)
{
  if (4 <= RATIONAL_DEBUG)
    std::cerr << "LINE " << __LINE__ << "  " << "Minimum needs to be bracketed" << std::endl;                          

  // Have bracketed the minimum
  Vector xzplane(0,1,0);
  FieldlineLib fieldlib;
  avtPoincareIC *_a = poincare_ic->a_IC;
  avtPoincareIC *_b = poincare_ic;
  avtPoincareIC *_c = poincare_ic->c_IC;        
  std::vector<avtVector> a_puncturePoints;
  std::vector<avtVector> b_puncturePoints;
  std::vector<avtVector> c_puncturePoints;
  fieldlib.getPunctures(_a->points,xzplane,a_puncturePoints);
  fieldlib.getPunctures(_b->points,xzplane,b_puncturePoints);
  fieldlib.getPunctures(_c->points,xzplane,c_puncturePoints);
                
  // Need to get distances for each a, b & c
  double a_dist = FindMinimizationDistance(_a);
  double b_dist = FindMinimizationDistance(_b);
  double c_dist = FindMinimizationDistance(_c);
                
  // Need to swap so a > b
  if ( b_dist > a_dist )
    {
      swapped = true;

      avtPoincareIC *temp = _a;
      _a = _b;
      _b = temp;

      std::vector<avtVector> vtemp = a_puncturePoints;
      a_puncturePoints = b_puncturePoints;
      b_puncturePoints = vtemp;

      int itemp = a_dist;
      a_dist = b_dist;
      b_dist = itemp;

      _a->properties.searchState =
        FieldlineProperties::MINIMIZING_A;
      _b->properties.searchState =
        FieldlineProperties::MINIMIZING_B;

      _b->a_IC = _a;
   }

  if (c_dist >= b_dist)
    return false;

  int a_i = FindMinimizationIndex(_a);
  int b_i = FindMinimizationIndex(_b);
  int c_i = FindMinimizationIndex(_c);

  // For Parabolic Bracketing, not actually implemented, too difficult
  //          double rr = PythDist( _a, _b ) * (b_dist - c_dist);
  //          double qq = PythDist( _c, _b ) * (b_dist - a_dist);

  avtVector va = a_puncturePoints[a_i];
  avtVector vb = b_puncturePoints[b_i];              
  avtVector vc = c_puncturePoints[c_i];
  if (swapped == true)
    {
      vc = vb + GOLD * (vb - va);
    }
  else    
    {
      vc = vb + GOLD * (vc - vb);
    }

  C = vc;
  C[1] = Z_OFFSET;

  return true;
}