1 // ******************************************************************************
2 //
3 // Title: Force Field X.
4 // Description: Force Field X - Software for Molecular Biophysics.
5 // Copyright: Copyright (c) Michael J. Schnieders 2001-2023.
6 //
7 // This file is part of Force Field X.
8 //
9 // Force Field X is free software; you can redistribute it and/or modify it
10 // under the terms of the GNU General Public License version 3 as published by
11 // the Free Software Foundation.
12 //
13 // Force Field X is distributed in the hope that it will be useful, but WITHOUT
14 // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
15 // FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
16 // details.
17 //
18 // You should have received a copy of the GNU General Public License along with
19 // Force Field X; if not, write to the Free Software Foundation, Inc., 59 Temple
20 // Place, Suite 330, Boston, MA 02111-1307 USA
21 //
22 // Linking this library statically or dynamically with other modules is making a
23 // combined work based on this library. Thus, the terms and conditions of the
24 // GNU General Public License cover the whole combination.
25 //
26 // As a special exception, the copyright holders of this library give you
27 // permission to link this library with independent modules to produce an
28 // executable, regardless of the license terms of these independent modules, and
29 // to copy and distribute the resulting executable under terms of your choice,
30 // provided that you also meet, for each linked independent module, the terms
31 // and conditions of the license of that module. An independent module is a
32 // module which is not derived from or based on this library. If you modify this
33 // library, you may extend this exception to your version of the library, but
34 // you are not obligated to do so. If you do not wish to do so, delete this
35 // exception statement from your version.
36 //
37 // ******************************************************************************
38 package ffx.algorithms.mc;
39
40 import static java.lang.System.arraycopy;
41
42 import ffx.potential.MolecularAssembly;
43 import ffx.potential.bonded.Atom;
44 import ffx.potential.bonded.ResidueState;
45 import org.apache.commons.math3.distribution.NormalDistribution;
46
47 /**
48 * The CoordShakeMove class implements a simplistic atomic coordinate shake. At present, simply adds
49 * a random number from a normal distribution to each Cartesian coordinate; in the future, will use
50 * a move in polar coordinates.
51 *
52 * @author Michael J. Schnieders
53 * @author Jacob M. Litman
54 * @since 1.0
55 */
56 public class CoordShakeMove implements MCMove {
57
58 private Atom[] atoms;
59 private double[][] originalCoords;
60 private double sigma = 0.001;
61 private NormalDistribution dist;
62
63 /**
64 * Constructor for CoordShakeMove.
65 *
66 * @param assembly a {@link ffx.potential.MolecularAssembly} object.
67 */
68 public CoordShakeMove(MolecularAssembly assembly) {
69 this(assembly.getAtomArray());
70 }
71
72 /**
73 * Constructor for CoordShakeMove.
74 *
75 * @param atoms an array of {@link ffx.potential.bonded.Atom} objects.
76 */
77 public CoordShakeMove(Atom[] atoms) {
78 int nAtoms = atoms.length;
79 this.atoms = new Atom[nAtoms];
80 arraycopy(atoms, 0, this.atoms, 0, nAtoms);
81 originalCoords = ResidueState.storeAtomicCoordinates(this.atoms);
82 dist = new NormalDistribution(0, sigma);
83 }
84
85 /** {@inheritDoc} */
86 @Override
87 public void move() {
88 originalCoords = ResidueState.storeAtomicCoordinates(atoms);
89 // Perform the shake.
90 for (Atom atom : atoms) {
91 double[] xyz = new double[3];
92 atom.getXYZ(xyz);
93 for (int j = 0; j < 3; j++) {
94 xyz[j] += dist.sample();
95 }
96 atom.setXYZ(xyz);
97 }
98 }
99
100 /** {@inheritDoc} */
101 @Override
102 public void revertMove() {
103 ResidueState.revertAtomicCoordinates(atoms, originalCoords);
104 }
105
106 /**
107 * Setter for the field <code>atoms</code>.
108 *
109 * @param atoms an array of {@link ffx.potential.bonded.Atom} objects.
110 */
111 public void setAtoms(Atom[] atoms) {
112 int nAtoms = atoms.length;
113 this.atoms = new Atom[nAtoms];
114 arraycopy(atoms, 0, this.atoms, 0, nAtoms);
115 originalCoords = ResidueState.storeAtomicCoordinates(atoms);
116 }
117
118 /**
119 * Setter for the field <code>sigma</code>.
120 *
121 * @param sigma a double.
122 */
123 public void setSigma(double sigma) {
124 this.sigma = sigma;
125 dist = new NormalDistribution(0, sigma);
126 }
127
128 /** {@inheritDoc} */
129 @Override
130 public String toString() {
131 return String.format(
132 " Coordinate randomization: normal distribution with sigma %10.6f.", sigma);
133 }
134 }