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.numerics.atomic;
39
40 import edu.rit.pj.ParallelTeam;
41
42 /**
43 * This interface abstracts away the implementation of maintaining a 1D double array that is operated
44 * on by multiple threads.
45 *
46 * @author Michael J. Schnieders
47 * @since 1.0
48 */
49 public interface AtomicDoubleArray {
50
51 /**
52 * Add a value to the double array at the specified index.
53 *
54 * @param threadID The thread ID.
55 * @param index The index of the array.
56 * @param value The value to add.
57 */
58 void add(int threadID, int index, double value);
59
60 /**
61 * Ensure the AtomicDoubleArray instance has at least the specified size.
62 *
63 * @param size The required size of the array.
64 */
65 void alloc(int size);
66
67 /**
68 * Get the value of the array at the specified index.
69 * Note: The `reduce` method should be called first when using the MULTI implementation.
70 *
71 * @param index The index of the array.
72 * @return The value at the specified index.
73 */
74 double get(int index);
75
76 /**
77 * Perform reduction between the given lower and upper bounds, if necessary.
78 *
79 * @param lowerBound The lower bound of the range.
80 * @param upperBound The upper bound of the range.
81 */
82 void reduce(int lowerBound, int upperBound);
83
84 /**
85 * Perform reduction between the given bounds using a ParallelTeam.
86 *
87 * @param parallelTeam The ParallelTeam to use.
88 * @param lowerBound The lower bound of the range.
89 * @param upperBound The upper bound of the range.
90 */
91 void reduce(ParallelTeam parallelTeam, int lowerBound, int upperBound);
92
93 /**
94 * Reset the double array values to zero within the specified bounds.
95 *
96 * @param threadID The thread ID.
97 * @param lowerBound The lower bound of the reset range.
98 * @param upperBound The upper bound of the reset range.
99 */
100 void reset(int threadID, int lowerBound, int upperBound);
101
102 /**
103 * Reset the double array values to zero within the specified bounds using a ParallelTeam.
104 *
105 * @param parallelTeam The ParallelTeam to use.
106 * @param lowerBound The lower bound of the reset range.
107 * @param upperBound The upper bound of the reset range.
108 */
109 void reset(ParallelTeam parallelTeam, int lowerBound, int upperBound);
110
111 /**
112 * Scale the value of the double array at the specified index.
113 *
114 * @param threadID The thread ID.
115 * @param index The index of the array.
116 * @param value The value to scale by.
117 */
118 void scale(int threadID, int index, double value);
119
120 /**
121 * Set the value of the double array at the specified index.
122 *
123 * @param threadID The thread ID.
124 * @param index The index of the array.
125 * @param value The value to set.
126 */
127 void set(int threadID, int index, double value);
128
129 /**
130 * Get the current size of the array.
131 *
132 * @return The size of the array.
133 */
134 int size();
135
136 /**
137 * Subtract a value from the double array at the specified index.
138 *
139 * @param threadID The thread ID.
140 * @param index The index of the array.
141 * @param value The value to subtract.
142 */
143 void sub(int threadID, int index, double value);
144
145 /**
146 * AtomicDoubleArray implementations (ADDER, MULTI, PJ).
147 */
148 enum AtomicDoubleArrayImpl {
149 /**
150 * A java.util.concurrent.atomic.DoubleAdder implementation.
151 */
152 ADDER {
153 @Override
154 public AtomicDoubleArray createInstance(int threads, int size) {
155 return new AdderDoubleArray(size);
156 }
157 },
158
159 /**
160 * Each thread has its own array, and reduction is performed by the user.
161 */
162 MULTI {
163 @Override
164 public AtomicDoubleArray createInstance(int threads, int size) {
165 return new MultiDoubleArray(threads, size);
166 }
167 },
168
169 /**
170 * Parallel Java edu.rit.pj.reduction.SharedDoubleArray implementation.
171 */
172 PJ {
173 @Override
174 public AtomicDoubleArray createInstance(int threads, int size) {
175 return new PJDoubleArray(size);
176 }
177 };
178
179 /**
180 * Factory method to create an AtomicDoubleArray instance.
181 *
182 * @param threads The number of threads.
183 * @param size The size of the array.
184 * @return A new instance of AtomicDoubleArray.
185 */
186 public abstract AtomicDoubleArray createInstance(int threads, int size);
187 }
188 }