1 //-----------------------------------------------------------------------bl-
2 //--------------------------------------------------------------------------
3 //
4 // QUESO - a library to support the Quantification of Uncertainty
5 // for Estimation, Simulation and Optimization
6 //
7 // Copyright (C) 2008-2017 The PECOS Development Team
8 //
9 // This library is free software; you can redistribute it and/or
10 // modify it under the terms of the Version 2.1 GNU Lesser General
11 // Public License as published by the Free Software Foundation.
12 //
13 // This library is distributed in the hope that it will be useful,
14 // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 // Lesser General Public License for more details.
17 //
18 // You should have received a copy of the GNU Lesser General Public
19 // License along with this library; if not, write to the Free Software
20 // Foundation, Inc. 51 Franklin Street, Fifth Floor,
21 // Boston, MA  02110-1301  USA
22 //
23 //-----------------------------------------------------------------------el-
24 
25 #include <queso/VectorFunctionSynchronizer.h>
26 #include <queso/GslVector.h>
27 #include <queso/GslMatrix.h>
28 
29 namespace QUESO {
30 
31 // Default constructor -----------------------------
32 template <class P_V, class P_M, class Q_V, class Q_M>
VectorFunctionSynchronizer(const BaseVectorFunction<P_V,P_M,Q_V,Q_M> & inputFunction,const P_V & auxPVec,const Q_V & auxQVec)33 VectorFunctionSynchronizer<P_V,P_M,Q_V,Q_M>::VectorFunctionSynchronizer(
34   const BaseVectorFunction<P_V,P_M,Q_V,Q_M>& inputFunction,
35   const P_V&                                        auxPVec,
36   const Q_V&                                        auxQVec)
37   :
38   m_env           (inputFunction.domainSet().env()),
39   m_vectorFunction(inputFunction),
40   m_auxPVec       (auxPVec),
41   m_auxQVec       (auxQVec)
42 {
43 }
44 
45 // Destructor ---------------------------------------
46 template <class P_V, class P_M, class Q_V, class Q_M>
~VectorFunctionSynchronizer()47 VectorFunctionSynchronizer<P_V,P_M,Q_V,Q_M>::~VectorFunctionSynchronizer()
48 {
49 }
50 // Math methods -------------------------------------
51 template<class P_V, class P_M, class Q_V, class Q_M>
52 const VectorSet<P_V,P_M>&
domainSet()53 VectorFunctionSynchronizer<P_V,P_M,Q_V,Q_M>::domainSet() const
54 {
55   return m_vectorFunction.domainSet();
56 }
57 
58 // Sync methods -------------------------------------
59 template <class P_V, class P_M, class Q_V, class Q_M>
60 void
callFunction(const P_V * vecValues,const P_V * vecDirection,Q_V * imageVector,DistArray<P_V * > * gradVectors,DistArray<P_M * > * hessianMatrices,DistArray<P_V * > * hessianEffects)61 VectorFunctionSynchronizer<P_V,P_M,Q_V,Q_M>::callFunction(
62   const P_V*                    vecValues,
63   const P_V*                    vecDirection,
64         Q_V*                    imageVector,
65         DistArray<P_V*>* gradVectors,     // Yes, 'P_V'
66         DistArray<P_M*>* hessianMatrices, // Yes, 'P_M'
67         DistArray<P_V*>* hessianEffects) const
68 {
69   if ((m_env.numSubEnvironments() < (unsigned int) m_env.fullComm().NumProc()) &&
70       (m_auxPVec.numOfProcsForStorage() == 1                                 ) &&
71       (m_auxQVec.numOfProcsForStorage() == 1                                 )) {
72     bool stayInRoutine = true;
73     do {
74       const P_V*                    internalValues    = NULL;
75       const P_V*                    internalDirection = NULL;
76             Q_V*                    internalImageVec  = NULL;
77             DistArray<P_V*>* internalGrads     = NULL; // Yes, 'P_V'
78             DistArray<P_M*>* internalHessians  = NULL; // Yes, 'P_M'
79             DistArray<P_V*>* internalEffects   = NULL;
80 
81       /////////////////////////////////////////////////
82       // Broadcast 1 of 3
83       /////////////////////////////////////////////////
84       // bufferChar[0] = '0' or '1' (vecValues       is NULL or not)
85       // bufferChar[1] = '0' or '1' (vecDirection    is NULL or not)
86       // bufferChar[2] = '0' or '1' (imageVector     is NULL or not)
87       // bufferChar[3] = '0' or '1' (gradVectors     is NULL or not)
88       // bufferChar[4] = '0' or '1' (hessianMatrices is NULL or not)
89       // bufferChar[5] = '0' or '1' (hessianEffects  is NULL or not)
90       std::vector<char> bufferChar(6,'0');
91 
92       if (m_env.subRank() == 0) {
93         if ((vecValues != NULL)) queso_require_msg(imageVector, "imageVector should not be NULL");
94         internalValues    = vecValues;
95         internalDirection = vecDirection;
96         internalImageVec  = imageVector;
97         internalGrads     = gradVectors;
98         internalHessians  = hessianMatrices;
99         internalEffects   = hessianEffects;
100 
101         if (internalValues    != NULL) bufferChar[0] = '1';
102         if (internalDirection != NULL) bufferChar[1] = '1';
103         if (internalImageVec  != NULL) bufferChar[2] = '1';
104         if (internalGrads     != NULL) bufferChar[3] = '1';
105         if (internalHessians  != NULL) bufferChar[4] = '1';
106         if (internalEffects   != NULL) bufferChar[5] = '1';
107       }
108 
109       m_env.subComm().syncPrintDebugMsg("In VectorFunctionSynchronizer<V,M>::callFunction(), just before char Bcast()",3,3000000);
110       //if (m_env.subId() != 0) while (true) sleep(1);
111 
112       int count = (int) bufferChar.size();
113       m_env.subComm().Bcast((void *) &bufferChar[0], count, RawValue_MPI_CHAR, 0,
114                             "VectorFunctionSynchronizer<P_V,P_M,Q_V,Q_M>::callFunction()",
115                             "failed broadcast 1 of 3");
116 
117       if (bufferChar[0] == '1') {
118         ///////////////////////////////////////////////
119         // Broadcast 2 of 3
120         ///////////////////////////////////////////////
121 
122         // bufferDouble[0...] = contents for (eventual) vecValues
123         std::vector<double> bufferDouble(m_auxPVec.sizeLocal(),0);
124 
125         if (m_env.subRank() == 0) {
126           for (unsigned int i = 0; i < internalValues->sizeLocal(); ++i) {
127             bufferDouble[i] = (*internalValues)[i];
128           }
129         }
130 
131         count = (int) bufferDouble.size();
132         m_env.subComm().Bcast((void *) &bufferDouble[0], count, RawValue_MPI_DOUBLE, 0,
133                               "VectorFunctionSynchronizer<P_V,P_M,Q_V,Q_M>::callFunction()",
134                               "failed broadcast 2 of 3");
135 
136         if (m_env.subRank() != 0) {
137           P_V tmpPVec(m_auxPVec);
138           for (unsigned int i = 0; i < tmpPVec.sizeLocal(); ++i) {
139             tmpPVec[i] = bufferDouble[i];
140           }
141           internalValues = new P_V(tmpPVec);
142         }
143 
144         if (bufferChar[1] == '1') {
145           /////////////////////////////////////////////
146           // Broadcast 3 of 3
147           /////////////////////////////////////////////
148           // bufferDouble[0...] = contents for (eventual) vecDirection
149 
150           if (m_env.subRank() == 0) {
151             for (unsigned int i = 0; i < internalDirection->sizeLocal(); ++i) {
152               bufferDouble[i] = (*internalDirection)[i];
153             }
154           }
155 
156           count = (int) bufferDouble.size();
157           m_env.subComm().Bcast((void *) &bufferDouble[0], count, RawValue_MPI_DOUBLE, 0,
158                                 "VectorFunctionSynchronizer<P_V,P_M,Q_V,Q_M>::callFunction()",
159                                 "failed broadcast 3 of 3");
160 
161           if (m_env.subRank() != 0) {
162             P_V tmpPVec(m_auxPVec);
163             for (unsigned int i = 0; i < tmpPVec.sizeLocal(); ++i) {
164               tmpPVec[i] = bufferDouble[i];
165             }
166             internalDirection = new P_V(tmpPVec);
167           }
168         }
169 
170         ///////////////////////////////////////////////
171         // All processors now call 'vectorFunction()'
172         ///////////////////////////////////////////////
173         if (m_env.subRank() != 0) {
174           if (bufferChar[2] == '1') internalImageVec = new Q_V(m_auxQVec);
175         //if (bufferChar[3] == '1') internalGrads    = new P_V(m_auxPVec);
176         //if (bufferChar[4] == '1') internalHessians = new P_M(m_auxPVec);
177         //if (bufferChar[5] == '1') internalEffects  = new P_V(m_auxPVec);
178         }
179 
180         m_env.subComm().Barrier();
181         m_vectorFunction.compute(*internalValues,
182                                  internalDirection,
183                                  *internalImageVec,
184                                  internalGrads,
185                                  internalHessians,
186                                  internalEffects);
187       }
188 
189       /////////////////////////////////////////////////
190       // Prepare to exit routine or to stay in it
191       /////////////////////////////////////////////////
192       if (m_env.subRank() == 0) {
193         stayInRoutine = false; // Always for processor 0
194       }
195       else {
196         if (internalValues    != NULL) delete internalValues;
197         if (internalDirection != NULL) delete internalDirection;
198         if (internalImageVec  != NULL) delete internalImageVec;
199       //if (internalGrads     != NULL) delete internalGrads;
200       //if (internalHessians  != NULL) delete internalHessians;
201       //if (internalEffects   != NULL) delete internalEffects;
202 
203         stayInRoutine = (vecValues == NULL) && (bufferChar[0] == '1');
204       }
205     } while (stayInRoutine);
206   }
207   else {
208     queso_require_msg(!((vecValues == NULL) || (imageVector == NULL)), "Neither vecValues nor imageVector should not be NULL");
209     queso_require_equal_to_msg(m_auxPVec.numOfProcsForStorage(), m_auxQVec.numOfProcsForStorage(), "Number of processors required for storage should be the same");
210 
211     m_env.subComm().Barrier();
212     m_vectorFunction.compute(*vecValues,
213                              vecDirection,
214                              *imageVector,
215                              gradVectors,
216                              hessianMatrices,
217                              hessianEffects);
218   }
219 
220   return;
221 }
222 
223 }  // End namespace QUESO
224 
225 template class QUESO::VectorFunctionSynchronizer<QUESO::GslVector, QUESO::GslMatrix, QUESO::GslVector, QUESO::GslMatrix>;
226