queso-0.55.0
InterpolationSurrogateBuilder.C
Go to the documentation of this file.
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-2015 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 // This class
26 #include <queso/InterpolationSurrogateBuilder.h>
27 
28 // QUESO
29 #include <queso/MpiComm.h>
30 #include <queso/GslVector.h>
31 #include <queso/GslMatrix.h>
32 #include <queso/InterpolationSurrogateHelper.h>
33 #include <queso/StreamUtilities.h>
34 
35 // C++
36 #include <numeric>
37 
38 namespace QUESO
39 {
40  template<class V, class M>
42  : SurrogateBuilderBase<V>(),
43  m_data(data),
44  m_njobs(this->get_default_data().get_paramDomain().env().numSubEnvironments(), 0)
45  {
46  this->partition_work();
47  }
48 
49  template<class V, class M>
51  {
52  // Convenience
53  unsigned int n_values = this->get_default_data().n_values();
54  unsigned int n_workers = this->get_default_data().get_paramDomain().env().numSubEnvironments();
55 
56  unsigned int n_jobs = n_values/n_workers;
57  unsigned int n_leftover = this->get_default_data().n_values() % n_workers;
58 
59  /* If the number of values is evenly divisible over all workers,
60  then everyone gets the same amount work */
61  if( n_leftover == 0 )
62  {
63  for(unsigned int n = 0; n < n_workers; n++)
64  this->m_njobs[n] = n_jobs;
65  }
66  /* Otherwise, some workers get more work than others*/
67  else
68  {
69  for(unsigned int n = 0; n < n_workers; n++)
70  {
71  if( n < n_leftover )
72  this->m_njobs[n] = n_jobs+1;
73  else
74  this->m_njobs[n] = n_jobs;
75  }
76  }
77 
78  // Sanity check
79  queso_assert_equal_to( n_values, std::accumulate( m_njobs.begin(), m_njobs.end(), 0 ) );
80  }
81 
82  template<class V, class M>
84  {
85  unsigned int n_begin, n_end;
86  this->set_work_bounds( n_begin, n_end );
87 
88  // Cache each processors work, then we only need to do 1 Allgather
89  std::vector<unsigned int> local_n(n_end-n_begin);
90 
91  // We need to cache (n_end-n_begin) values for each dataset,
92  std::vector<std::vector<double> > local_values(this->m_data.size());
93  for( std::vector<std::vector<double> >::iterator it = local_values.begin();
94  it != local_values.end(); ++it )
95  it->resize(n_end-n_begin);
96 
97  unsigned int count = 0;
98 
99  // vector to store current domain value
100  V domain_vector(this->get_default_data().get_paramDomain().vectorSpace().zeroVector());
101 
102  // vector to store values evaluated at the current domain_vector
103  std::vector<double> values(this->m_data.size());
104 
105  for( unsigned int n = n_begin; n < n_end; n++ )
106  {
107  this->set_domain_vector( n, domain_vector );
108 
109  this->evaluate_model( domain_vector, values );
110 
111  local_n[count] = n;
112 
113  for( unsigned int s = 0; s < this->m_data.size(); s++ )
114  local_values[s][count] = values[s];
115 
116  count += 1;
117  }
118 
119  /* Sync all the locally computed values between the subenvironments
120  so all processes have all the computed values. We need to sync
121  values for every data set. */
122  for( unsigned int s = 0; s < this->m_data.size(); s++ )
123  this->sync_data( local_n, local_values[s], this->m_data.get_dataset(s) );
124  }
125 
126  template<class V, class M>
127  void InterpolationSurrogateBuilder<V,M>::set_work_bounds( unsigned int& n_begin, unsigned int& n_end ) const
128  {
129  unsigned int my_subid = this->get_default_data().get_paramDomain().env().subId();
130 
131  /* Starting index will be the sum of the all the previous num jobs */
132  n_begin = 0;
133  for( unsigned int n = 0; n < my_subid; n++ )
134  n_begin += m_njobs[n];
135 
136  n_end = n_begin + m_njobs[my_subid];
137  }
138 
139  template<class V, class M>
140  void InterpolationSurrogateBuilder<V,M>::sync_data( std::vector<unsigned int>& local_n,
141  std::vector<double>& local_values,
143  {
144  // Only members of the inter0comm will do the communication of the local values
145  unsigned int my_subrank = data.get_paramDomain().env().subRank();
146 
147  if( my_subrank == 0 )
148  {
149  std::vector<double> all_values(data.n_values());
150 
151  std::vector<unsigned int> all_indices(data.n_values());
152 
153  std::vector<int> strides;
154  this->compute_strides( strides );
155 
156  const MpiComm& inter0comm = data.get_paramDomain().env().inter0Comm();
157 
160  inter0comm.template Gatherv<unsigned int>(&local_n[0], local_n.size(),
161  &all_indices[0], &m_njobs[0], &strides[0],
162  0 /*root*/, "InterpolationSurrogateBuilder::sync_data()",
163  "MpiComm::gatherv() failed!");
164 
165  inter0comm.template Gatherv<double>(&local_values[0],
166  local_values.size(), &all_values[0], &m_njobs[0], &strides[0],
167  0 /*root*/, "InterpolationSurrogateBuilder::sync_data()",
168  "MpiComm::gatherv() failed!");
169 
170  // Now set the values.
171  /* PB: Although we are guaranteed per-rank ordering of the data we gathered,
172  I'm not sure we can assume the same continuity of the inter0 ranks, i.e.
173  I'm not sure how QUESO ordered the inter0 ranks. So, we go ahead and
174  manually set the values. */
175  if( data.get_paramDomain().env().subRank() == 0 )
176  {
177  for( unsigned int n = 0; n < data.n_values(); n++ )
178  data.set_value( all_indices[n], all_values[n] );
179  }
180  }
181 
182  // Now broadcast the values data to all other processes
183  data.sync_values( 0 /*root*/);
184  }
185 
186  template<class V, class M>
187  void InterpolationSurrogateBuilder<V,M>::set_domain_vector( unsigned int n, V& domain_vector ) const
188  {
189  // Convert global index n to local coordinates in each dimension
190  std::vector<unsigned int> indices(this->get_default_data().dim());
191  InterpolationSurrogateHelper::globalToCoord( n, this->get_default_data().get_n_points(), indices );
192 
193  // Use indices to get x coordinates and populate domain_vector
194  for( unsigned int d = 0; d < this->get_default_data().dim(); d++ )
195  {
196  domain_vector[d] = this->get_default_data().get_x( d, indices[d] );
197  }
198  }
199 
200  template<class V, class M>
201  void InterpolationSurrogateBuilder<V,M>::compute_strides( std::vector<int>& strides ) const
202  {
203  unsigned int n_subenvs = this->get_default_data().get_paramDomain().env().numSubEnvironments();
204 
205  strides.resize(n_subenvs);
206 
207  // Don't stride the first entry
208  strides[0] = 0;
209 
210  int stride = 0;
211  for( unsigned int n = 1; n < n_subenvs; n++ )
212  {
213  // The stride is measured agaisnt the beginning of the buffer
214  // We want things packed tightly together so just stride
215  // by the number of entries from the previous group.
216  stride += this->m_njobs[n-1];
217  strides[n] = stride;
218  }
219  }
220 
221 } // end namespace QUESO
222 
223 // Instantiate
void sync_data(std::vector< unsigned int > &local_n, std::vector< double > &local_values, InterpolationSurrogateData< V, M > &data)
Take the local values computed from each process and communicate.
void compute_strides(std::vector< int > &strides) const
Helper function to compute strides needed for MPI_Gatherv.
int dim
Definition: ann2fig.cpp:81
#define queso_assert_equal_to(expr1, expr2)
Definition: asserts.h:149
const BoxSubset< V, M > & get_paramDomain() const
that you receive source code or can get it if you want it
Definition: License.txt:41
void partition_work()
Partition the workload of model evaluations across the subenvironments.
static void globalToCoord(unsigned int global, const std::vector< unsigned int > &n_points, std::vector< unsigned int > &coord_indices)
Inverse of coordToGlobal map.
Build interpolation-based surrogate.
void set_work_bounds(unsigned int &n_begin, unsigned int &n_end) const
Set the starting and ending global indices for the current subenvironment.
Container class for multiple, consistent InterpolationSurrogateData objects.
void sync_values(unsigned int root)
Sync values across all processors from root processor.
The QUESO MPI Communicator Class.
Definition: MpiComm.h:203
void set_value(unsigned int n, double value)
Base class for builders of surrogates.
void build_values()
Execute the user&#39;s model and populate m_values for the given n_points.
void set_domain_vector(unsigned int n, V &domain_vector) const
Provide the spatial coordinates for the global index n.

Generated on Fri Jun 17 2016 14:17:42 for queso-0.55.0 by  doxygen 1.8.5