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