From: <ha...@us...> - 2008-03-25 22:34:02
|
Revision: 9200 http://jmol.svn.sourceforge.net/jmol/?rev=9200&view=rev Author: hansonr Date: 2008-03-25 15:33:58 -0700 (Tue, 25 Mar 2008) Log Message: ----------- version=11.5.21_dev # new feature: minimize command with thread # # minimizationSteps = 10 # for now # minimizationRefresh = false # for now # set loglevel 5 # for a minimal report # set loglevel 6 # for a detailed report # select * # minimize # minimize stop # minimize cancel # Modified Paths: -------------- branches/bob-minimize/Jmol/src/org/jmol/minimize/Minimizer.java branches/bob-minimize/Jmol/src/org/jmol/minimize/forcefield/CalculationsUFF.java branches/bob-minimize/Jmol/src/org/jmol/minimize/forcefield/ForceField.java branches/bob-minimize/Jmol/src/org/jmol/minimize/forcefield/ForceFieldUFF.java Modified: branches/bob-minimize/Jmol/src/org/jmol/minimize/Minimizer.java =================================================================== --- branches/bob-minimize/Jmol/src/org/jmol/minimize/Minimizer.java 2008-03-25 21:12:28 UTC (rev 9199) +++ branches/bob-minimize/Jmol/src/org/jmol/minimize/Minimizer.java 2008-03-25 22:33:58 UTC (rev 9200) @@ -52,26 +52,69 @@ int[][] torsions; double[] partialCharges; - int steps = 1000; - double crit = 1e-6; + int steps = 50; + double crit = 1e-3; boolean sd = true; Viewer viewer; - BitSet bsFixed; ForceField pFF; String ff = "UFF"; - + BitSet bsTaint; + public Minimizer() { } + public void setProperty(String propertyName, Object value) { + if (propertyName.equals("clear")) { + clear(); + return; + } + if (propertyName.equals("cancel")) { + stopMinimization(false); + return; + } + if (propertyName.equals("steps")) { + steps = ((Integer)(value)).intValue(); + return; + } + if (propertyName.equals("criterion")) { + crit = ((Float)(value)).floatValue(); + return; + } + if (propertyName.equals("stop")) { + stopMinimization(true); + return; + } + } + + private void clear() { + setMinimizationOn(false); + atomCount = 0; + bondCount = 0; + atoms = null; + if (viewer != null) + viewer.setMinimizer(null); + viewer = null; + minAtoms = null; + minBonds = null; + angles = null; + torsions = null; + partialCharges = null; + coordSaved = null; + bsTaint = null; + pFF = null; + } + public boolean minimize(Viewer viewer, BitSet bsSelected, BitSet bsFixed, BitSet bsIgnore) { + clear(); this.viewer = viewer; + viewer.setMinimizer(this); Object val = viewer.getParameter("minimizationSteps"); if (val != null && val instanceof Integer) steps = ((Integer) val).intValue(); - Logger.info("minimize: initializing..."); + Logger.info("minimize: initializing (" + steps + " steps) ..."); int atomCountFull = viewer.getAtomCount(); atoms = viewer.getModelSet().getAtoms(); @@ -85,7 +128,6 @@ bsMinFixed.set(pt); pt++; } - this.bsFixed = bsMinFixed; } // add all atoms @@ -189,8 +231,10 @@ else for (int j = 0, pt = 0; j < atomCountFull; j++) if (bsAtoms.get(j)) { - if (search.get(j)) + if (search.get(j)) { minAtoms[pt].type = data[1]; + System.out.println("pt" +pt + data[1]); + } pt++; } } @@ -210,26 +254,24 @@ pFF.setModel(viewer, minAtoms, minBonds, angles, torsions, partialCharges); - if (!pFF.setup()) + if (!pFF.setup()) { Logger.error(GT._("could not setup force field {0}", ff)); - - // minimize and store values - - Object result = minimizeOrReturnError(); - if (result != null) { - System.out.println("error in calc " + result); return false; } - // taint the affected atom coordinates. - - BitSet bsTaint = BitSetUtil.copy(bsAtoms); + bsTaint = BitSetUtil.copy(bsAtoms); if (bsFixed != null) BitSetUtil.andNot(bsTaint, bsFixed); - viewer.setTaintedAtoms(bsTaint, AtomCollection.TAINT_COORD); + + // minimize and store values + + setMinimizationOn(true); return true; } + + //////////////// atom type support ////////////////// + final static int TOKEN_ELEMENT_ONLY = 0; final static int TOKEN_ELEMENT_CHARGED = 1; final static int TOKEN_ELEMENT_CONNECTED = 2; @@ -485,6 +527,7 @@ System.out.println(e.getMessage()); } } + System.out.println(" forcefield = " + pFF); return pFF; } @@ -493,31 +536,87 @@ return (pFF == null ? null : pFF.getAtomTypes()); } - public String minimizeOrReturnError() { - pFF.steepestDescentInitialize(steps, crit); - boolean going = true; - viewer.setBooleanProperty("minimizationStop", false); - while (going && !viewer.getBooleanProperty("minimizationStop")) { - going = pFF.steepestDescentTakeNSteps(1); - boolean doRefresh = viewer.getBooleanProperty("minimizationRefresh"); - if (doRefresh) { - updateAtomXYZ(); - viewer.refresh(0, "minimization step " + pFF.getStepCurrent()); + /* *************************************************************** + * Minimization thead support + ****************************************************************/ + + boolean minimizationOn; + + private MinimizationThread minimizationThread; + + private void setMinimizationOn(boolean minimizationOn) { + if (!minimizationOn) { + if (minimizationThread != null) { + minimizationThread.interrupt(); + minimizationThread = null; } - - if (pFF.DetectExplosion()) - return "explosion has occurred!"; + this.minimizationOn = false; + return; } - - //return the new atom coordinates - + if (minimizationThread == null) { + minimizationThread = new MinimizationThread(); + minimizationThread.start(); + } + this.minimizationOn = true; + } + + public void startMinimization() { + if (pFF == null || viewer == null) + return; + pFF.steepestDescentInitialize(steps, crit); + saveCoordinates(); + } + + boolean stepMinimization() { + boolean doRefresh = true;//viewer.getBooleanProperty("minimizationRefresh"); + boolean going = pFF.steepestDescentTakeNSteps(1); + if (doRefresh) { + updateAtomXYZ(); + viewer.refresh(0, "minimization step " + pFF.getStepCurrent()); + } + return going; + } + + void endMinimization() { updateAtomXYZ(); if (Logger.debugging) - pFF.dumpAtomList("F I N A L G E O M E T R Y"); - return null; + pFF.dumpAtomList("F I N A L G E O M E T R Y"); + setMinimizationOn(false); + boolean failed = pFF.DetectExplosion(); + if (failed) + restoreCoordinates(); + viewer.refresh(0, "Minimizer:done" + (failed ? " EXPLODED" : "OK")); + clear(); } - private void updateAtomXYZ() { + double[][] coordSaved; + + private void saveCoordinates() { + if (coordSaved == null) + coordSaved = new double[atomCount][3]; + for (int i = 0; i < atomCount; i++) + for (int j = 0; j < 3; j++) + coordSaved[i][j] = minAtoms[i].coord[j]; + } + + private void restoreCoordinates() { + if (coordSaved == null) + return; + for (int i = 0; i < atomCount; i++) + for (int j = 0; j < 3; j++) + minAtoms[i].coord[j] = coordSaved[i][j]; + updateAtomXYZ(); + } + + private void stopMinimization(boolean coordAreOK) { + setMinimizationOn(false); + if (coordAreOK) + endMinimization(); + else + restoreCoordinates(); + } + + void updateAtomXYZ() { if (steps == 0) return; for (int i = 0; i < atomCount; i++) { @@ -527,7 +626,34 @@ atom.y = (float) minAtom.coord[1]; atom.z = (float) minAtom.coord[2]; } + viewer.setTaintedAtoms(bsTaint, AtomCollection.TAINT_COORD); + viewer.setShapeProperty(JmolConstants.SHAPE_MEASURES, "refresh", null); } - - + + class MinimizationThread extends Thread implements Runnable { + public void run() { + long startTime = System.currentTimeMillis(); + long lastRepaintTime = startTime; + + //should save the atom coordinates + startMinimization(); + + try { + do { + long currentTime = System.currentTimeMillis(); + int elapsed = (int) (currentTime - lastRepaintTime); + int sleepTime = 33 - elapsed; + if (sleepTime > 0) + Thread.sleep(sleepTime); + lastRepaintTime = currentTime = System.currentTimeMillis(); + if (!stepMinimization()) + endMinimization(); + elapsed = (int) (currentTime - startTime); + } while (!isInterrupted()); + } catch (Exception e) { + if (minimizationOn) + System.out.println(" minimization thread interrupted"); + } + } + } } Modified: branches/bob-minimize/Jmol/src/org/jmol/minimize/forcefield/CalculationsUFF.java =================================================================== --- branches/bob-minimize/Jmol/src/org/jmol/minimize/forcefield/CalculationsUFF.java 2008-03-25 21:12:28 UTC (rev 9199) +++ branches/bob-minimize/Jmol/src/org/jmol/minimize/forcefield/CalculationsUFF.java 2008-03-25 22:33:58 UTC (rev 9200) @@ -342,7 +342,7 @@ * (3.0 * rab * rbc * (1.0 - cosT0 * cosT0) - rac * rac * cosT0); calc.addElement(new Object[] { new int[] { ia, ib, ic, coordination }, - new double[] { ka, c0, c1, c2, theta0 * RAD_TO_DEG } }); + new double[] { ka, c0 - c2, c1, 2 * c2, theta0 * RAD_TO_DEG } }); } double compute(boolean debugging, Object[] dataIn) { @@ -353,9 +353,9 @@ ic = iData[2]; int coordination = iData[3]; double ka = dData[0]; - double c0 = dData[1]; - double c1 = dData[2]; - double c2 = dData[3]; + double a0 = dData[1]; + double a1 = dData[2]; + double a2 = dData[3]; if (gradients) { da.set(atoms[ia].coord); @@ -370,38 +370,43 @@ theta = 0.0; // doesn't explain why GetAngle is returning NaN but solves it for us; //problem here for square planar cis or trans - if ((coordination == 4 || coordination == 6) && theta > 2.35619) // 135o + if ((coordination == 4 || coordination == 6) && + (theta > 2.35619 || theta < 0.785398)) // 135o, 45o coordination = 1; + double cosT = Math.cos(theta); + double sinT = Math.sin(theta); switch (coordination) { case 1: //sp - energy = ka * (1.0 + Math.cos(theta)); + energy = ka * (1.0 + cosT) * (1.0 + cosT) / 4.0; break; case 2: //sp2 - energy = ka * (1.0 - Math.cos(3.0 * theta)) / 9.0; + //(1 + 4cos(theta) + 4cos(theta)^2)/9 + energy = ka * (1.0 + (4.0 * cosT) * (1.0 + cosT)) / 9.0; break; case 4: //dsp2 case 6: //d2sp3 - energy = ka * (1.0 - Math.cos(4.0 * theta)) / 16.0; + energy = ka * cosT * cosT; break; default: - energy = ka * (c0 + c1 * Math.cos(theta) + c2 * Math.cos(2.0 * theta)); + // + energy = ka * (a0 + a1 * cosT + a2 * cosT * cosT); } if (gradients) { // da = dTheta/dx * dE/dTheta switch (coordination) { case 1: - dE = -ka * Math.sin(theta); + dE = -0.5 * ka * sinT * (1 + cosT); break; case 2: - dE = ka * Math.sin(3.0 * theta) / 3.0; + dE = -4.0 * sinT * ka * (1.0 - 2.0 * cosT)/9.0; break; case 4: case 6: - dE = -ka * Math.sin(4.0 * theta) / 4.0; + dE = -ka * sinT * cosT; break; default: - dE = -ka * (c1 * Math.sin(theta) + 2.0 * c2 * Math.sin(2.0 * theta)); + dE = -ka * (a1 * sinT - 2.0 * a2 * cosT * sinT); } addGradient(da, ia, dE); addGradient(db, ib, dE); @@ -675,7 +680,7 @@ * * = K [ c0 + c1 cos(theta) + c2 (2 cos(theta)^2 - 1) ] * - * = K [ (c0 - c2) + c1 cos(theta) + 2 c2 ] + * = K [ (c0 - c2) + c1 cos(theta) + 2 c2 cos(theta)^2] * * so * Modified: branches/bob-minimize/Jmol/src/org/jmol/minimize/forcefield/ForceField.java =================================================================== --- branches/bob-minimize/Jmol/src/org/jmol/minimize/forcefield/ForceField.java 2008-03-25 21:12:28 UTC (rev 9199) +++ branches/bob-minimize/Jmol/src/org/jmol/minimize/forcefield/ForceField.java 2008-03-25 22:33:58 UTC (rev 9200) @@ -52,13 +52,13 @@ Calculations calc; - private String GetUnit() { + private String getUnits() { return calc.getUnit(); } public abstract Vector getAtomTypes(); - protected abstract Hashtable ParseParamFile(); + protected abstract Hashtable getFFParameters(); private double criterion, e0; private int stepCurrent, stepMax; @@ -90,7 +90,7 @@ public boolean setup() { if (!calc.haveParams()) { - Hashtable temp = ParseParamFile(); + Hashtable temp = getFFParameters(); if (temp == null) return false; calc.setParams(temp); @@ -114,7 +114,7 @@ public void steepestDescentInitialize(int stepMax, double criterion) { this.stepMax = stepMax;//1000 - this.criterion = criterion; //1e-6 + this.criterion = criterion; //1e-3 stepCurrent = 0; clearGradients(); @@ -134,26 +134,29 @@ public boolean steepestDescentTakeNSteps(int n) { if (stepMax == 0) return false; - + for (int iStep = 1; iStep <= n; iStep++) { stepCurrent++; calc.setSilent(true); for (int i = 0; i < atomCount; i++) - setGradientsUsingNumericalDerivative(atoms[i], ENERGY); - linearSearch(); + setGradientsUsingNumericalDerivative(atoms[i], ENERGY); + linearSearch(); calc.setSilent(false); - + if (Logger.debugging) calc.dumpAtomList("S T E P " + stepCurrent); - + double e1 = energyFull(false, false); - if (stepCurrent % 10 == 0) - Logger.info(TextFormat.sprintf(" %4i %8.3f %8.3f", - null, new float[] { (float) e1, (float) e0 }, + boolean done = Util.isNear(e1, e0, criterion); + if (done || stepCurrent % 10 == 0) + Logger.info(TextFormat.sprintf(" Step %-4i E = %10.6f dE = %8.6f criterion %10.8f", null, + new float[] { (float) e1, (float) (e1 - e0), (float) criterion }, new int[] { stepCurrent })); - if (Util.isNear(e1, e0, criterion)) { - Logger.info(" STEEPEST DESCENT HAS CONVERGED: " + e1); + if (done) { + Logger.info(TextFormat.formatString( + " STEEPEST DESCENT HAS CONVERGED: E = %8.5f " + getUnits() + " after " + stepCurrent + " steps", "f", + (float) e1)); return false; //done } @@ -162,7 +165,7 @@ } e0 = e1; - } + } return true; // continue } @@ -255,7 +258,7 @@ + energyES(gradients); if (!isSilent && Logger.debugging) - Logger.info(TextFormat.sprintf("\nTOTAL ENERGY = %8.3f " + GetUnit() + "\n", + Logger.info(TextFormat.sprintf("\nTOTAL ENERGY = %8.3f " + getUnits() + "\n", null, new float[] { (float) energy })); return energy; } Modified: branches/bob-minimize/Jmol/src/org/jmol/minimize/forcefield/ForceFieldUFF.java =================================================================== --- branches/bob-minimize/Jmol/src/org/jmol/minimize/forcefield/ForceFieldUFF.java 2008-03-25 21:12:28 UTC (rev 9199) +++ branches/bob-minimize/Jmol/src/org/jmol/minimize/forcefield/ForceFieldUFF.java 2008-03-25 22:33:58 UTC (rev 9200) @@ -46,7 +46,7 @@ calc = new CalculationsUFF(atoms, bonds, angles, torsions, partialCharges); } - protected Hashtable ParseParamFile() { + protected Hashtable getFFParameters() { FFParam ffParam; Hashtable temp = new Hashtable(); @@ -58,11 +58,10 @@ try { if ((url = this.getClass().getResource(fileName)) == null) System.err.println("Couldn't find file: " + fileName); - //turns out from the Jar file // it's a sun.net.www.protocol.jar.JarURLConnection$JarURLInputStream // and within Eclipse it's a BufferedInputStream - //LogPanel.log(name + " : " + url.getContent().toString()); + br = new BufferedReader(new InputStreamReader( (InputStream) url.getContent())); String line; @@ -122,10 +121,11 @@ try{ br.close(); } catch (Exception ee) { - // + } return null; } + Logger.info(temp.size() + " atom types read from " + fileName); return temp; } @@ -140,7 +140,7 @@ //turns out from the Jar file // it's a sun.net.www.protocol.jar.JarURLConnection$JarURLInputStream // and within Eclipse it's a BufferedInputStream - //LogPanel.log(name + " : " + url.getContent().toString()); + BufferedReader br = new BufferedReader(new InputStreamReader( (InputStream) url.getContent())); String line; @@ -158,6 +158,7 @@ + fileName); } + Logger.info(types.size() + " force field parameters read"); return (types.size() > 0 ? types : null); } } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |