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