1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38 package ffx.numerics.atomic;
39
40 import static java.lang.String.format;
41
42 import edu.rit.pj.IntegerForLoop;
43 import edu.rit.pj.ParallelRegion;
44 import edu.rit.pj.ParallelTeam;
45 import ffx.numerics.atomic.AtomicDoubleArray.AtomicDoubleArrayImpl;
46 import ffx.numerics.math.Double3;
47 import ffx.numerics.math.DoubleMath;
48 import java.util.Objects;
49
50
51
52
53
54
55
56 public class AtomicDoubleArray3D {
57
58
59
60
61 private final AtomicDoubleArray[] atomicDoubleArray;
62
63
64
65
66 private final AtomicDoubleArrayImpl atomicDoubleArrayImpl;
67
68
69
70
71 private final ParallelRegion3D parallelRegion3D = new ParallelRegion3D();
72
73
74
75
76
77
78
79 public AtomicDoubleArray3D(AtomicDoubleArrayImpl atomicDoubleArrayImpl, int size) {
80 this(atomicDoubleArrayImpl, size, ParallelTeam.getDefaultThreadCount());
81 }
82
83
84
85
86
87
88
89
90
91 public AtomicDoubleArray3D(AtomicDoubleArrayImpl atomicDoubleArrayImpl, int size, int nThreads) {
92 atomicDoubleArray = new AtomicDoubleArray[3];
93 atomicDoubleArray[0] = atomicDoubleArrayImpl.createInstance(nThreads, size);
94 atomicDoubleArray[1] = atomicDoubleArrayImpl.createInstance(nThreads, size);
95 atomicDoubleArray[2] = atomicDoubleArrayImpl.createInstance(nThreads, size);
96 this.atomicDoubleArrayImpl = atomicDoubleArrayImpl;
97 }
98
99
100
101
102
103
104
105
106 public AtomicDoubleArray3D(AtomicDoubleArray x, AtomicDoubleArray y, AtomicDoubleArray z) {
107 atomicDoubleArray = new AtomicDoubleArray[3];
108 atomicDoubleArray[0] = x;
109 atomicDoubleArray[1] = y;
110 atomicDoubleArray[2] = z;
111 if (x instanceof MultiDoubleArray) {
112 this.atomicDoubleArrayImpl = AtomicDoubleArrayImpl.MULTI;
113 } else if (x instanceof AdderDoubleArray) {
114 this.atomicDoubleArrayImpl = AtomicDoubleArrayImpl.ADDER;
115 } else {
116 this.atomicDoubleArrayImpl = AtomicDoubleArrayImpl.PJ;
117 }
118 }
119
120
121
122
123
124
125
126
127
128
129 public void add(int threadID, int index, double x, double y, double z) {
130 atomicDoubleArray[0].add(threadID, index, x);
131 atomicDoubleArray[1].add(threadID, index, y);
132 atomicDoubleArray[2].add(threadID, index, z);
133 }
134
135
136
137
138
139
140
141
142 public void add(int threadID, int index, Double3 d3) {
143 atomicDoubleArray[0].add(threadID, index, d3.x());
144 atomicDoubleArray[1].add(threadID, index, d3.y());
145 atomicDoubleArray[2].add(threadID, index, d3.z());
146 }
147
148
149
150
151
152
153 public void alloc(int size) {
154 atomicDoubleArray[0].alloc(size);
155 atomicDoubleArray[1].alloc(size);
156 atomicDoubleArray[2].alloc(size);
157 }
158
159
160
161
162
163
164
165
166 public double get(int dim, int index) {
167 return atomicDoubleArray[dim].get(index);
168 }
169
170
171
172
173
174
175
176
177 public Double3 get(int index) {
178 return new Double3(
179 atomicDoubleArray[0].get(index),
180 atomicDoubleArray[1].get(index),
181 atomicDoubleArray[2].get(index));
182 }
183
184
185
186
187
188
189
190
191 public double getX(int index) {
192 return atomicDoubleArray[0].get(index);
193 }
194
195
196
197
198
199
200
201
202 public double getY(int index) {
203 return atomicDoubleArray[1].get(index);
204 }
205
206
207
208
209
210
211
212
213 public double getZ(int index) {
214 return atomicDoubleArray[2].get(index);
215 }
216
217
218
219
220
221
222
223 public void reduce(int lb, int ub) {
224
225 if (Objects.requireNonNull(atomicDoubleArrayImpl) == AtomicDoubleArrayImpl.MULTI) {
226 atomicDoubleArray[0].reduce(lb, ub);
227 atomicDoubleArray[1].reduce(lb, ub);
228 atomicDoubleArray[2].reduce(lb, ub);
229 }
230 }
231
232
233
234
235
236
237 public void reduce(ParallelTeam parallelTeam) {
238 if (Objects.requireNonNull(atomicDoubleArrayImpl) == AtomicDoubleArrayImpl.MULTI) {
239 parallelRegion3D.setOperation(Operation.REDUCE);
240 try {
241 parallelTeam.execute(parallelRegion3D);
242 } catch (Exception e) {
243 throw new RuntimeException(e);
244 }
245 }
246 }
247
248
249
250
251
252
253
254
255 public void reset(int threadID, int lb, int ub) {
256 atomicDoubleArray[0].reset(threadID, lb, ub);
257 atomicDoubleArray[1].reset(threadID, lb, ub);
258 atomicDoubleArray[2].reset(threadID, lb, ub);
259 }
260
261
262
263
264
265
266 public void reset(ParallelTeam parallelTeam) {
267 parallelRegion3D.setOperation(Operation.RESET);
268 try {
269 parallelTeam.execute(parallelRegion3D);
270 } catch (Exception e) {
271 throw new RuntimeException(e);
272 }
273 }
274
275
276
277
278
279
280
281
282 public void scale(int threadID, int index, double scale) {
283 atomicDoubleArray[0].scale(threadID, index, scale);
284 atomicDoubleArray[1].scale(threadID, index, scale);
285 atomicDoubleArray[2].scale(threadID, index, scale);
286 }
287
288
289
290
291
292
293
294
295
296
297 public void set(int threadID, int index, double x, double y, double z) {
298 atomicDoubleArray[0].set(threadID, index, x);
299 atomicDoubleArray[1].set(threadID, index, y);
300 atomicDoubleArray[2].set(threadID, index, z);
301 }
302
303
304
305
306
307
308
309
310 public void set(int threadID, int index, Double3 d3) {
311 atomicDoubleArray[0].set(threadID, index, d3.x());
312 atomicDoubleArray[1].set(threadID, index, d3.y());
313 atomicDoubleArray[2].set(threadID, index, d3.z());
314 }
315
316
317
318
319
320
321
322
323
324
325 public void sub(int threadID, int index, double x, double y, double z) {
326 atomicDoubleArray[0].sub(threadID, index, x);
327 atomicDoubleArray[1].sub(threadID, index, y);
328 atomicDoubleArray[2].sub(threadID, index, z);
329 }
330
331
332
333
334
335
336
337
338 public void sub(int threadID, int index, Double3 d3) {
339 atomicDoubleArray[0].sub(threadID, index, d3.x());
340 atomicDoubleArray[1].sub(threadID, index, d3.y());
341 atomicDoubleArray[2].sub(threadID, index, d3.z());
342 }
343
344
345
346
347
348
349
350 public String toString(int index) {
351 String defaultLabel = " " + index + ": ";
352 return toString(index, defaultLabel);
353 }
354
355
356
357
358
359
360
361
362 public String toString(int index, String label) {
363 var d = new double[] {getX(index), getY(index), getZ(index)};
364 return DoubleMath.toString(d, label);
365 }
366
367
368
369
370
371
372 public String toString() {
373 StringBuilder sb = new StringBuilder();
374 for (int i = 0; i < atomicDoubleArray.length; i++) {
375 sb.append(toString(i)).append("\n");
376 }
377 return sb.toString();
378 }
379
380
381
382
383
384
385
386
387 public String toString(String label) {
388 StringBuilder sb = new StringBuilder();
389 if (label.contains("%d")) {
390 for (int i = 0; i < atomicDoubleArray[0].size(); i++) {
391 sb.append(toString(i, format(label, i))).append("\n");
392 }
393 } else {
394 for (int i = 0; i < atomicDoubleArray[0].size(); i++) {
395 sb.append(toString(i, label)).append("\n");
396 }
397 }
398 return sb.toString();
399 }
400
401
402
403
404 private enum Operation {
405 RESET,
406 REDUCE
407 }
408
409
410
411
412 private class ParallelRegion3D extends ParallelRegion {
413
414 private Operation operation;
415 private IntegerForLoop3D[] integerForLoop3D;
416
417
418
419
420 public ParallelRegion3D() {
421 operation = Operation.RESET;
422 }
423
424
425
426
427
428
429 public void setOperation(Operation operation) {
430 this.operation = operation;
431 }
432
433
434 @Override
435 public void start() {
436 int nThreads = getThreadCount();
437 if (integerForLoop3D == null) {
438 integerForLoop3D = new IntegerForLoop3D[nThreads];
439 }
440 }
441
442
443 @Override
444 public void run() throws Exception {
445 int threadID = getThreadIndex();
446 if (integerForLoop3D[threadID] == null) {
447 integerForLoop3D[threadID] = new IntegerForLoop3D();
448 }
449 int size = atomicDoubleArray[0].size();
450 execute(0, size - 1, integerForLoop3D[threadID]);
451 }
452
453
454
455
456 private class IntegerForLoop3D extends IntegerForLoop {
457
458
459 @Override
460 public void run(int lb, int ub) {
461 int threadID = getThreadIndex();
462 switch (operation) {
463 case RESET -> reset(threadID, lb, ub);
464 case REDUCE -> reduce(lb, ub);
465 }
466 }
467 }
468 }
469
470
471 }