ffx.potential.parameters.PolarizeType.java Source code

Java tutorial

Introduction

Here is the source code for ffx.potential.parameters.PolarizeType.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.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.logging.Logger;

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

import ffx.potential.bonded.Atom;
import ffx.potential.bonded.Bond;

/**
 * The PolarizeType class defines an isotropic atomic polarizability.
 *
 * @author Michael J. Schnieders
 * @since 1.0
 *
 */
public final class PolarizeType extends BaseType implements Comparator<String> {

    private static final Logger logger = Logger.getLogger(PolarizeType.class.getName());

    private static final double sixth = 1.0 / 6.0;
    /**
     * Atom type number.
     */
    public int type;
    /**
     * Thole damping factor.
     */
    public final double thole;
    /**
     * Value of polarizability scale factor.
     */
    public final double pdamp;
    /**
     * Isotropic polarizability in units of Angstroms^3.
     */
    public final double polarizability;
    /**
     * Connected types in the polarization group of each atom. (may be null)
     */
    public int[] polarizationGroup;

    /**
     * PolarizeType Constructor.
     *
     * @param atomType int
     * @param polarizability double
     * @param polarizationGroup int[]
     * @param thole a double.
     */
    public PolarizeType(int atomType, double polarizability, double thole, int polarizationGroup[]) {
        super(ForceField.ForceFieldType.POLARIZE, Integer.toString(atomType));
        this.type = atomType;
        this.thole = thole;
        this.polarizability = polarizability;
        this.polarizationGroup = polarizationGroup;
        if (thole == 0.0) {
            pdamp = 0.0;
        } else {
            pdamp = pow(polarizability, sixth);
        }
    }

    /**
     * <p>
     * incrementType</p>
     *
     * @param increment a int.
     */
    public void incrementType(int increment) {
        type += increment;
        setKey(Integer.toString(type));
        if (polarizationGroup != null) {
            for (int i = 0; i < polarizationGroup.length; i++) {
                polarizationGroup[i] += increment;
            }
        }
    }

    /**
     * Add mapped known types to the polarization group of a new patch.
     *
     * @param typeMap a lookup between new atom types and known atom types.
     * @return
     */
    public boolean patchTypes(HashMap<AtomType, AtomType> typeMap) {
        if (polarizationGroup == null) {
            return false;
        }

        /**
         * Append known mapped types.
         */
        int len = polarizationGroup.length;
        int added = 0;
        for (AtomType newType : typeMap.keySet()) {
            for (int i = 1; i < len; i++) {
                if (polarizationGroup[i] == newType.type) {
                    AtomType knownType = typeMap.get(newType);
                    added++;
                    polarizationGroup = Arrays.copyOf(polarizationGroup, len + added);
                    polarizationGroup[len + added - 1] = knownType.type;
                }
            }
        }
        if (added > 0) {
            return true;
        }
        return false;
    }

    /**
     * <p>
     * add</p>
     *
     * @param key a int.
     */
    public void add(int key) {
        for (int i : polarizationGroup) {
            if (key == i) {
                return;
            }
        }
        int len = polarizationGroup.length;
        int newGroup[] = new int[len + 1];
        for (int i = 0; i < len; i++) {
            newGroup[i] = polarizationGroup[i];
        }
        newGroup[len] = key;
        polarizationGroup = newGroup;
    }

    /**
     * {@inheritDoc}
     *
     * Nicely formatted polarization type.
     */
    @Override
    public String toString() {
        StringBuilder polarizeString = new StringBuilder(
                String.format("polarize  %5d  %6.3f %6.3f", type, polarizability, thole));
        if (polarizationGroup != null) {
            for (int a : polarizationGroup) {
                polarizeString.append(String.format("  %5d", a));
            }
        }
        return polarizeString.toString();
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public int compare(String s1, String s2) {

        int t1 = Integer.parseInt(s1);
        int t2 = Integer.parseInt(s2);

        if (t1 < t2) {
            return -1;
        }
        if (t1 > t2) {
            return 1;
        }

        return 0;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public boolean equals(Object other) {
        if (other == this) {
            return true;
        }
        if (other == null || !(other instanceof PolarizeType)) {
            return false;
        }
        PolarizeType polarizeType = (PolarizeType) other;
        if (polarizeType.type == this.type) {
            return true;
        }

        return false;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public int hashCode() {
        int hash = 5;
        hash = 37 * hash + type;
        return hash;
    }

    /**
     * Average two PolarizeType instances. The atom types to include in the new
     * polarizationGroup must be supplied.
     *
     * @param polarizeType1
     * @param polarizeType2
     * @param atomType
     * @param polarizationGroup
     * @return
     */
    public static PolarizeType average(PolarizeType polarizeType1, PolarizeType polarizeType2, int atomType,
            int polarizationGroup[]) {
        if (polarizeType1 == null || polarizeType2 == null) {
            return null;
        }
        double thole = (polarizeType1.thole + polarizeType2.thole) / 2.0;
        double polarizability = (polarizeType1.polarizability + polarizeType2.polarizability) / 2.0;
        return new PolarizeType(atomType, thole, polarizability, polarizationGroup);
    }

    public static void assignPolarizationGroups(Atom atoms[], int ip11[][], int ip12[][], int ip13[][]) {
        /**
         * Find directly connected group members for each atom.
         */
        List<Integer> group = new ArrayList<>();
        List<Integer> polarizationGroup = new ArrayList<>();
        //int g11 = 0;
        for (Atom ai : atoms) {
            group.clear();
            polarizationGroup.clear();
            Integer index = ai.getXYZIndex() - 1;
            group.add(index);
            polarizationGroup.add(ai.getType());
            PolarizeType polarizeType = ai.getPolarizeType();
            if (polarizeType != null) {
                if (polarizeType.polarizationGroup != null) {
                    for (int i : polarizeType.polarizationGroup) {
                        if (!polarizationGroup.contains(i)) {
                            polarizationGroup.add(i);
                        }
                    }
                    growGroup(polarizationGroup, group, ai);
                    Collections.sort(group);
                    ip11[index] = new int[group.size()];
                    int j = 0;
                    for (int k : group) {
                        ip11[index][j++] = k;
                    }
                } else {
                    ip11[index] = new int[group.size()];
                    int j = 0;
                    for (int k : group) {
                        ip11[index][j++] = k;
                    }
                }
                //g11 += ip11[index].length;
                //System.out.println(format("%d %d", index + 1, g11));
            } else {
                String message = "The polarize keyword was not found for atom " + (index + 1) + " with type "
                        + ai.getType();
                logger.severe(message);
            }
        }
        /**
         * Find 1-2 group relationships.
         */
        int nAtoms = atoms.length;
        int mask[] = new int[nAtoms];
        List<Integer> list = new ArrayList<>();
        List<Integer> keep = new ArrayList<>();
        for (int i = 0; i < nAtoms; i++) {
            mask[i] = -1;
        }
        for (int i = 0; i < nAtoms; i++) {
            list.clear();
            for (int j : ip11[i]) {
                list.add(j);
                mask[j] = i;
            }
            keep.clear();
            for (int j : list) {
                Atom aj = atoms[j];
                ArrayList<Bond> bonds = aj.getBonds();
                for (Bond b : bonds) {
                    Atom ak = b.get1_2(aj);
                    int k = ak.getXYZIndex() - 1;
                    if (mask[k] != i) {
                        keep.add(k);
                    }
                }
            }
            list.clear();
            for (int j : keep) {
                for (int k : ip11[j]) {
                    list.add(k);
                }
            }
            Collections.sort(list);
            ip12[i] = new int[list.size()];
            int j = 0;
            for (int k : list) {
                ip12[i][j++] = k;
            }
        }
        /**
         * Find 1-3 group relationships.
         */
        for (int i = 0; i < nAtoms; i++) {
            mask[i] = -1;
        }
        for (int i = 0; i < nAtoms; i++) {
            for (int j : ip11[i]) {
                mask[j] = i;
            }
            for (int j : ip12[i]) {
                mask[j] = i;
            }
            list.clear();
            for (int j : ip12[i]) {
                for (int k : ip12[j]) {
                    if (mask[k] != i) {
                        if (!list.contains(k)) {
                            list.add(k);
                        }
                    }
                }
            }
            ip13[i] = new int[list.size()];
            Collections.sort(list);
            int j = 0;
            for (int k : list) {
                ip13[i][j++] = k;
            }
        }
    }

    /**
     * A recursive method that checks all atoms bonded to the seed atom for
     * inclusion in the polarization group. The method is called on each newly
     * found group member.
     *
     * @param polarizationGroup Atom types that should be included in the group.
     * @param group XYZ indeces of current group members.
     * @param seed The bonds of the seed atom are queried for inclusion in the
     * group.
     */
    private static void growGroup(List<Integer> polarizationGroup, List<Integer> group, Atom seed) {
        List<Bond> bonds = seed.getBonds();
        for (Bond bi : bonds) {
            Atom aj = bi.get1_2(seed);
            int tj = aj.getType();
            boolean added = false;
            for (int g : polarizationGroup) {
                if (g == tj) {
                    Integer index = aj.getXYZIndex() - 1;
                    if (!group.contains(index)) {
                        group.add(index);
                        added = true;
                        break;
                    }
                }
            }
            if (added) {
                PolarizeType polarizeType = aj.getPolarizeType();
                for (int i : polarizeType.polarizationGroup) {
                    if (!polarizationGroup.contains(i)) {
                        polarizationGroup.add(i);
                    }
                }
                growGroup(polarizationGroup, group, aj);
            }
        }
    }

}