/*
 * LCR.java by Richard J. Davies
 * from `Introductory Java for Scientists and Engineers'
 * chapter: `Physical Modelling'
 * section: `Example - A.C. Circuit'
 *
 * This program simulates the effect of an LCR filter on a square
 * input waveform.
 */
import uk.co.jscieng.*;
import java.awt.*;


// The `Wave' class is a wrapper for the method
// `f' to allow it to be passed as an argument.
// It implements the initial input waveform.
class Wave implements Plottable
{
  // The frequency of the input waveform.
  public static final double OMEGA = 100.0/3;
  
  // The order of the term in its Fourier series
  // at which we stop evaluation.
  public static final double TERMMAX = 9;
  
  
  // The square wave itself
  public double f(double x)
  {
    double ans = 0;
    
    // Evaluate via Fourier series.
    for (int i=1; i<=TERMMAX; i+=2)
      ans += 4 * Math.sin(i*OMEGA*x) / (Math.PI * i);
    
    return ans;
  }
}


// The `FilteredWave' class is a wrapper for the
// method `f' to allow it to be passed as an
// argument. It implements the output waveform.
class FilteredWave implements Plottable
{
  // Internal storage for circuit parameters.
  private double l, c, r;
  
  
  // The constructor allows circuit parameters
  // to be passed in.
  FilteredWave(double lval, double cval, double rval)
  {
    l = lval;
    c = cval;
    r = rval;
  }
  

  // The filtered square wave itself.
  public double f(double x)
  {
    double ans = 0;
    
    // Evaluate via Fourier series
    for (int i=1; i<=Wave.TERMMAX; i+=2)
    {
      // A useful figure.
      double tmp = i*Wave.OMEGA*l - 1/(i*Wave.OMEGA*c);
      
      // The phase lag on this component of the series.
      double lag = Math.atan(tmp/r);
      
      // The factor dividing the magnitude of this
      // component of the series.
      double mag = Math.sqrt(r*r + tmp*tmp);
      
      // Evaluate the term and add it in.
      ans += 4 * Math.sin(i*Wave.OMEGA*x - lag)
             / (mag * Math.PI * i);
    }
    
    return ans;
  }
}


// The class containing the main method.
public class LCR
{
  public static void main(String[] argv)
  {
    // Show the graphics window, at a size that
    // will show two square waves.
    SciGraph.showGraph(0, 4*Math.PI/Wave.OMEGA,
                       -1.5, 1.5);

    // Plot the input waveform.
    SciGraph.functionPlot(new Wave(), Color.red, 1);
    
    // Plot the output waveform for a filter of
    // L=10, C=0.00001, R=1. This filter will let
    // components of angular frequency 100 through
    // unchanged, and will greatly reduce the magnitudes
    // of those much either side of this figure.
    SciGraph.functionPlot(new FilteredWave(10, 0.00001, 1),
                          Color.blue, 1);
  }
}

