View Javadoc
1   // ******************************************************************************
2   //
3   // Title:       Force Field X.
4   // Description: Force Field X - Software for Molecular Biophysics.
5   // Copyright:   Copyright (c) Michael J. Schnieders 2001-2024.
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.algorithms.optimize.manybody;
39  
40  import static java.lang.Double.isFinite;
41  import static java.lang.String.format;
42  
43  import edu.rit.pj.IntegerForLoop;
44  import edu.rit.pj.ParallelRegion;
45  import edu.rit.pj.reduction.SharedDouble;
46  import ffx.algorithms.optimize.RotamerOptimization;
47  import ffx.potential.bonded.Residue;
48  import java.util.ArrayList;
49  import java.util.Arrays;
50  import java.util.logging.Level;
51  import java.util.logging.Logger;
52  import java.util.stream.IntStream;
53  
54  public class GoldsteinPairRegion extends ParallelRegion {
55  
56    private static final Logger logger = Logger.getLogger(GoldsteinPairRegion.class.getName());
57  
58    private RotamerOptimization rotamerOptimization;
59    private Residue[] residues;
60    private int i, riA, rjC;
61    private int j, riB, rjD;
62    private int[] possK;
63    private int nK;
64    private final GoldsteinRotamerPairLoop[] goldsteinRotamerPairLoop;
65    private final SharedDouble sharedSumOverK = new SharedDouble();
66    private ArrayList<Residue> blockedResidues;
67  
68    public GoldsteinPairRegion(int nThreads) {
69      goldsteinRotamerPairLoop = new GoldsteinRotamerPairLoop[nThreads];
70    }
71  
72    public void finish() {
73      for (GoldsteinRotamerPairLoop rotamerPairLoop : goldsteinRotamerPairLoop) {
74        blockedResidues.addAll(rotamerPairLoop.blockedResidues);
75      }
76    }
77  
78    public ArrayList<Residue> getMissedResidues() {
79      return blockedResidues;
80    }
81  
82    public double getSumOverK() {
83      return sharedSumOverK.get();
84    }
85  
86    /**
87     * Initializes a ParallelRegion to attempt the elimination of riA,rjC by riB,rjD.
88     *
89     * @param residues The residue array.
90     * @param i First residue of the pair.
91     * @param riA First member of the pair to attempt eliminating.
92     * @param riB First member of the pair to try eliminating by.
93     * @param j Second residue of the pair.
94     * @param rjC Second member of the pair to attempt eliminating.
95     * @param rjD Second member of the pair to try eliminating by.
96     * @param bidiResNeighbors All interaction partners of a Residue, including prior residues
97     * @param rotamerOptimization RotamerOptimization instance.
98     */
99    public void init(Residue[] residues, int i, int riA, int riB, int j, int rjC, int rjD,
100       int[][] bidiResNeighbors, RotamerOptimization rotamerOptimization) {
101     this.residues = residues;
102     this.i = i;
103     this.riA = riA;
104     this.riB = riB;
105     this.j = j;
106     this.rjC = rjC;
107     this.rjD = rjD;
108     this.rotamerOptimization = rotamerOptimization;
109     int[] nI = bidiResNeighbors[i];
110     int[] nJ = bidiResNeighbors[j];
111     IntStream kStream = IntStream.concat(Arrays.stream(nI), Arrays.stream(nJ));
112     possK = kStream.distinct().filter(k -> (k != i && k != j)).sorted().toArray();
113     nK = possK.length;
114   }
115 
116   @Override
117   public void run() {
118     int threadID = getThreadIndex();
119     if (goldsteinRotamerPairLoop[threadID] == null) {
120       goldsteinRotamerPairLoop[threadID] = new GoldsteinRotamerPairLoop();
121     }
122     try {
123       execute(0, nK - 1, goldsteinRotamerPairLoop[threadID]);
124     } catch (Exception e) {
125       logger.log(Level.WARNING, " Exception in GoldsteinPairRegion.", e);
126     }
127   }
128 
129   public void start() {
130     sharedSumOverK.set(0.0);
131     blockedResidues = new ArrayList<>();
132   }
133 
134   private class GoldsteinRotamerPairLoop extends IntegerForLoop {
135 
136     double sumOverK;
137     ArrayList<Residue> blockedResidues;
138 
139     @Override
140     public void finish() {
141       sharedSumOverK.addAndGet(sumOverK);
142     }
143 
144     @Override
145     public void run(int lb, int ub) {
146       if (blockedResidues.isEmpty()) {
147         double locSumOverK = rotamerOptimization.goldsteinPairSumOverK(residues, lb, ub, i, riA, riB,
148             j, rjC, rjD, blockedResidues, possK);
149         // Should be redundant checks.
150         if (isFinite(locSumOverK) && blockedResidues.isEmpty()) {
151           sumOverK += locSumOverK;
152         } else {
153           sumOverK = 0;
154         }
155       } else {
156         rotamerOptimization.logIfRank0(
157             format(" Skipping %d to %d because we cannot eliminate", lb, ub), Level.FINE);
158       }
159     }
160 
161     @Override
162     public void start() {
163       sumOverK = 0.0;
164       blockedResidues = new ArrayList<>();
165     }
166   }
167 }