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