String getDebugFooter(int iType, double energy) { String s = ""; switch (iType) { case CALC_DISTANCE: s = "BOND STRETCHING"; break; case CALC_ANGLE: s = "ANGLE BENDING"; break; case CALC_TORSION: s = "TORSIONAL"; break; case CALC_OOP: s = "OUT-OF-PLANE BENDING"; break; case CALC_VDW: s = "VAN DER WAALS"; break; case CALC_ES: s = "ELECTROSTATIC ENERGY"; break; } return TextFormat.sprintf( "\n TOTAL %s ENERGY = %8.3f %s\n", new String[] {s, getUnit()}, new float[] {(float) energy}); }
/* // // f(x + 2delta) - 2f(x + delta) + f(x) // f''(x) = ------------------------------------ // (delta)^2 // void getNumericalSecondDerivative(MinAtom atom, int terms, Vector3d dir) { double delta = 1.0e-5; double e0 = getEnergy(terms, false); double dx = getDx2(atom, terms, 0, e0, delta); double dy = getDx2(atom, terms, 1, e0, delta); double dz = getDx2(atom, terms, 2, e0, delta); dir.set(dx, dy, dz); } private double getDx2(MinAtom atom, int terms, int i, double e0, double delta) { // calculate f(1) atom.coord[i] += delta; double e1 = getEnergy(terms, false); // calculate f(2) atom.coord[i] += delta; double e2 = getEnergy(terms, false); atom.coord[i] -= 2 * delta; return (e2 - 2 * e1 + e0) / (delta * delta); } */ public double energyFull(boolean gradients, boolean isSilent) { double energy; if (gradients) clearForces(); energy = energyBond(gradients) + energyAngle(gradients) + energyTorsion(gradients) + energyStretchBend(gradients) + energyOOP(gradients) + energyVDW(gradients) + energyES(gradients); if (!isSilent && calc.loggingEnabled) calc.appendLogData( TextFormat.sprintf( "\nTOTAL %s ENERGY = %8.3f %s/mol\n", new Object[] {name, Float.valueOf(toUserUnits(energy)), minimizer.units})); return energy; }
String getAtomList(String title) { String trailer = "----------------------------------------" + "-------------------------------------------------------\n"; StringBuffer sb = new StringBuffer(); sb.append( "\n" + title + "\n\n" + " ATOM X Y Z TYPE GRADX GRADY GRADZ " + "---------BONDED ATOMS--------\n" + trailer); for (int i = 0; i < atomCount; i++) { MinAtom atom = atoms[i]; int[] others = atom.getBondedAtomIndexes(); int[] iVal = new int[others.length + 1]; iVal[0] = atom.atom.getAtomNumber(); String s = " "; for (int j = 0; j < others.length; j++) { s += " %3d"; iVal[j + 1] = atoms[others[j]].atom.getAtomNumber(); } sb.append( TextFormat.sprintf( "%3d %8.3f %8.3f %8.3f %-5s %8.3f %8.3f %8.3f" + s + "\n", new String[] {atom.type}, new float[] { (float) atom.coord[0], (float) atom.coord[1], (float) atom.coord[2], (float) atom.force[0], (float) atom.force[1], (float) atom.force[2], }, iVal)); } sb.append(trailer + "\n\n"); return sb.toString(); }
public void steepestDescentInitialize(int stepMax, double criterion) { this.stepMax = stepMax; // 1000 // The criterion must be in the units of the calculation. // However, the user is setting this, so they will be in Minimizer units. // this.criterion = criterion / toUserUnits(1); // 1e-3 currentStep = 0; clearForces(); calc.setLoggingEnabled(true); calc.setLoggingEnabled(stepMax == 0 || Logger.isActiveLevel(Logger.LEVEL_DEBUGHIGH)); String s = name + " " + calc.getDebugHeader(-1) + "Jmol Minimization Version " + Viewer.getJmolVersion() + "\n"; calc.appendLogData(s); Logger.info(s); calc.getConstraintList(); if (calc.loggingEnabled) calc.appendLogData(calc.getAtomList("S T E E P E S T D E S C E N T")); dE = 0; calc.setPreliminary(stepMax > 0); e0 = energyFull(false, false); s = TextFormat.sprintf( " Initial " + name + " E = %10.3f " + minimizer.units + " criterion = %8.6f max steps = " + stepMax, new Object[] {Float.valueOf(toUserUnits(e0)), Float.valueOf(toUserUnits(criterion))}); minimizer.report(s, false); calc.appendLogData(s); }
// Vector3d dir = new Vector3d(); public boolean steepestDescentTakeNSteps(int n) { if (stepMax == 0) return false; boolean isPreliminary = true; for (int iStep = 1; iStep <= n; iStep++) { currentStep++; calc.setSilent(true); for (int i = 0; i < minAtomCount; i++) if (bsFixed == null || !bsFixed.get(i)) setForcesUsingNumericalDerivative(minAtoms[i], ENERGY); linearSearch(); calc.setSilent(false); if (calc.loggingEnabled) calc.appendLogData(calc.getAtomList("S T E P " + currentStep)); double e1 = energyFull(false, false); dE = e1 - e0; boolean done = Util.isNear(e1, e0, criterion); if (done || currentStep % 10 == 0 || stepMax <= currentStep) { String s = TextFormat.sprintf( name + " Step %-4d E = %10.6f dE = %8.6f ", new Object[] { new float[] {(float) e1, (float) (dE), (float) criterion}, Integer.valueOf(currentStep) }); minimizer.report(s, false); calc.appendLogData(s); } e0 = e1; if (done || stepMax <= currentStep) { if (calc.loggingEnabled) calc.appendLogData(calc.getAtomList("F I N A L G E O M E T R Y")); if (done) { String s = TextFormat.formatString( "\n " + name + " STEEPEST DESCENT HAS CONVERGED: E = %8.5f " + minimizer.units + " after " + currentStep + " steps", "f", toUserUnits(e1)); calc.appendLogData(s); minimizer.report(s, true); Logger.info(s); } return false; } // System.out.println(isPreliminary + " " + getNormalizedDE() + " " + currentStep); if (isPreliminary && getNormalizedDE() >= 2) { // looking back at this after some time, I don't exactly see why I wanted // this to stay in preliminary mode unless |DE| >= 2 * crit. // It's hard to ever have |DE| NOT >= 2 * crit -- that would be very close to the criterion. // And when that IS the case, why would you want to STAY in preliminary mode? Hmm. calc.setPreliminary(isPreliminary = false); e0 = energyFull(false, false); } } return true; // continue }
String getDebugLine(int iType, Calculation c) { switch (iType) { case CALC_DISTANCE: return TextFormat.sprintf( "%3d %3d %-5s %-5s %4.2f%8.3f %8.3f %8.3f %8.3f %8.3f", new String[] {atoms[c.ia].type, atoms[c.ib].type}, new float[] { (float) c.dData[2] /*rab*/, (float) c.rab, (float) c.dData[0], (float) c.dData[1], (float) c.delta, (float) c.energy }, new int[] {atoms[c.ia].atom.getAtomNumber(), atoms[c.ib].atom.getAtomNumber()}); case CALC_ANGLE: return TextFormat.sprintf( "%3d %3d %3d %-5s %-5s %-5s %8.3f %8.3f %8.3f %8.3f", new String[] {atoms[c.ia].type, atoms[c.ib].type, atoms[c.ic].type}, new float[] { (float) (c.theta * RAD_TO_DEG), (float) c.dData[4] /*THETA0*/, (float) c.dData[0] /*Kijk*/, (float) c.energy }, new int[] { atoms[c.ia].atom.getAtomNumber(), atoms[c.ib].atom.getAtomNumber(), atoms[c.ic].atom.getAtomNumber() }); case CALC_TORSION: return TextFormat.sprintf( "%3d %3d %3d %3d %-5s %-5s %-5s %-5s %8.3f %8.3f %8.3f", new String[] {atoms[c.ia].type, atoms[c.ib].type, atoms[c.ic].type, atoms[c.id].type}, new float[] { (float) c.dData[0] /*V*/, (float) (c.theta * RAD_TO_DEG), (float) c.energy }, new int[] { atoms[c.ia].atom.getAtomNumber(), atoms[c.ib].atom.getAtomNumber(), atoms[c.ic].atom.getAtomNumber(), atoms[c.id].atom.getAtomNumber() }); case CALC_OOP: return TextFormat.sprintf( "" + "%3d %3d %3d %3d %-5s %-5s %-5s %-5s %8.3f %8.3f %8.3f", new String[] {atoms[c.ia].type, atoms[c.ib].type, atoms[c.ic].type, atoms[c.id].type}, new float[] { (float) (c.theta * RAD_TO_DEG), (float) c.dData[0] /*koop*/, (float) c.energy }, new int[] { atoms[c.ia].atom.getAtomNumber(), atoms[c.ib].atom.getAtomNumber(), atoms[c.ic].atom.getAtomNumber(), atoms[c.id].atom.getAtomNumber() }); case CALC_VDW: return TextFormat.sprintf( "%3d %3d %-5s %-5s %6.3f %8.3f %8.3f", new String[] {atoms[c.iData[0]].type, atoms[c.iData[1]].type}, new float[] {(float) c.rab, (float) c.dData[0] /*kab*/, (float) c.energy}, new int[] {atoms[c.ia].atom.getAtomNumber(), atoms[c.ib].atom.getAtomNumber()}); case CALC_ES: return TextFormat.sprintf( "%3d %3d %-5s %-5s %6.3f %8.3f %8.3f", new String[] {atoms[c.iData[0]].type, atoms[c.iData[1]].type}, new float[] {(float) c.rab, (float) c.dData[0] /*qq*/, (float) c.energy}, new int[] {atoms[c.ia].atom.getAtomNumber(), atoms[c.ib].atom.getAtomNumber()}); } return ""; }