View Javadoc
1   package ffx.algorithms.thermodynamics;
2   
3   import static edu.rit.mp.DoubleBuf.buffer;
4   import static java.lang.String.format;
5   
6   import edu.rit.mp.DoubleBuf;
7   import edu.rit.pj.Comm;
8   import ffx.algorithms.thermodynamics.OrthogonalSpaceTempering.Histogram;
9   import java.io.IOException;
10  import java.util.logging.Level;
11  import java.util.logging.Logger;
12  
13  /**
14   * Synchronous (blocking) communication of OST counts.
15   *
16   * @author Michael J. Schnieders
17   * @since 1.0
18   */
19  public class SendSynchronous {
20  
21    private static final Logger logger = Logger.getLogger(SendSynchronous.class.getName());
22  
23    /** Parallel Java world communicator. */
24    protected final Comm world = Comm.world();
25    /** Rank of this process. */
26    protected final int rank = world.rank();
27    /** Number of processes. */
28    private final int numProc = world.size();
29    /**
30     * The counts array stores [Lambda, dU/dL, temper] for each process. Therefore, the array is of
31     * size [numProc][3].
32     *
33     * <p>Each 3 entry array must be wrapped inside a Parallel Java DoubleBuf for the All-Gather
34     * communication calls.
35     */
36    private final double[][] counts;
37    /**
38     * myCounts is a convenience pointer for this process to counts[rank].
39     */
40    private final double[] myCounts;
41    /**
42     * countsBuf wraps the counts arrays for each process.
43     */
44    private final DoubleBuf[] countsBuf;
45    /**
46     * myCountsBuf is a convenience pointer for this process to countsBuf[rank].
47     */
48    private final DoubleBuf myCountsBuf;
49    /**
50     * The histograms to update.
51     */
52    private Histogram[] histograms;
53    /**
54     * Map from ranks to histograms.
55     */
56    private int[] rankToHistogramMap;
57  
58    /**
59     * Synchronous Communication Constructor.
60     *
61     * @param histograms An array of Bias Histograms.
62     * @param rankToHistogramMap A map from process rank to Histogram.
63     */
64    public SendSynchronous(Histogram[] histograms, int[] rankToHistogramMap) {
65      counts = new double[numProc][3];
66      countsBuf = new DoubleBuf[numProc];
67      for (int i = 0; i < numProc; i++) {
68        countsBuf[i] = buffer(counts[i]);
69      }
70      myCounts = counts[rank];
71      myCountsBuf = countsBuf[rank];
72  
73      this.histograms = histograms;
74      this.rankToHistogramMap = rankToHistogramMap;
75    }
76  
77    public int getHistogramIndex() {
78      return rankToHistogramMap[rank];
79    }
80  
81    /**
82     * Send an OST count to all other processes while also receiving an OST count from all other
83     * processes.
84     *
85     * @param lambda Current value of lambda.
86     * @param dUdL Current value of dU/dL.
87     * @param temperingWeight Current value of the temperingWeight.
88     */
89    public void send(double lambda, double dUdL, double temperingWeight) {
90      // All-Gather counts from each walker.
91      myCounts[0] = lambda;
92      myCounts[1] = dUdL;
93      myCounts[2] = temperingWeight;
94      try {
95        world.allGather(myCountsBuf, countsBuf);
96      } catch (IOException ex) {
97        String message = " Multi-walker OST allGather failed.";
98        logger.log(Level.SEVERE, message, ex);
99      }
100 
101     // Increment the Recursion Kernel(s) based on the input of each walker.
102     for (int i = 0; i < numProc; i++) {
103 
104       int his = rankToHistogramMap[i];
105       Histogram currentHistogram = histograms[his];
106 
107       // Only include this walkers bias.
108       if (currentHistogram.getIndependentWalkers() && i != rank) {
109         continue;
110       }
111 
112       double walkerLambda = counts[i][0];
113       double walkerdUdL = counts[i][1];
114       double weight = counts[i][2];
115 
116       currentHistogram.setLastReceivedLambda(walkerLambda);
117       currentHistogram.setLastReceiveddUdL(walkerdUdL);
118 
119       boolean resetStatistics = currentHistogram.getResetStatistics();
120       double lambdaResetValue = currentHistogram.getLambdaResetValue();
121       if (resetStatistics && walkerLambda > lambdaResetValue) {
122         currentHistogram.allocateRecursionKernel();
123         logger.info(format(" Cleared OST histogram (Lambda = %6.4f).", walkerLambda));
124       }
125 
126       currentHistogram.addToRecursionKernelValue(walkerLambda, walkerdUdL, weight);
127     }
128   }
129 
130   /**
131    * Update the synchronous communication histograms.
132    *
133    * @param histograms Histograms in use.
134    * @param rankToHistogramMap Map from rank to histogram.
135    */
136   public void setHistograms(Histogram[] histograms, int[] rankToHistogramMap) {
137     this.histograms = histograms;
138     this.rankToHistogramMap = rankToHistogramMap;
139   }
140 
141   /**
142    * Update the map of rank-to-histogram.
143    *
144    * @param updatedRankToHisto Updated rank-to-histogram mappings.
145    */
146   public void updateRanks(int[] updatedRankToHisto) {
147     assert updatedRankToHisto.length == rankToHistogramMap.length;
148     System.arraycopy(updatedRankToHisto, 0, rankToHistogramMap, 0, rankToHistogramMap.length);
149   }
150 }