package simulate;

/**
 * Potential that acts like a hard string connecting the centers of two atoms.
 * Meant for use as an intra-molecular interaction.
 * Interaction of atoms is zero if separated by less than the tether length.  Atoms
 * undergo an impulsive attractive collision when attempting to separate by more than the tether distance.
 */
public class PotentialTether implements PotentialHard {

  private double tetherLength, tetherLengthSquared;

  public PotentialTether() {
    setTetherLength(Default.ATOM_SIZE);
  }

  /**
   * Always returns false
   */
  public boolean overlap(AtomPair pair) {return false;}

  /**
   * Accessor method for the tether distance
   */
  public final double getTetherLength() {return tetherLength;}
  /**
   * Accessor method for the tether distance
   */
  public final void setTetherLength(double t) {
      tetherLength = t;
      tetherLengthSquared = t*t;
  }

  /**
   * Implements collision dynamics for pair attempting to separate beyond tether distance
   */
  public final void bump(AtomPair pair) {
        double r2 = pair.r2();
        double factor = 2.0/(pair.atom1().rm() + pair.atom2().rm())*pair.vDotr()/r2;
        pair.cPair.push(factor);
  }


  /**
   * Always returns zero (not yet implemented)
   */
  public double lastCollisionVirial() {return 0.0;}

  
  /**
   * Time at which two atoms will reach the end of their tether, assuming free-flight kinematics
   */
  public final double collisionTime(AtomPair pair) {
    boolean minus;  //flag for +/- root
    double r2 = pair.r2();
    double bij = pair.vDotr();
 //       if(r2 < sig2) {return (bij > 0) ? Double.MAX_VALUE : 0.0;}  //inside wall; no collision
    if(r2 > tetherLengthSquared && bij >= 0) {return 0.0;}  //outside tether, moving apart; collide now
    double v2 = pair.v2();
    double discr = bij*bij - v2 * ( r2 - tetherLengthSquared );
    return (-bij + Math.sqrt(discr))/v2;
    }
  
  /**
   * Returns infinity if separation is greater than tether distance, zero otherwise
   */
    public double energy(AtomPair pair) {
        return (pair.r2() > tetherLengthSquared) ? Double.MAX_VALUE : 0.0;
    }
  
  /**
   * Always returns zero
   */
    public double energyLRC(int n1, int n2, double V) {return 0.0;}
      
}
  