/** * @version 1.20 27 Jun 1998 * @author Cay Horstmann */ /* Koide Calc Modified by Carl Brannen to give base X and scientific capabilities. */ import java.awt.BorderLayout; import java.awt.Container; import java.awt.Button; import java.awt.GridLayout; import java.awt.GridBagLayout; import java.awt.GridBagConstraints; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.TextArea; import java.awt.Font; import java.awt.Color; import java.awt.Panel; import javax.swing.JApplet; import javax.swing.JButton; import javax.swing.JCheckBox; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.JTextField; //import javax.swing.JTextArea; public class Koide_top extends JApplet { public void init() { CalculatorPanel CalcPanel = new CalculatorPanel(); Container contentPane = getContentPane(); contentPane.add(CalcPanel); } } class CalculatorPanel extends Panel implements ActionListener { public CalculatorPanel() { // Basic mass quantum number calculation. // // \lambda_{n,m} = 1 + \sqrt(2)\cos(2n\pi/3 + 2/9 + m\pi/12) // double sqrt2 = Math.sqrt(2.0); double PiOv12 = Math.PI/12.0; double Pi2ov3 = Math.PI/1.5; double delta = 2.0/9.0; for (int N=0; N<3; N++) for (int M=0; M<8; M++) { double angle = N*Pi2ov3 + delta + M*PiOv12; double lambda = 1.0 + sqrt2 * Math.cos(angle); System.out.println("2/9, N="+N+" M="+M+" lambda = "+lambda); } System.out.println(); delta = 0.22222204717; for (int N=0; N<3; N++) for (int M=0; M<8; M++) { double angle = N*Pi2ov3 + delta + M*PiOv12; double lambda = 1.0 + sqrt2 * Math.cos(angle); System.out.println("TDN, N="+N+" M="+M+" lambda = "+lambda); } // Gridbaglayout: // 0 1 2 3 4 5 6 7 8 9 10 11 // -------- ------- ------- ------- // Min Best Max Del | 0 // 6 6 6 6 | 1 // 5 5 5 5 | 2 // 4 4 4 4 | 3 // 3 3 3 3 | 4 // 2 2 2 2 | 5 // 1 1 1 1 | 6 // KOIDE PERM:123 P+K xx | 7 // ++++++++++ Display +++++++++++ | 8 // ++++++++++ Display +++++++++++ | 9 // ++++++++++ Display +++++++++++ | 10 // ++++++++++ Display +++++++++++ | 11 GridBagLayout gridbag = new GridBagLayout(); GridBagConstraints c = new GridBagConstraints(); setLayout(gridbag); c.fill = GridBagConstraints.BOTH; // Labels at line 0 c.weighty = 0.0; c.weightx = 1.0; c.gridy = 0; c.gridwidth = 3; String[] TopLabels = {"Min", "Best", "Max", "Error"}; for (int I=0; I<4; I++) { c.gridx = 3*I; LabelTop[I] = new JLabel(TopLabels[I]); gridbag.setConstraints(LabelTop[I],c); add(LabelTop[I]); } // Mass input regions for (int I=0; I<6; I++) { c.gridy = I+1; c.gridx = 0; MassMin[I] = new JTextField("0"); gridbag.setConstraints(MassMin[I],c); add(MassMin[I]); c.gridx = 3; MassBst[I] = new JTextField("0"); gridbag.setConstraints(MassBst[I],c); add(MassBst[I]); c.gridx = 6; MassMax[I] = new JTextField("0"); gridbag.setConstraints(MassMax[I],c); add(MassMax[I]); c.gridx = 9; MassDel[I] = new JTextField("0"); gridbag.setConstraints(MassDel[I],c); add(MassDel[I]); MassOk[I] = false; dMin[I] = 0.0; dBst[I] = 0.0; dMax[I] = 0.0; dDel[I] = 0.0; } // Koide and permutation buttons c.gridy = 7; c.gridx = 0; KoideButton = new JButton("KOIDE"); gridbag.setConstraints(KoideButton,c); add(KoideButton); KoideButton.addActionListener(this); c.gridx = 3; PermButton = new JButton("PERM"); gridbag.setConstraints(PermButton,c); add(PermButton); PermButton.addActionListener(this); c.gridx = 6; PermKButton = new JButton("PERM+KOIDE"); gridbag.setConstraints(PermKButton,c); add(PermKButton); PermKButton.addActionListener(this); // Check boxes at end c.gridx = 9; c.gridwidth = 1; VerboseBox = new JCheckBox("Verb"); gridbag.setConstraints(VerboseBox,c); add(VerboseBox); VerboseBox.addActionListener(this); // Add descriptions to empty text fields String DispStr = "This calculator computes Koide parameters for masses." + " It accepts up to six masses. Masses must be positive." + "\nMasses are described with four parameters. ''Min'' gives the" + " minimum value of the mass. ''Max'' gives the maximum.\n''Best''" + " gives the best value. If best is not provided, it will be" + " computed as the average of min and max.\n''Error'' gives the" + " difference between best and min and max. If Error and Best" + " are provided (i.e. are non zero),\nMin and Max will be computed" + " as Best - Error and Best + Error and will be so updated." + "\n\nThe Koide formula requires three input masses. Which of the" + " six masses are used is determined by the ''PERM: xxx'' button." + "\nPressing this button cycles through the (at most 20) possible" + " choices of non-zero masses." + " \n\nOn pressing ''KOIDE'' a new calculation for the Koide parameters" + " are computed and pasted to the end of this region.\nThe ''PERM+KOIDE''" + " button permutes and computes. The ''Verb'' checkbox determines how" + " verbose the Koide display is."; // Output display area c.gridx = 0; c.gridy = 8; c.weighty = 1.0; c.gridwidth = 12; OutDisplay = new TextArea(DispStr); OutDisplay.setEditable(true); OutDisplay.setFont(Font.getFont("Monospaced")); c.fill = GridBagConstraints.BOTH; gridbag.setConstraints(OutDisplay,c); add(OutDisplay); // Other initializations: PermButton.setText("PERM: 123"); Verbose = true; VerboseBox.setSelected(true); // Initialize to charged lepton numbers MassBst[0].setText("0.510998918"); MassDel[0].setText("0.000000044"); MassBst[1].setText("105.6583692"); MassDel[1].setText("0.000000094"); MassBst[2].setText("1776.99"); MassMin[2].setText("1776.73"); MassMax[2].setText("1777.28"); } public boolean DoPerm() { boolean EndPerm = false; PermChoice[2]++; if (PermChoice[2] > 6) { PermChoice[1]++; PermChoice[2] = PermChoice[1]+1; } if (PermChoice[1] > 5) { PermChoice[0]++; PermChoice[1] = PermChoice[0]+1; PermChoice[2] = PermChoice[1]+1; } if (PermChoice[0] > 4) { EndPerm = true; PermChoice[0] = 1; PermChoice[1] = PermChoice[0]+1; PermChoice[2] = PermChoice[1]+1; } return EndPerm; } public double[] KoideParams(double M1, double M2, double M3) { double CalcVals[] = new double[4]; CalcVals[0] = M1; CalcVals[1] = M2; CalcVals[2] = M3; CalcVals[3] = 0.0; double muv = (Math.sqrt(M1) + Math.sqrt(M2) + Math.sqrt(M3))/3.0; double sum2 = (M1 + M2 + M3)/3.0; double mus = Math.sqrt((sum2-muv*muv)*2.0); double del = 100000.0; for (int I=0; I<3; I++) { double delta = Math.acos((Math.sqrt(CalcVals[I]) - muv)/mus); if (delta < del) del = delta; } // Check to see if calc is correct. double CalcMass[] = new double[3]; for (int I=0; I<3; I++) { CalcMass[I] = muv + mus * Math.cos(del + I*Math.PI/1.5); CalcMass[I] = CalcMass[I]*CalcMass[I]; } double ErrorSum = 0.0; for (int I=0; I<3; I++) { double Error = (CalcVals[0] - CalcMass[I]) *(CalcVals[1] - CalcMass[I]) * (CalcVals[2] - CalcMass[I]); ErrorSum += Error*Error; } // CheckVal has units of M^6 so take 6th root and normalize: ErrorSum = Math.pow(ErrorSum,0.166666666) / (M1 + M2 + M3); if (ErrorSum > 1.0e-5) System.out.println(" Error Check: "+ErrorSum); else System.out.print("."); CalcVals[0] = muv; CalcVals[1] = mus; CalcVals[2] = mus*mus/(muv*muv); CalcVals[3] = Math.toDegrees(del); return CalcVals; } public void actionPerformed(ActionEvent evt) { // Click control eliminates double clicks from my busted mouse. // Times are in milliseconds, so this removes keyboard bounce of 200ms // or less. long ThisClick = evt.getWhen(); if (ThisClick - LastClick < 200) { LastClick = ThisClick; return; } Verbose = VerboseBox.isSelected(); LastClick = ThisClick; // Update the mass information. // We need to have dMin < dBest < dMax. for (int I=0; I<6; I++) { try { dMin[I] = Double.parseDouble(MassMin[I].getText());} catch (NumberFormatException e) {dMin[I] = 0.0;} try { dBst[I] = Double.parseDouble(MassBst[I].getText());} catch (NumberFormatException e) {dBst[I] = 0.0;} try { dMax[I] = Double.parseDouble(MassMax[I].getText());} catch (NumberFormatException e) {dMax[I] = 0.0;} try { dDel[I] = Double.parseDouble(MassDel[I].getText());} catch (NumberFormatException e) {dDel[I] = 0.0;} MassMin[I].setText(""+dMin[I]); MassBst[I].setText(""+dBst[I]); MassMax[I].setText(""+dMax[I]); MassDel[I].setText(""+dDel[I]); boolean MinOk = dMin[I] > 0.0; boolean BstOk = dBst[I] > 0.0; boolean MaxOk = dMax[I] > 0.0; boolean DelOk = dDel[I] > 0.0; // Cases: // M // 0000 f // 0001 f // 0010 f // 0011 f // 0100 T Max = Bst, Min = Bst // 0101 T Max = Bst+Del, Min = Bst-Del // 0110 T Min = Bst, // 0111 T Max = Bst+Del, Min = Bst-Del // 1000 f // 1001 f // 1010 T Bst = Max + Min / 2 // 1011 T Bst = Max + Min / 2, Min = Bst-Del, Max = Bst+Del // 1100 T Max = Bst // 1101 T Max = Bst+Del, Min = Bst-Del // 1110 T // 1111 T Max = Bst+Del, Min = Bst-Del if (MinOk && (!BstOk) && MaxOk ) dBst[I] = (dMin[I] + dMax[I])/2.0; if ((BstOk && DelOk) || (MinOk && MaxOk && DelOk)) { dMax[I] = dBst[I] + dDel[I]; dMin[I] = dBst[I] - dDel[I]; } if (BstOk && (! MaxOk) && (! DelOk)) dMax[I] = dBst[I]; if (BstOk && (! MinOk) && (! DelOk)) dMin[I] = dBst[I]; MassOk[I+1] = BstOk || (MinOk && MaxOk); // We will always use dDel if it exists, so now good numbers // are in dMin and dMax. if (dDel[I] > 0.0) { dMin[I] = dBst[I] - dDel[I]; dMax[I] = dBst[I] + dDel[I]; } } String s = evt.getActionCommand(); boolean ExecKoide = s.startsWith("KOIDE") || s.startsWith("PERM+KOIDE"); boolean ExecPerm = s.startsWith("PERM"); // Change Permval to next values with easy algorithm. boolean BadMasses = true; boolean Running = true; boolean EndPerm = false; boolean OldEnd = false; if (ExecPerm) { do { EndPerm = DoPerm(); if (MassOk[PermChoice[0]] && MassOk[PermChoice[1]] && MassOk[PermChoice[2]]) { BadMasses = false; Running = false; } else if (EndPerm) { Running = ! OldEnd; OldEnd = true; } } while (Running); if (BadMasses) { PermChoice[0] = 1; PermChoice[1] = 2; PermChoice[2] = 3; } String PermStr = "PERM: "+PermChoice[0]+PermChoice[1]+PermChoice[2]; PermButton.setText(PermStr); } boolean OkMasses = MassOk[PermChoice[0]] && MassOk[PermChoice[1]] && MassOk[PermChoice[2]]; // Print to display if (ExecKoide) { // Verbose tells whether to give the full nine yards. String OutText = OutDisplay.getText(); if (OkMasses) { // Get masses double MC[][] = new double[3][3]; for (int I=0; I<3; I++) { MC[I][0] = dMin[PermChoice[I]-1]; MC[I][1] = dBst[PermChoice[I]-1]; MC[I][2] = dMax[PermChoice[I]-1]; } // Compute mins and maxes double[] MuVal = new double[3]; double[] MuSea = new double[3]; double[] Delta = new double[3]; double[] EtaSq = new double[3]; // Compute the best cases double[] KR = new double[4]; KR = KoideParams(MC[0][1],MC[1][1],MC[2][1]); // Put best case into min best and max for (int I=0; I<3; I++) { MuVal[I] = KR[0]; MuSea[I] = KR[1]; EtaSq[I] = KR[2]; Delta[I] = KR[3]; } // Compute all possible min max combos. for (int I=0; I<3; I+=2) for (int J=0; J<3; J+=2) for (int K=0; K<3; K+=2) { KR = KoideParams(MC[0][I],MC[1][J],MC[2][K]); if (KR[0] < MuVal[0]) MuVal[0] = KR[0]; if (KR[0] > MuVal[2]) MuVal[2] = KR[0]; if (KR[1] < MuSea[0]) MuSea[0] = KR[1]; if (KR[1] > MuSea[2]) MuSea[2] = KR[1]; if (KR[2] < EtaSq[0]) EtaSq[0] = KR[2]; if (KR[2] > EtaSq[2]) EtaSq[2] = KR[2]; if (KR[3] < Delta[0]) Delta[0] = KR[3]; if (KR[3] > Delta[2]) Delta[2] = KR[3]; } // Write out results OutText = OutText + "\n"+PermChoice[0]+PermChoice[1]+PermChoice[2]+" "; if (Verbose) { for (int I=0; I<3; I++) { int N = I+1; OutText = OutText + "Mass#" + N + " = " + MC[I][0] + " " + MC[I][1] + " " + MC[I][2]; if (I < 2) OutText = OutText + " , "; } OutText = OutText + "\nMuV, MuS, Eta2, Delta ="; OutText = OutText +"\n Min = "+MuVal[0]+" "+MuSea[0]+" "+EtaSq[0]+" "+Delta[0] +"\n Best = "+MuVal[1]+" "+MuSea[1]+" "+EtaSq[1]+" "+Delta[1] +"\n Max = "+MuVal[2]+" "+MuSea[2]+" "+EtaSq[2]+" "+Delta[2]+"\n"; } else { OutText = OutText + "Masses = "+MC[0][1]+" "+MC[1][1]+" "+MC[2][1]; OutText = OutText + " MuV, MuS, Delta = "+MuVal[1]+" "+MuSea[1]+" "+Delta[1]; } } else OutText = OutText + "\n Error: Need 3 good mass choices."; OutDisplay.setText(OutText); } // double muv = (Math.sqrt(DV[3]) + Math.sqrt(DV[2]) + Math.sqrt(DV[1]))/3.0; // double sum2 = (DV[3] + DV[2] + DV[1])/3.0; // double mus = Math.sqrt((sum2-muv*muv)*2.0); // double del = 100000.0; // for (int I=1; I<4; I++) { // double delta = Math.acos((Math.sqrt(DV[I]) - muv)/mus); // if (delta < del) del = delta; // } } private JLabel[] LabelTop = new JLabel[4]; private JTextField[] MassMin = new JTextField[6]; private JTextField[] MassBst = new JTextField[6]; private JTextField[] MassMax = new JTextField[6]; private JTextField[] MassDel = new JTextField[6]; private double[] dMin = new double[6]; private double[] dBst = new double[6]; private double[] dMax = new double[6]; private double[] dDel = new double[6]; private JButton KoideButton; private JButton PermButton; private JButton PermKButton; private JCheckBox VerboseBox; boolean Verbose; private TextArea OutDisplay; private int[] PermChoice = {1, 2, 3}; private boolean[] MassOk = new boolean[7]; // Keep Carl's defective Gateway MX6121 notebook mouse button // from causing a double click event. These happen on button // release and are quite annoying. How could their engineers // screw up something so fundamental. And why doesn't Microsoft // have an anti-double click feature put into their accessibility // options list. Amateurs in industry! private long LastClick; }