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.pme;
39
40 import edu.rit.pj.IntegerForLoop;
41 import edu.rit.pj.IntegerSchedule;
42 import edu.rit.pj.ParallelRegion;
43 import edu.rit.pj.ParallelTeam;
44 import ffx.crystal.Crystal;
45 import ffx.crystal.SymOp;
46 import ffx.potential.bonded.Atom;
47
48 import java.util.List;
49 import java.util.logging.Level;
50 import java.util.logging.Logger;
51
52 /**
53 * Parallel expansion of the asymmetric unit induced dipoles to symmetry mates by applying symmetry
54 * operator rotation matrices.
55 *
56 * @author Michael J. Schnieders
57 * @since 1.0
58 */
59 public class ExpandInducedDipolesRegion extends ParallelRegion {
60
61 private static final Logger logger = Logger.getLogger(ExpandInducedDipolesRegion.class.getName());
62 private final ExpandInducedDipoleLoop[] expandInducedDipoleLoop;
63 /** Dimensions of [nsymm][nAtoms][3] */
64 public double[][][] inducedDipole;
65
66 public double[][][] inducedDipoleCR;
67 /** An ordered array of atoms in the system. */
68 private Atom[] atoms;
69 /** Unit cell and spacegroup information. */
70 private Crystal crystal;
71
72 public ExpandInducedDipolesRegion(int maxThreads) {
73 expandInducedDipoleLoop = new ExpandInducedDipoleLoop[maxThreads];
74 for (int i = 0; i < maxThreads; i++) {
75 expandInducedDipoleLoop[i] = new ExpandInducedDipoleLoop();
76 }
77 }
78
79 /**
80 * Execute the ExpandInducedDipolesRegion with the passed ParallelTeam.
81 *
82 * @param parallelTeam The ParallelTeam instance to execute with.
83 */
84 public void executeWith(ParallelTeam parallelTeam) {
85 try {
86 parallelTeam.execute(this);
87 } catch (Exception e) {
88 String message = " Exception expanding induced dipoles.\n";
89 logger.log(Level.WARNING, message, e);
90 }
91 }
92
93 public void init(
94 Atom[] atoms, Crystal crystal, double[][][] inducedDipole, double[][][] inducedDipoleCR) {
95 // Input
96 this.atoms = atoms;
97 this.crystal = crystal;
98 // Output
99 this.inducedDipole = inducedDipole;
100 this.inducedDipoleCR = inducedDipoleCR;
101 }
102
103 @Override
104 public void run() {
105 try {
106 int nAtoms = atoms.length;
107 execute(0, nAtoms - 1, expandInducedDipoleLoop[getThreadIndex()]);
108 } catch (Exception e) {
109 String message =
110 "Fatal exception expanding coordinates in thread: " + getThreadIndex() + "\n";
111 logger.log(Level.SEVERE, message, e);
112 }
113 }
114
115 private class ExpandInducedDipoleLoop extends IntegerForLoop {
116
117 @Override
118 public void run(int lb, int ub) {
119 List<SymOp> symOps = crystal.spaceGroup.symOps;
120 int nSymm = symOps.size();
121 for (int s = 1; s < nSymm; s++) {
122 SymOp symOp = symOps.get(s);
123 for (int ii = lb; ii <= ub; ii++) {
124 crystal.applySymRot(inducedDipole[0][ii], inducedDipole[s][ii], symOp);
125 crystal.applySymRot(inducedDipoleCR[0][ii], inducedDipoleCR[s][ii], symOp);
126 }
127 }
128 }
129
130 @Override
131 public IntegerSchedule schedule() {
132 return IntegerSchedule.fixed();
133 }
134 }
135 }