/* * simpvai.java - revised 22 Apr 05 - width 601, height 431 * @author jackord@kw.igs.net * the algorithm optimizes the fit of P-A data at varying angle of incidence * to a model consisting of one or two layers on a known substrate * NOTE: THE ALGORITHM DOES ARITHMETIC BUT MAKES NO CLAIM ABOUT * THE SIGNIFICANCE OF THE PARAMETER VALUES IT DETERMINES */ import java.awt.*; import java.awt.event.ActionListener; import java.awt.event.ActionEvent; public class simpvai extends java.applet.Applet implements ActionListener { int x1, y1, x2, y2, xorg, yorg; // Declarations int kk=0; int np=0; int ndata=0; int w=0; String b1s="Data1"; Button b1=new Button(b1s); String b2s="Data2"; Button b2=new Button(b2s); String b3s="Tplot"; Button b3=new Button(b3s); String b4s="Smplx"; Button b4=new Button(b4s); String b5s="Print"; Button b5=new Button(b5s); String zz; Checkbox ch1=new Checkbox("Nin"); Checkbox ch2=new Checkbox("Kin"); Checkbox ch3=new Checkbox("Lin"); Checkbox ch4=new Checkbox("Nout"); Checkbox ch5=new Checkbox("Kout"); Checkbox ch6=new Checkbox("Lout"); TextField tx[]=new TextField[7]; double[] db=new double[13]; double[][] q=new double[11][8]; double[][] da=new double[20][4]; double lmda, pp, aa, df, namb, nsub, ksub; int nlay, nvr, nvx, test; int sn=7; int[] ip=new int[8]; public void init() { setBackground(new Color(211, 211, 211)); for (int i=1; i<=6; i=i+1) { tx[i]=new TextField(10); add(tx[i]); tx[i].setBackground(getBackground()); } add(b1); add(b2); add(b3); add(b4); add(b5); add(ch1); add(ch2); add(ch3); add(ch4); add(ch5); add(ch6); ch1.setBackground(getBackground()); ch2.setBackground(getBackground()); ch3.setBackground(getBackground()); ch4.setBackground(getBackground()); ch5.setBackground(getBackground()); ch6.setBackground(getBackground()); b1.addActionListener(this); b2.addActionListener(this); b3.addActionListener(this); b4.addActionListener(this); b5.addActionListener(this); } public void pin(Graphics g) { if (kk==0) { // Screen layout tx[1].setBounds(110, 0, 100, 20); tx[4].setBounds(270, 0, 100, 20); tx[2].setBounds(110, 30, 100, 20); tx[5].setBounds(270, 30, 100, 20); tx[3].setBounds(110, 60, 100, 20); tx[6].setBounds(270, 60, 100, 20); ch1.setBounds(60, 0, 50, 20); ch4.setBounds(220, 0, 50, 20); ch2.setBounds(60, 30, 50, 20); ch5.setBounds(220, 30, 50, 20); ch3.setBounds(60, 60, 50, 20); ch6.setBounds(220, 60, 50, 20); b1.setBounds(0, 0, 44, 20); b2.setBounds(0, 25, 44, 20); b3.setBounds(0, 50, 44, 20); b4.setBounds(0, 75, 44, 20); b5.setBounds(0, 100, 44, 20); g.setFont(new Font("TimesRoman", Font.PLAIN, 14)); xorg=80; yorg=390; g.setColor(Color.black); g.drawRect(80, 90, 500, 300); } if ((kk>0)&&(kk<4)) { for (int i=0; i<=5; i=i+1) { // Plot grid x1=80+i*100; g.drawLine(x1, 90, x1, 390); } for (int i=0; i<=3; i=i+1) { y1=90+i*100; g.drawLine(80, y1, 580, y1); } g.drawRect(380, 0, 200, 80); // Simplex strip chart for (int i=1; i<=3; i=i+1) { x1=380+50*i; g.drawLine(x1, 0, x1, 80); } g.drawString(Double.toString(db[7]), xorg-10, yorg+20); g.drawString(Double.toString(db[8]), 580-18, yorg+20); g.drawString("P deg", 310, yorg+20); g.drawString(Double.toString(db[9]), xorg-28, yorg+6); g.drawString(Double.toString(db[10]), xorg-28, 96); g.drawString("A", 50, 238); g.drawString("deg", 44, 258); for (int i=1; i<=ndata; i=i+1) { // Plot data g.setColor(Color.red); g.fillArc(xs(da[i][0])-5, ys(da[i][1])-5, 10, 10, 0, 360); g.setColor(Color.black); g.drawArc(xs(da[i][0])-5, ys(da[i][1])-5, 10, 10, 0, 360); } } } int xs(double x) { // Scale x return xorg+(int)((x-db[7])*500/(db[8]-db[7])+.5); } int ys(double y) { // Scale y return yorg-(int)((y-db[9])*300/(db[10]-db[9])+.5); } public void pst(double x, double y, Graphics g) { x1=xs(x); y1=ys(y); // Start line } public void plt(double x, double y, Graphics g) { // Draw line x2=xs(x); y2=ys(y); if (Math.abs(x2-x1)>90) { x1=x2; y1=y2; } g.drawLine(x1, y1, x2, y2); x1=x2; y1=y2; } public void tplot(Graphics g) { // P-A curve ... double t, pold; pold=0; for (int i=0; i<=np; i=i+1) { t=db[11]+i*(double)(db[12]-db[11])/np; pa(1, t); if (i==0) { pst(pp, aa, g); } else { if (Math.abs(pp-pold)>120) { pst(pp, aa, g); } else { plt(pp, aa, g); } } pold=pp; } for (int i=1; i<=ndata; i=i+1) { // ... with points at pa(1, da[i][2]); // specified angles g.setColor(Color.yellow); // of incidence g.fillArc(xs(pp)-3, ys(aa)-3, 6, 6, 0, 360); g.setColor(Color.black); g.drawArc(xs(pp)-3, ys(aa)-3, 6, 6, 0, 360); } } public void paint(Graphics g) { // Main program pin(g); if (kk==2) { // Plot curve g.setColor(Color.magenta); tplot(g); } if (kk==3) { // Simplex fit g.setColor(Color.green); tplot(g); sim(g); } if (kk==4) { // Print results int r=105; int c=90; g.setColor(Color.black); g.drawString("P deg", c, r); c=c+120; g.drawString("A deg", c, r); c=c+120; g.drawString("Theta deg", c, r); c=c+120; g.drawString("Dev deg", c, r); c=90; r=120; for (int i=1; i<=ndata; i=i+1) { for (int j=0; j<=3; j=j+1) { g.drawString(Float.toString((float)da[i][j]), c+j*120, r); } r=r+15; } g.drawString("rms dev", 390, r); g.drawString(Float.toString((float)q[1][sn]), 450, r); kk=0; } } public void sim(Graphics g) { // Simplex algorithm int ii=0; int iv=0; int jlof=0; int xflag; double dni, dnf, ave, nexp; long tt=System.currentTimeMillis(); dni=0.02; dnf=0.0000001; if (w==0) { zz="Weight Off"; } else { zz="Weight On"; } if (ch1.getState()==true) { ii=ii+1; ip[ii]=1; } if (ch2.getState()==true) { ii=ii+1; ip[ii]=2; } if (ch3.getState()==true) { ii=ii+1; ip[ii]=3; } if ((ch4.getState()==true)&&(nlay>1)) { ii=ii+1; ip[ii]=4; } if ((ch5.getState()==true)&&(nlay>1)) { ii=ii+1; ip[ii]=5; } if ((ch6.getState()==true)&&(nlay>1)) { ii=ii+1; ip[ii]=6; } nvr=ii; nvx=ii+1; ip[nvx]=sn; if (nvr==0) { df=0; fit(1); } else { for (int i=2; i<=(nvx+3); i=i+1) { for (int j=1; j<=sn-1; j=j+1) { q[i][j]=q[1][j]; } } for (int i=1; i<=nvr; i=i+1) { if ((ip[i]==3)||(ip[i]==6)) { q[i][ip[i]] = q[i][ip[i]]+1; } else { q[i][ip[i]] = q[i][ip[i]]+dni; } } for (int i=1; i<=nvx; i=i+1) { fit(i); } sort(); g.setColor(Color.red); // Plot stripchart x1=380+(int)(15*Math.log(df/dnf)); y1=1; } while (df>dnf) { x2=380+(int)(15*Math.log(df/dnf)); y2=y1+1; g.drawLine(x1, y1, x2, y2); x1=x2; y1=y2; if (y1==79) { y1=1; } xflag=0; for (int i=1; i<=nvr; i=i+1) { ave=0; for (int j=1; j<=nvr; j=j+1) { ave=ave+q[j][ip[i]]; } q[nvx+1][ip[i]]=ave/nvr; } if ((jlof==1)&&(q[nvx+2][sn]==q[nvx][sn])) { jlof=0; cns(); } else { jlof=0; iv=nvx+2; for (int i=1; i<=nvr; i=i+1) { q[iv][ip[i]]=2*q[nvx+1][ip[i]]-q[nvx][ip[i]]; } fit(iv); if (q[iv][sn]>q[nvx][sn]) { cns(); } else { if (q[iv][sn]q[i+1][sn]) { s=s+1; for (int j=1; j<=nvx; j=j+1) { temp=q[i][ip[j]]; q[i][ip[j]]=q[i+1][ip[j]]; q[i+1][ip[j]]=temp; } } } } while (s>0); for (int i=1; i<=nvr; i=i+1) { max=q[1][ip[i]]; min=max; for (int j=2; j<=nvx; j=j+1) { if (q[j][ip[i]]>max) { max=q[j][ip[i]]; } if (q[j][ip[i]]df) { df=dfi; } } } } public void cns() { // Shrink simplex int iv=nvx+2; for (int i=1; i<=nvr; i=i+1) { q[iv][ip[i]] = (q[nvx+1][ip[i]]+q[nvx][ip[i]])/2; } fit(iv); if (q[iv][sn]90) { pp=pp-180; } if ((da[j][0]-pp)>90) { pp=pp+180; } ddp=da[j][0]-pp; if (w>0) { ddp=ddp*Math.sin(aa*Math.PI/90); } dda=da[j][1]-aa; ds=ddp*ddp+dda*dda; da[j][3]=Math.sqrt(ds); fs=fs+ds; } q[i][sn]=Math.sqrt(fs/ndata); } public void pa(int iv, double theta) { // Calculate P and A double[][] c=new double[4][2]; double[][] d=new double[4][2]; double[] b=new double[2]; double[] j=new double[4]; double[] k=new double[4]; double[] m=new double[4]; double[] h=new double[4]; double[] r=new double[4]; double[] s=new double[4]; double[] u=new double[2]; double[] v=new double[2]; double[] e=new double[4]; double[] f=new double[4]; double t, bb, e2, e3, e4, e5, e6, e7, e8, e9; double f1, f2, f3, f4, f5, f6, f7; double g1, g2, g3, g4, g5, g6, g7, g8; j[0]=nsub; k[0]=ksub; for (int i=1; i<=nlay; i=i+1) { j[i]=q[iv][3*i-2]; k[i]=q[iv][3*i-1]; } t=theta*Math.PI/180; bb=namb*Math.sin(t); bb=bb*bb; b[0]= namb*Math.cos(t); b[1]=b[0]/namb/namb; for (int i=0; i<=nlay; i=i+1) { e2=j[i]*j[i]; e3=k[i]*k[i]; e4=e2-e3-bb; e5=Math.sqrt(e4*e4+4*e2*e3); e6=1/(e2+e3)/(e2+e3); c[i][0]=Math.sqrt((e4+e5)/2); d[i][0]=-j[i]*k[i]/c[i][0]; c[i][1]=e6*(c[i][0]*(e2-e3)-2*d[i][0]*k[i]*j[i]); d[i][1]=e6*(d[i][0]*(e2-e3)+2*c[i][0]*k[i]*j[i]); } for (int i=0; i<=1; i=i+1) { for (int il=1; il<=nlay; il=il+1) { f1=q[iv][3*il]*2*Math.PI/lmda; f2=f1*c[il][0]; f3=f1*d[il][0]; f4=Math.sin(f2); f5=Math.cos(f2); f6=Math.exp(f3)/2; f7=Math.exp(-f3)/2; e7=f5*(f7-f6); e8=f4*(f6+f7); if (il>1) { for (int is=0; is<=3; is=is+1) { m[is]=e[is]; h[is]=f[is]; } } e[0]=f5*(f6+f7); f[0]=f4*(f7-f6); f[2]=-e7*c[il][i]+e8*d[il][i]; e[2]=e7*d[il][i]+e8*c[il][i]; e9=c[il][i]*c[il][i]+d[il][i]*d[il][i]; f[1]=(e7*c[il][i]+e8*d[il][i])/e9; e[1]=(-e8*c[il][i]+e7*d[il][i])/e9; e[3]=e[0]; f[3]=f[0]; if (il>1) { for (int im=0; im<=1; im=im+1) { for (int in=0; in<=2; in=in+2) { r[im+in]=e[in]*m[im]-f[in]*h[im]+e[in+1]*m[im+2]-f[in+1]*h[im+2]; s[im+in]=f[in]*m[im]+e[in]*h[im]+e[in+1]*h[im+2]+f[in+1]*m[im+2]; } } for (int is=0; is<=3; is=is+1) { e[is]=r[is]; f[is]=s[is]; } } } g1=(e[0]+f[1]*c[0][i]+e[1]*d[0][i])*b[i]; g2=(f[0]+f[1]*d[0][i]-e[1]*c[0][i])*b[i]; g3=-f[2]+e[3]*c[0][i]-f[3]*d[0][i]; g4=e[2]+e[3]*d[0][i]+f[3]*c[0][i]; g5=(g1+g3)*(g1+g3)+(g2+g4)*(g2+g4); u[i]=(g1*g1+g2*g2-g3*g3-g4*g4)/g5; v[i]=2*(g2*g3-g1*g4)/g5; } g6=u[0]*u[0]+v[0]*v[0]; g7=(u[0]*u[1]+v[0]*v[1])/g6; g8=(u[0]*v[1]-u[1]*v[0])/g6; aa=Math.atan(Math.sqrt(g7*g7+g8*g8))*180/Math.PI; pp=Math.atan2(g8,g7)*90/Math.PI-45; if (pp0)&&(kk<4)) { getnums(); if (test==0) { kk=2; repaint(); } } } if (b4s.equals(tst)) { // Simplex fit if ((kk>0)&&(kk<4)) { getnums(); if (test==0) { kk=3; repaint(); } } } if (b5s.equals(tst)) { // Print results if (kk==3) { kk=4; repaint(); } } } }