/** applet No. 1066 * * sound scattering in water - periodic sound wave 2D * - multi thread SW2D :: display - asynchronous * - grid 640 x 640, source point/plane * - float precision - material table * * Created by Ikeuchi Mitsuru on November 26 2006. * Copyright (c) 2006-2007 Ikeuchi Mitsuru. All rights reserved. * * ver 0.0.1 2006.11.26 created * ver 0.0.2 2007.06.03 improved code * */ import java.awt.*; import java.awt.event.*; import java.applet.*; public class scatterMatMtPSW2D extends Applet implements MouseListener, MouseMotionListener, ItemListener, ActionListener, AdjustmentListener, Runnable { // ------------------------------------ preset field ----------- Thread th = null; // for run()-paint() thread periodicSW2D sw = null; DrawGraph2D dg2d = new DrawGraph2D(); // for event Choice ch_source, ch_mat2, ch_view; Button bt_reset, bt_startStop, bt_step; Scrollbar sc_freq, sc_mag; // for off-paint buffer Dimension dim; Image imgOff; Graphics gOff; int dgX, dgY, dgXb,dgYb; // mouse int sleepTime = 50; int dispMode = 1; int thCount = 0; // ------------------------------ applet main thread ----------- public void init() { resize(630,460); setBackground(Color.white); dim = getSize(); imgOff = createImage(dim.width,dim.height); gOff = imgOff.getGraphics(); bt_reset= new Button("reset"); bt_reset.addActionListener(this); bt_startStop= new Button("start/stop"); bt_startStop.addActionListener(this); bt_step = new Button("step"); bt_step.addActionListener(this); addMouseListener(this); addMouseMotionListener(this); sc_freq= new Scrollbar(Scrollbar.HORIZONTAL,50,10,20,110); sc_freq.addAdjustmentListener(this); sc_mag= new Scrollbar(Scrollbar.HORIZONTAL,100,10,10,510); sc_mag.addAdjustmentListener(this); ch_source = new Choice(); ch_source.add("point"); ch_source.add("plane"); ch_source.addItemListener(this); ch_source.select("plane"); ch_mat2 = new Choice(); ch_mat2.add("water"); ch_mat2.add("polystyrene"); ch_mat2.add("glass"); ch_mat2.add("iron"); ch_mat2.addItemListener(this); ch_mat2.select("glass"); ch_view = new Choice(); ch_view.add("P grid"); ch_view.add("P density"); ch_view.add("vx-vy"); ch_view.add("vx-vy & P"); ch_view.addItemListener(this); ch_view.select("P density"); setLayout(new BorderLayout()); Panel pnl = new Panel(); pnl.setLayout(new GridLayout(2,6,5,0)); //pnl.add(new Label(" ")); pnl.add(bt_reset); pnl.add(bt_startStop); pnl.add(bt_step); pnl.add(new Label("sound in water")); pnl.add(new Label(" ")); pnl.add(new Label(" ")); pnl.add(ch_source); pnl.add(sc_freq); pnl.add(ch_mat2); pnl.add(new Label(" ")); pnl.add(sc_mag); pnl.add(ch_view); add(pnl,"North"); } public void start() { if (sw == null) { sw = new periodicSW2D(); sw.start(); } if (th == null) { th = new Thread(this); th.start(); } } public void stop() { if (th != null) th = null; if (sw != null) sw = null; } // ---------------------------------- event listener ----------- public void itemStateChanged(ItemEvent ev){ if (ev.getSource() == ch_source){ sw.setSourceMode( ch_source.getSelectedIndex() ); } else if (ev.getSource() == ch_mat2){ sw.setMAT2( 1 + ch_mat2.getSelectedIndex() ); } else if (ev.getSource() == ch_view){ dispMode = ch_view.getSelectedIndex(); } } public void actionPerformed(ActionEvent ev){ if(ev.getSource() == bt_reset){ sw.reset(); thCount = 0; } else if (ev.getSource() == bt_startStop){ if (sw.getStartSW()==0) { sw.setStartSW(1); } else { sw.setStartSW(0); } } else if (ev.getSource() == bt_step){ if (sw.getStartSW()==0) { sw.setStepSW(); } } } public void adjustmentValueChanged(AdjustmentEvent ev){ if (ev.getSource() == sc_freq) { sw.setFrequency( 100.0*(double)sc_freq.getValue() ); } else if(ev.getSource() == sc_mag) { dg2d.setMag( 0.01*(double)(sc_mag.getValue()) ); } } public void mousePressed(MouseEvent ev){ } public void mouseReleased(MouseEvent ev){ dgXb = 0; dgYb = 0; dgX = 0; dgY = 0; } public void mouseClicked(MouseEvent ev){ } public void mouseEntered(MouseEvent ev){ } public void mouseExited (MouseEvent ev){ } public void mouseMoved (MouseEvent ev){ } public void mouseDragged(MouseEvent ev){ dgXb = dgX; dgYb = dgY; dgX=ev.getX(); dgY=ev.getY(); if (dgXb==0 && dgYb==0) { dgXb = dgX; dgYb = dgY; } dg2d.setViewDelta( (dgX-dgXb), (dgY-dgYb) ); } // ========================= run() - paint() loop ============== public void run() { while (th != null) { try { Thread.sleep(sleepTime); } catch (InterruptedException e) { } thCount += 1; offPaint(); repaint(); } } public void update(Graphics g) { paint(g); } public void paint(Graphics g) { g.drawImage(imgOff,0,0,this); } public void offPaint() { if (sw != null) { dg2d.plotGraph2D(gOff, sw, dispMode, thCount); } } } // =============================== draw graph 2D class =========== class DrawGraph2D { private Graphics gOff; private periodicSW2D sim; private int NNx; private int NNy; private double dx; private double magn = 1.0; double viewTheta = -15.0*3.14/180.0; double viewFai = -60.0*3.14/180.0; //-72.0*3.14/180.0; private double cosTh = Math.cos(viewTheta); private double sinTh = Math.sin(viewTheta); private double cosFi = Math.cos(viewFai); private double sinFi = Math.sin(viewFai); private int xpts[] = new int[2000]; private int ypts[] = new int[2000]; private int micNN = 500; private double mic[][] = new double[micNN][4]; private int micp = 0; private int micx[] = { 0, 160, 480, 480 }; private int micy[] = { 0, 320, 320, 480 }; private float micColor[] = { 0, 0.01f, 0.30f, 0.60f }; private int mikeSW = 1; private int drawnCount = 0; // ------------------------------- class constructor ----------- DrawGraph2D() { } // ----------------------------------- class methods ----------- public void plotGraph2D(Graphics gg, periodicSW2D sw, int dispMode, int thCount) { int simCount,gb; gOff = gg; sim = sw; if (sim==null) return; simCount = sim.getCount(); if (simCount==drawnCount) return; drawnCount = simCount; NNx = sim.getNNx(); NNy = sim.getNNy(); dx = sim.getdx(); microphone(); gOff.setColor(Color.white); gOff.fillRect(0,0,630,460); if (dispMode==0) { // sound Pressure gridPlot((NNx/10.0)*magn,NNx/40); } else if (dispMode==1) { // sound Pressure density densityPlot((NNx/20.0)*magn, 1, NNx/160); } else if (dispMode==2) { // vx-vy field densityPlot((NNx/20.0)*magn, 2, NNx/160); } else if (dispMode==3) { // sound Pressure + vx-vy densityPlot((NNx/20.0)*magn, 3, NNx/160); } else if (dispMode==4) { ; } gOff.setColor(Color.black); gOff.drawString("source",630/6*0+20,70); gOff.drawString("freq="+(int)(sim.getFrequency()+0.5)+" ",630/6*1+10,70); gOff.drawString("object",630/6*2+20,70); gOff.drawString("mag="+(int)(magn*100.0+0.5)+"%",630/6*4+10,70); gOff.drawString("view",630/6*5+10,70); gOff.drawString("grid = "+(int)(NNx*dx*100+0.5)/100.0+" x "+(int)(NNy*dx*100+0.5)/100.0+" (m)",400,100); gOff.drawString("t="+(int)(sim.getTime()*100000.0+0.5)/100.0+" ms",400,120); gOff.drawString("scattering object = "+sim.getMAT2String()+"",400,140); gOff.drawString("density = "+sim.getMAT2Density()+"kg/m3",400,160); gOff.drawString("sound velocity = "+sim.getMAT2Velocity()+"m/s",400,180); gOff.setColor(Color.black); gOff.drawString("thread SW2D = "+sim.getCount()+" ",20,440); gOff.drawString("thread disp = "+thCount+" ",220,440); } // ------------------------------------ plot methods ----------- private void gridPlot(double mag, int inc) { int cx,cy,cz; int i,j,gbx,gby,ic; double sc,z,px,py,pz; cx = NNx/2; cy = NNy/2; cz = 0; sc = 1.5*(320.0/NNx); ic = 2; gbx = 60; gby = 20; for(j=0; j1.0) { gOff.setColor(Color.getHSBColor(colorOf(i,j),0.9f,0.5f)); } else { gOff.setColor(Color.getHSBColor(colorOf(i,j),0.9f,0.9f)); } gOff.drawLine(xpts[i],ypts[i],xpts[i+ic],ypts[i+ic]); } } for(i=0; i1.0) { gOff.setColor(Color.getHSBColor(colorOf(i,j),0.9f,0.5f)); } else { gOff.setColor(Color.getHSBColor(colorOf(i,j),0.9f,0.9f)); } gOff.drawLine(xpts[j],ypts[j],xpts[j+ic],ypts[j+ic]); } } } private void densityPlot(double mag, int mode,int inc) { int i,j,gx,gy,ix,iy,ir,ch; double cs,cb,sc,vx,vy; gx = 30; gy = 100; sc = 1.0*(320.0/NNx); ir = (int)(sc*inc+0.99999); for(i=0+inc/2; i0.999) cb = 0.999; if (cb<0.0) cb = 0.0; if (mode==1 || mode==3) { gOff.setColor(Color.getHSBColor( colorOf(i,j), 0.8f, (float)cb )); } else if (mode==2) { gOff.setColor(Color.getHSBColor( colorOf(i,j), 0.3f, 0.9f )); } ix = (int)(gx+sc*i); iy = (int)(gy+sc*j); gOff.fillRect(ix,iy,ir,ir); } } if (mikeSW==1) { for (ch=1; ch<4; ch++) { gOff.setColor(Color.getHSBColor( micColor[ch], 0.8f, 0.8f )); ix = (int)(gx+sc*micx[ch]); iy = (int)(gy+sc*micy[ch]); gOff.fillRect(ix-2,iy-2,4,4); } } if (mode==2 || mode==3) { for(i=0+inc; i0) { gOff.setColor(Color.red); } else { gOff.setColor(Color.blue); } ix = (int)(gx+sc*(i+inc)); iy = (int)(gy+sc*(j+inc)); gOff.drawLine(ix,iy,ix+(int)(mag*2000000.0*vx),iy+(int)(mag*2000000.0*vy) ); } } } if (mikeSW==1) { plotMicrophone(200.0*magn); } } private float colorOf(int i, int j) { float c; c = (float)(0.5-0.00012*(sim.getSoundVelocity(i,j)-1500.0)); if (sim.getAttenuation(i,j)>1.0) c = c + 0.1f; return c; } // private void microphone() { if (sim.getStartSW()==1) { micp = (micp+1)%micNN; mic[micp][0] = sim.getTime(); mic[micp][1] = sim.getSoundPressure(micx[1],micy[1]); mic[micp][2] = sim.getSoundPressure(micx[2],micy[2]); mic[micp][3] = sim.getSoundPressure(micx[3],micy[3]); } } private void plotMicrophone(double mag) { int n,ch,i,ip1,ip2,gx1,gy1,gx2,gy2; gOff.setColor(Color.black); gOff.drawString("microphone (250us/div)",420,230); gOff.setColor(Color.lightGray); for (i=0; i<=200; i+=50) { gOff.drawLine(400+i,240,400+i,440); } for (i=0; i<=200; i+=50) { gOff.drawLine(400,240+i,600,240+i); } for (ch=1; ch<4; ch++) { gOff.setColor(Color.getHSBColor( micColor[ch], 0.8f, 0.6f )); for (i=1; i600) continue; gOff.drawLine(gx1,gy1,gx2,gy2); } } } // ------------------------------------- I/O methods ----------- public void setViewDelta(double xDisplacement, double yDisplacement) { viewTheta += 0.5*3.14159/180.0*xDisplacement; viewFai += 0.5*3.14159/180.0*yDisplacement; cosTh = Math.cos(viewTheta); sinTh = Math.sin(viewTheta); cosFi = Math.cos(viewFai); sinFi = Math.sin(viewFai); } public void setMag(double mg) { magn = mg; } public double getMag() { return magn; } } // ============================ periodic sound wave 2D =========== class periodicSW2D extends Thread { private float t = 0.0f; private float dt = 1.0e-6f; private float dx = 1.0e-2f; private int NNx = 640; private int NNy = 640; private byte kind[][] = new byte[NNx][NNy]; private float fai[][][] = new float[3][NNx][NNy]; // v-potential private int pbf=0; private int ppr=1; private int pnx=2; private float frequency = 5000.0f; //Hz private float omega = (float)(2.0*Math.PI*frequency); private int sourceMode = 1; // 0-point 1-plane source private float material[][] = { // c(m/s), rho(kg/m3), alpha(atenuation) { 340.0f, 1.2f, 0.0001f }, // 0 air { 1500.0f, 1000.0f, 0.01f }, // 1 water { 2350.0f, 1056.0f, 0.01f }, // 2 polystyrene { 5100.0f, 2400.0f, 0.01f }, // 3 glass { 5950.0f, 7860.0f, 0.01f }, // 4 iron { 1500.0f, 1000.0f, 10000.0f }, // 5 absorber1 { 1500.0f, 1000.0f, 30000.0f }, // 6 absorber2 { 1500.0f, 1000.0f, 100000.0f } // 7 absorber3 }; private String materialString[] = { "air", "water", "polystyrene", "glass", "iron" }; private int MAT1 = 1; // water private int MAT2 = 3; // scattering object private int resetSW = 0; private int startSW = 1; private int stepSW = 1; private int sleepTime = 1; private int stopSleepTime = 100; private int count = 0; // ------------------------------- class constructor ----------- periodicSW2D() { setInitialCondition(); } // -------------------------------------- thread run ----------- public void run() { while (true) { count += 1; timeEvolution(); if (sleepTime>0) { try { Thread.sleep(sleepTime); } catch (InterruptedException e) { } } } } // --------------------------- set initial condition ----------- private void setInitialCondition() { int i,j; t = 0.0f; count = 0; int pbf=0; int ppr=1; int pnx=2; for (i=0; iNNx-32) { kind[i][j] = 5; if ( i<16 || i>NNx-16) { kind[i][j] = 6; if ( i<8 || i>NNx-8) { kind[i][j] = 7; } } } if ((i-NNx/2)*(i-NNx/2)+(j-NNy/2)*(j-NNy/2)2.0/frequency) return; if (sMode==0) { // point source ix = 3*NNx/16; iy = 3*NNy/16; fai[pnx][ix][iy] += (float)(0.01*Math.sin(w*tt)*dt); } else if (sMode==1) { // plane wave ix = 50; for (iy=0; iy { f(k+1) + f(k-1) -2f(k) }/dt^2 * d^2(fai)/dr^2 -> * { f(i+1) + f(i-1) -2f(i) }/dx^2 + { f(j+1) + f(j-1) -2f(j) }/dx^2 * */