ffx.potential.parameters.OutOfPlaneBendType.java Source code

Java tutorial

Introduction

Here is the source code for ffx.potential.parameters.OutOfPlaneBendType.java

Source

/**
 * Title: Force Field X.
 *
 * Description: Force Field X - Software for Molecular Biophysics.
 *
 * Copyright: Copyright (c) Michael J. Schnieders 2001-2017.
 *
 * This file is part of Force Field X.
 *
 * Force Field X is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 3 as published by
 * the Free Software Foundation.
 *
 * Force Field X is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
 * details.
 *
 * You should have received a copy of the GNU General Public License along with
 * Force Field X; if not, write to the Free Software Foundation, Inc., 59 Temple
 * Place, Suite 330, Boston, MA 02111-1307 USA
 *
 * Linking this library statically or dynamically with other modules is making a
 * combined work based on this library. Thus, the terms and conditions of the
 * GNU General Public License cover the whole combination.
 *
 * As a special exception, the copyright holders of this library give you
 * permission to link this library with independent modules to produce an
 * executable, regardless of the license terms of these independent modules, and
 * to copy and distribute the resulting executable under terms of your choice,
 * provided that you also meet, for each linked independent module, the terms
 * and conditions of the license of that module. An independent module is a
 * module which is not derived from or based on this library. If you modify this
 * library, you may extend this exception to your version of the library, but
 * you are not obligated to do so. If you do not wish to do so, delete this
 * exception statement from your version.
 */
package ffx.potential.parameters;

import java.util.Arrays;
import java.util.Comparator;
import java.util.HashMap;

import static org.apache.commons.math3.util.FastMath.PI;
import static org.apache.commons.math3.util.FastMath.pow;

/**
 * The OutOfPlaneBendType class defines one Allinger style out-of-plane angle
 * bending energy type.
 *
 * @author Michael J. Schnieders
 * @since 1.0
 *
 */
public final class OutOfPlaneBendType extends BaseType implements Comparator<String> {

    /**
     * Atom classes for this out-of-plane angle bending type.
     */
    public final int atomClasses[];
    /**
     * Force constant (Kcal/mol/Angstrom).
     */
    public final double forceConstant;

    /**
     * OutOfPlaneBendType Constructor.
     *
     * @param atomClasses int[]
     * @param forceConstant double
     */
    public OutOfPlaneBendType(int atomClasses[], double forceConstant) {
        super(ForceField.ForceFieldType.OPBEND, sortKey(atomClasses));
        this.atomClasses = atomClasses;
        this.forceConstant = forceConstant;
    }

    /**
     * <p>
     * incrementClasses</p>
     *
     * @param increment a int.
     */
    public void incrementClasses(int increment) {
        for (int i = 0; i < atomClasses.length; i++) {
            if (atomClasses[i] > 0) {
                atomClasses[i] += increment;
            }
        }
        setKey(sortKey(atomClasses));
    }

    /**
     * Remap new atom classes to known internal ones.
     *
     * @param typeMap a lookup between new atom types and known atom types.
     * @return
     */
    public OutOfPlaneBendType patchClasses(HashMap<AtomType, AtomType> typeMap) {
        int count = 0;
        int len = atomClasses.length;
        /**
         * Look for new OutOfPlaneBends that contain 1 mapped atom classes.
         */
        for (AtomType newType : typeMap.keySet()) {
            for (int i = 0; i < len; i++) {
                if (atomClasses[i] == newType.atomClass) {
                    count++;
                }
            }
        }
        /**
         * If found, create a new OutOfPlaneBend that bridges to known classes.
         */
        if (count == 1) {
            int newClasses[] = Arrays.copyOf(atomClasses, len);
            for (AtomType newType : typeMap.keySet()) {
                for (int i = 0; i < len; i++) {
                    if (atomClasses[i] == newType.atomClass) {
                        AtomType knownType = typeMap.get(newType);
                        newClasses[i] = knownType.atomClass;
                    }
                }
            }
            return new OutOfPlaneBendType(newClasses, forceConstant);
        }
        return null;
    }

    /**
     * This method sorts the atom classes for the out-of-plane angle bending
     * type.
     *
     * @param c atomClasses
     * @return lookup key
     */
    public static String sortKey(int c[]) {
        if (c == null || c.length != 4) {
            return null;
        }
        String key = c[0] + " " + c[1] + " " + c[2] + " " + c[3];
        return key;
    }

    /**
     * {@inheritDoc}
     *
     * Nicely formatted out-of-plane angle bending string.
     */
    @Override
    public String toString() {
        return String.format("opbend  %5d  %5d  %5d  %5d  %6.2f", atomClasses[0], atomClasses[1], atomClasses[2],
                atomClasses[3], forceConstant);
    }

    /**
     * Cubic coefficient in out-of-plane angle bending potential.
     */
    public static final double cubic = -0.014;
    /**
     * Quartic coefficient in out-of-plane angle bending potential.
     */
    public static final double quartic = 0.000056;
    /**
     * Quintic coefficient in out-of-plane angle bending potential.
     */
    public static final double quintic = -0.0000007;
    /**
     * Sextic coefficient in out-of-plane angle bending potential.
     */
    public static final double sextic = 0.000000022;
    /**
     * Convert Out-of-Plane bending energy to kcal/mole.
     *
     * TINKER v.5 and v.6 Units: 1.0 / (180.0/PI)^2 = 0.00030461741979 TINKER
     * v.4 Units: 0.02191418
     *
     * Ratio of v.4 to v.5/6 = 0.02191418 / 1.0 / (180.0/PI)^2 = 71.94
     */
    public static final double units = 1.0 / pow(180.0 / PI, 2);

    /**
     * {@inheritDoc}
     */
    @Override
    public int compare(String s1, String s2) {
        String keys1[] = s1.split(" ");
        String keys2[] = s2.split(" ");

        for (int i = 0; i < 4; i++) {
            int c1 = Integer.parseInt(keys1[i]);
            int c2 = Integer.parseInt(keys2[i]);
            if (c1 < c2) {
                return -1;
            } else if (c1 > c2) {
                return 1;
            }
        }
        return 0;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public boolean equals(Object other) {
        if (other == this) {
            return true;
        }
        if (other == null || !(other instanceof OutOfPlaneBendType)) {
            return false;
        }
        OutOfPlaneBendType outOfPlaneBendType = (OutOfPlaneBendType) other;
        for (int i = 0; i < 4; i++) {
            if (outOfPlaneBendType.atomClasses[i] != atomClasses[i]) {
                return false;
            }
        }
        return true;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public int hashCode() {
        int hash = 7;
        hash = 53 * hash + Arrays.hashCode(atomClasses);
        return hash;
    }

    /**
     * Average two OutOfPlaneBendType instances. The atom classes that define
     * the new type must be supplied.
     *
     * @param outOfPlaneBendType1
     * @param outOfPlaneBendType2
     * @param atomClasses
     * @return
     */
    public static OutOfPlaneBendType average(OutOfPlaneBendType outOfPlaneBendType1,
            OutOfPlaneBendType outOfPlaneBendType2, int atomClasses[]) {
        if (outOfPlaneBendType1 == null || outOfPlaneBendType2 == null || atomClasses == null) {
            return null;
        }

        double forceConstant = (outOfPlaneBendType1.forceConstant + outOfPlaneBendType2.forceConstant) / 2.0;

        return new OutOfPlaneBendType(atomClasses, forceConstant);
    }

}