package jass.generators; import jass.engine.*; /** @author Kees van den Doel (kvdoel@cs.ubc.ca) Implement Webster equation with open ends (pressure=0) and external fluid force applied on left end. u,f on o grid, S (area) on both p on x grid, p=0 on boundaries O x o x o x o x O N grid points, N is odd. Let i= 0,...,N-1 S[i] p[i=0,2...,N-1], u[i=1,3,..,N-2], same for f[] Physical parameters: - pressure deviation PP = rho * p (rho = dmass dens. air) - velocity UU = u/c - force on fluid FF = (rho/c)*f CFL conditions give delta_x = h > c/2*srate. */ public class OpenWebsterTube extends InOut{ /** Sampling rate in Hertz. */ protected float srate; protected double minLen=.15; protected double c = 340; protected double len; // > minLen protected double h; protected int overSamplingFactor = 20; protected int N; protected double[] S; // Area of the segments protected double[] Sold; // Area of the segments protected double[] pu; // velocity u and pressure p on staggered grid protected double[] d_pu; protected double[] outBuf; // oversampled TubeModel tubeModel; private void allocate() { h = 2*c/(2*srate); N = 1 + (int)(minLen/h); if(N%2 == 0) { N--; } System.out.println(N); h = minLen/(N-1); len = minLen; S = new double[N]; Sold = new double[N]; pu = new double[N]; // p on even points, u on odd d_pu = new double[N]; outBuf = new double[getBufferSize()*overSamplingFactor]; for(int i=0;i<N;i++) { S[i] = 1; Sold[i] = 1; pu[i]=0; d_pu[i]=0; } } public void changeTubeModel() { double len = tubeModel.getLength(); for(int k=0;k<N;k++) { double x = k*h; double r = tubeModel.getRadius(x); S[k] = r*r; } for(int k=0;k<N;k++) { System.out.println("s: "+S[k]); } } /* int sdfsdfs=0; public void changeTubeModel() { System.out.println("changed: "+sdfsdfs); if(sdfsdfs++>2) { for(int k=N/2;k<N;k++) { S[k] = .1; } } for(int k=0;k<N;k++) { System.out.println(S[k]); } } */ public void reset() { for(int i=0;i<N;i++) { pu[i]=0; } } /** Create and initialize. @param srate sampling rate in Hertz. @param nTubeSection maximum number of sections (must be even) */ public OpenWebsterTube(float srate, int bufferSize,TubeModel tm) { super(bufferSize); this.srate = srate; this.tubeModel = tm; allocate(); } /** Set an individual segment area @param k index of segment (0,....N-1) @param a area to set */ public void setArea(int k,double a) { S[k]=a; } /** Set all areas @param array of r areas */ public void setAllAreas(double[] a) { for(int k=0;k<N;k++) { S[k] = a[k]; } } /** Compute the next buffer and store in member float[] buf. */ protected void computeBuffer() { float[] tmpbuf = srcBuffers[0]; int bufsz = getBufferSize()*overSamplingFactor; double eta = c/(srate*2*h*overSamplingFactor); //System.out.println(eta); for(int k=0;k<bufsz;k++) { /* Area at time indexed by k is given by (1-spar)S_old + spar * S where spar = (k+1)/bufsz; */ double s_now = (k+1)/bufsz; // runs from 0 -1 over sample buffer to interp. double s_prev = k/bufsz; for(int i=2;i<=N-3;i+=2) { double S_now = (1-s_now)*Sold[i] + s_now*S[i]; double S_prev = (1-s_prev)*Sold[i] + s_prev*S[i]; double S_prev_right = (1-s_prev)*Sold[i+1] + s_prev*S[i+1]; double S_prev_left = (1-s_prev)*Sold[i-1] + s_prev*S[i-1]; double tmp = S_prev/S_now-1; double tmp2 = (S_prev_right*pu[i+1] - S_prev_left*pu[i-1])/S_now; d_pu[i] = tmp*pu[i]-eta*tmp2 + c*c*tmp; //System.out.println(i+" "+d_pu[i]); } for(int i=1;i<N;i+=2) { d_pu[i] = -eta*(pu[i+1]-pu[i-1]); } double damping = .003; for(int i=1;i<N;i+=2) { pu[i] *= (1-damping); } d_pu[1] += tmpbuf[k/overSamplingFactor]/srate; //System.out.println(System.out.println(pu[N-2]+" "+d_pu[N-2]); for(int i=0;i<N;i++) { pu[i] += d_pu[i]; Sold[i] = S[i]; } outBuf[k] = (float)pu[N-2]; } bufsz = getBufferSize(); for(int k=0;k<bufsz;k++) { buf[k] = (float)outBuf[k*overSamplingFactor]; } // System.out.println(buf[0]); } }