1 // ******************************************************************************
2 //
3 // Title: Force Field X.
4 // Description: Force Field X - Software for Molecular Biophysics.
5 // Copyright: Copyright (c) Michael J. Schnieders 2001-2025.
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.potential.nonbonded;
39
40 import edu.rit.pj.IntegerForLoop;
41 import edu.rit.pj.IntegerSchedule;
42
43 import java.util.logging.Logger;
44
45 /**
46 * Loop over a list of atoms and assign their density to a grid.
47 *
48 * @author Michael J. Schnieders
49 * @since 1.0
50 */
51 public abstract class SpatialDensityLoop extends IntegerForLoop {
52
53 private static final Logger logger = Logger.getLogger(SpatialDensityLoop.class.getName());
54 private int nSymm;
55 private SpatialDensityRegion spatialDensityRegion;
56 private SpatialDensitySchedule spatialDensitySchedule;
57 private int octant = 0;
58
59 /**
60 * Constructor for SpatialDensityLoop.
61 *
62 * @param region a {@link ffx.potential.nonbonded.SpatialDensityRegion} object.
63 * @param nSymm a int.
64 * @param atomsPerChunk an array of int.
65 */
66 public SpatialDensityLoop(SpatialDensityRegion region, int nSymm, int[] atomsPerChunk) {
67 this.spatialDensityRegion = region;
68 this.nSymm = nSymm;
69 this.spatialDensitySchedule =
70 new SpatialDensitySchedule(region.nThreads, region.nAtoms, atomsPerChunk, 0.97);
71 assert (nSymm <= region.nSymm);
72 }
73
74 /**
75 * gridDensity
76 *
77 * @param iSymm a int.
78 * @param iAtom a int.
79 */
80 public abstract void gridDensity(int iSymm, int iAtom);
81
82 /** {@inheritDoc} */
83 @Override
84 public void run(int lb, int ub) {
85 // Loop over work cells
86 for (int icell = lb; icell <= ub; icell++) {
87 int ia = spatialDensityRegion.actualA[icell];
88 int ib = spatialDensityRegion.actualB[icell];
89 int ic = spatialDensityRegion.actualC[icell];
90 switch (octant) {
91 // Case 0 -> In place.
92 case 0:
93 gridCell(ia, ib, ic);
94 break;
95 // Case 1: Step along the C-axis.
96 case 1:
97 gridCell(ia, ib, ic + 1);
98 break;
99 // Case 2 & 3: Step along the B-axis.
100 case 2:
101 gridCell(ia, ib + 1, ic);
102 break;
103 case 3:
104 gridCell(ia, ib + 1, ic + 1);
105 break;
106 // Case 4-7: Step along the A-axis.
107 case 4:
108 gridCell(ia + 1, ib, ic);
109 break;
110 case 5:
111 gridCell(ia + 1, ib, ic + 1);
112 break;
113 case 6:
114 gridCell(ia + 1, ib + 1, ic);
115 break;
116 case 7:
117 gridCell(ia + 1, ib + 1, ic + 1);
118 break;
119 default:
120 String message = "Programming error in PermanentDensityLoop.\n";
121 logger.severe(message);
122 }
123 }
124 }
125
126 /** {@inheritDoc} */
127 @Override
128 public IntegerSchedule schedule() {
129 return spatialDensitySchedule;
130 }
131
132 /**
133 * setNsymm
134 *
135 * @param nSymm a int.
136 */
137 public void setNsymm(int nSymm) {
138 this.nSymm = nSymm;
139 assert (nSymm <= spatialDensityRegion.nSymm);
140 }
141
142 /**
143 * Setter for the field <code>octant</code>.
144 *
145 * @param octant a int.
146 * @return a {@link ffx.potential.nonbonded.SpatialDensityLoop} object.
147 */
148 public SpatialDensityLoop setOctant(int octant) {
149 this.octant = octant;
150 return this;
151 }
152
153 /**
154 * setRegion.
155 *
156 * @param spatialDensityRegion a {@link ffx.potential.nonbonded.SpatialDensityRegion} object.
157 */
158 public void setRegion(SpatialDensityRegion spatialDensityRegion) {
159 this.spatialDensityRegion = spatialDensityRegion;
160 this.spatialDensitySchedule =
161 new SpatialDensitySchedule(
162 spatialDensityRegion.nThreads,
163 spatialDensityRegion.nAtoms,
164 spatialDensityRegion.actualCount,
165 0.97);
166 }
167
168 private void gridCell(int ia, int ib, int ic) {
169 for (int iSymm = 0; iSymm < nSymm; iSymm++) {
170 final int[] pairList = spatialDensityRegion.cellList[iSymm];
171 final int index = spatialDensityRegion.index(ia, ib, ic);
172 final int start = spatialDensityRegion.cellStart[iSymm][index];
173 final int stop = start + spatialDensityRegion.cellCount[iSymm][index];
174 for (int i = start; i < stop; i++) {
175 int n = pairList[i];
176 gridDensity(iSymm, n);
177 }
178 }
179 }
180 }