1 /*  _______________________________________________________________________
2 
3     DAKOTA: Design Analysis Kit for Optimization and Terascale Applications
4     Copyright 2014-2020 National Technology & Engineering Solutions of Sandia, LLC (NTESS).
5     This software is distributed under the GNU Lesser General Public License.
6     For more information, see the README file in the top Dakota directory.
7     _______________________________________________________________________ */
8 
9 //- Class:        SharedC3ApproxData
10 //- Description:  Base Class for C3 aprpoximation interface
11 //-
12 //- Owner:        Alex Gorodetsky
13 
14 #ifndef SHARED_C3_APPROX_DATA_H
15 #define SHARED_C3_APPROX_DATA_H
16 
17 #include "SharedApproxData.hpp"
18 #include "SharedRegressOrthogPolyApproxData.hpp"
19 #include "dakota_c3_include.hpp"
20 
21 namespace Dakota {
22 
23 
24 /// Derived approximation class for global basis polynomials.
25 
26 /** The SharedC3ApproxData class provides a global approximation
27     based on basis polynomials.  This includes orthogonal polynomials
28     used for polynomial chaos expansions and interpolation polynomials
29     used for stochastic collocation. */
30 
31 class SharedC3ApproxData: public SharedApproxData
32 {
33   //
34   //- Heading: Friends
35   //
36 
37   friend class C3Approximation;
38 
39 public:
40 
41   //
42   //- Heading: Constructor and destructor
43   //
44 
45   /// default constructor
46   SharedC3ApproxData();
47   /// standard ProblemDescDB-driven constructor
48   SharedC3ApproxData(ProblemDescDB& problem_db, size_t num_vars);
49   /// on-the-fly constructor (no problem DB)
50   SharedC3ApproxData(const String& approx_type,
51                      const UShortArray& approx_order, size_t num_vars,
52                      short data_order, short output_level);
53   /// destructor
54   ~SharedC3ApproxData();
55 
56   //
57   //- Heading: Member functions
58   //
59 
60   // *** IMPORTANT NOTE: these regression_size() implementations utilize shared
61   // *** before-build input specification (subject to increment/decrement), not
62   // *** after-build per-QoI details (subject to CV adapt_rank/adapt_order)
63 
64   /// return number of FT unknowns given scalars: num vars, rank, order
65   static size_t regression_size(size_t num_v, size_t rank, size_t max_rank,
66 				const UShortArray& orders,
67 				unsigned short max_order);
68   /// return number of FT unknowns using start_rank(), max_rank(),
69   /// start_orders(), max_order()
70   size_t regression_size();
71   /// return number of FT unknowns using maximum rank, start_orders(),
72   /// max_order()
73   size_t max_rank_regression_size();
74   /// return number of FT unknowns using start_rank(), max_rank(), and
75   /// maximum basis order
76   size_t max_order_regression_size();
77   /// return number of FT unknowns using maxima for rank and basis order
78   size_t max_regression_size();
79 
80   /// set UShortArray attribute value based on identifier string
81   void set_parameter(String var, const UShortArray& val);
82   /// set unsigned short attribute value based on identifier string
83   void set_parameter(String var, unsigned short     val);
84   /// set size_t attribute value based on identifier string
85   void set_parameter(String var, size_t val);
86   /// set bool attribute value based on identifier string
87   void set_parameter(String var, bool   val);
88   /// set short attribute value based on identifier string
89   void set_parameter(String var, short  val);
90   /// set double attribute value based on identifier string
91   void set_parameter(String var, double val);
92   /// set int attribute value based on identifier string
93   void set_parameter(String var, int    val);
94 
95   /// set active UShortArray attribute value based on identifier string
96   void set_active_parameter(String var, const UShortArray& val);
97   /// set active unsigned short attribute value based on identifier string
98   void set_active_parameter(String var, unsigned short val);
99   /// set active size_t attribute value based on identifier string
100   void set_active_parameter(String var, size_t val);
101   /// set active int attribute value based on identifier string
102   void set_active_parameter(String var, int val);
103 
104   // set SharedOrthogPolyApproxData::basisTypes
105   //void basis_types(const ShortArray& basis_types);
106   // get SharedOrthogPolyApproxData::basisTypes
107   //const ShortArray& basis_types() const;
108 
109   /// return active start value for basis order
110   const UShortArray& start_orders() const;
111   /// return active start value for basis order (mutable)
112   UShortArray& start_orders();
113   /// return active maximum value for basis order
114   unsigned short max_order() const;
115   /// return active maximum value for basis order (mutable)
116   unsigned short& max_order();
117 
118   /// return active start value for expansion rank
119   size_t start_rank() const;
120   /// return active start value for expansion rank (mutable)
121   size_t& start_rank();
122   /// return active maximum value for expansion rank
123   size_t max_rank() const;
124   /// return active maximum value for expansion rank (mutable)
125   size_t& max_rank();
126 
127   // return c3AdvancementType
128   //short advancement_type() const;
129 
130   /// update oneApproxOpts with active basis orders after an order change
131   void update_basis();
132   /// update oneApproxOpts with passed basis orders after an order change
133   void update_basis(const UShortArray& start_orders, unsigned short max_order);
134   /// update oneApproxOpts for variable v with passed basis orders
135   void update_basis(size_t v, unsigned short start_order,
136 		    unsigned short max_order);
137 
138 protected:
139 
140   //
141   //- Heading: Virtual function redefinitions
142   //
143 
144   void active_model_key(const UShortArray& key);
145   //void clear_model_keys();
146 
147   void construct_basis(const Pecos::MultivariateDistribution& mv_dist);
148 
149   short discrepancy_type() const;
150 
151   // Activate as additional features (and basis types) come online
152 
153   //void update_basis_distribution_parameters(        // beyond STD_{NORMAL,
154   //  const Pecos::MultivariateDistribution& u_dist); //             UNIFORM}
155 
156   //void configuration_options(const Pecos::ExpansionConfigOptions& ec_options);
157   //void configuration_options(const Pecos::BasisConfigOptions&     bc_options);
158 
159   void random_variables_key(const BitArray& random_vars_key);
160 
161   //void refinement_statistics_mode(short stats_mode);
162 
163   //const Pecos::BitArrayULongMap& SharedApproxData::sobol_index_map();
164 
165   void build();
166   //void rebuild(); // defaults to build()
167 
168   void increment_order();
169   void decrement_order();
170 
171   void   pop(bool save_surr_data);
172   bool   push_available();
173   size_t push_index(const UShortArray& key);
174   void   post_push();
175 
176   void pre_combine();
177   //void post_combine();
178 
179   bool advancement_available();
180   void max_rank_advancement(bool r_advance);
181   void max_order_advancement(bool o_advance);
182 
183   //
184   //- Heading: Data
185   //
186 
187   // While these containers are shared across the QoI, some data now varies per
188   // QoI (for adapt_order). Per QoI data is pushed/pulled in C3Approx::build().
189   //
190   // lower level basis options
191   //std::vector<OpeOpts*> polyBasisOpts;
192   /// one-D approximation options (basis type, poly order, etc.)
193   std::vector<OneApproxOpts*> oneApproxOpts;
194   /// n-D approximation options, augmenting one-D options
195   MultiApproxOpts* multiApproxOpts;
196 
197   /// starting user specification for polynomial orders (from start_order
198   /// scalar plus anisotropic dimension preference)
199   UShortArray startOrders;
200   /// starting values for polynomial order (prior to adaptive refinement);
201   /// for each model key, there is an array of polynomial orders per variable
202   std::map<UShortArray, UShortArray> startOrdersMap;
203   /// user specification for increment in order used within adapt_order
204   unsigned short kickOrder;
205   /// maximum value for polynomial order from user spec
206   unsigned short maxOrder;
207   /// user specification for maximum order used within adapt_order;
208   /// usually a scalar specification but can be adapted per model key
209   /// for MAX_{ORDER,RANK_ORDER}_ADVANCEMENT refine types
210   std::map<UShortArray, unsigned short> maxOrderMap;
211   /// C3 FT can support CV over polynomial order in addition to adapt_rank
212   bool adaptOrder;
213 
214   /// polynomial basis order for combined expansion for each variable core
215   UShortArray combinedOrders;
216 
217   // the remaining data are separate as can be seen in C3Approximation::build()
218 
219   /// starting user specification for rank (not augmented by dimension
220   /// preference); Note: rank sequence spec is managed externally and becomes
221   /// reflected in startRank model index mapping
222   size_t startRank; // or SizetArray for start_rank_sequence spec
223   /// starting values for rank (note: adapt_rank currently covers refinement);
224   /// for each model index key, there is a scalar starting rank (recovered
225   /// rank in C3FnrainPtrs can vary per core/variable and per QoI)
226   std::map<UShortArray, size_t> startRankMap;
227   /// user specification for increment in rank used within adapt_rank
228   size_t kickRank;
229   /// scalar user specification for maximum allowable rank when adapting
230   size_t maxRank;
231   /// user specification for maximum rank used within adapt_rank;
232   /// usually a scalar specification but can be adapted per model key
233   /// for MAX_{RANK,RANK_ORDER}_ADVANCEMENT refine types
234   std::map<UShortArray, size_t> maxRankMap;
235   /// internal C3 adaptation that identifies the best rank representation
236   /// for a set of sample data based on cross validation
237   bool adaptRank;
238 
239   /// type of regression solver for forming FT approximation
240   short  regressType;
241   /// penalty parameter if regularized regression
242   double regressRegParam;
243   /// tolerance on regression solver
244   double solverTol;
245   /// tolerance for rounding (performing a truncation operation on a FT
246   /// expansion) within the regression solver
247   double solverRoundingTol;
248   /// tolerance for rounding (performing a truncation operation on a FT
249   /// expansion) when post-processing an expansion: computing products
250   /// for moments, combining expansions with c3axpy, etc.
251   double statsRoundingTol;
252   /// maximum number of iterations for regression solver
253   int maxSolverIterations;
254   /// maximum number of iterations for (future) cross iteration solver
255   int crossMaxIter;
256   /// C3 regression solver employs a random seed
257   int randomSeed;
258 
259   // a more general adaptive construction option, distinct from adapt_rank
260   //bool adaptConstruct; // inactive placeholder for now
261 
262   /// type of discrepancy calculation: additive, multiplicative, or both
263   short combineType;
264   /// type of multilevel discrepancy emulation: distinct or recursive
265   short discrepancyType;
266   /// type of multilevel strategy for sample allocation: ESTIMATOR_VARIANCE,
267   /// RANK_SAMPLING, GREEDY
268   short allocControl;
269   // indicates refinement based on active or combined statistics
270   //short refineStatsMode;
271   /// type of advancement strategy used in uniform refinement:
272   /// {START_ORDER,START_RANK,MAX_ORDER,MAX_RANK,MAX_RANK_ORDER}_ADVANCEMENT
273   short c3AdvancementType;
274 
275   /// flag indicating availability of rank advancement (accumulated from
276   /// C3Approximation::advancement_available())
277   std::map<UShortArray, bool> c3MaxRankAdvance;
278   /// flag indicating availability of order advancement (accumulated from
279   /// C3Approximation::advancement_available())
280   std::map<UShortArray, bool> c3MaxOrderAdvance;
281 
282   // key identifying the subset of build variables that can be treated
283   // as random, for purposes of computing statistics
284   //BitArray ranVarsKey; // stored locally rather than passed to library (Pecos)
285   /// indices for random subset when approximating in all-variables mode
286   SizetArray randomIndices;
287 
288   /// number of instances within the popped arrays (mostly a placeholder for
289   /// supporting push_available())
290   std::map<UShortArray, size_t> poppedCounts;
291 
292 private:
293 
294   //
295   //- Heading: Convenience functions
296   //
297 
298   //
299   //- Heading: Data
300   //
301 
302 };
303 
304 
SharedC3ApproxData()305 inline SharedC3ApproxData::SharedC3ApproxData()
306 { }
307 
308 
active_model_key(const UShortArray & key)309 inline void SharedC3ApproxData::active_model_key(const UShortArray& key)
310 {
311   // set activeKey and approxDataKeys
312   SharedApproxData::active_model_key(key);
313 
314   // these aren't used enough to warrant active iterators
315   bool form = false;
316   if (startOrdersMap.find(key) == startOrdersMap.end())
317     { startOrdersMap[key]      =  startOrders;  form = true; }
318   if (startRankMap.find(key)   == startRankMap.end())
319     { startRankMap[key]        =  startRank;    form = true; }
320   if (maxOrderMap.find(key)    == maxOrderMap.end())
321     { maxOrderMap[key]         =  maxOrder;     if (adaptOrder) form = true; }
322   if (maxRankMap.find(key)     == maxRankMap.end())
323     { maxRankMap[key]          =  maxRank;      if (adaptRank)  form = true; }
324 
325   // ensure approximation rebuild, when needed, in absence of sample increment
326   if (form) formUpdated[key] = true;
327 }
328 
329 
update_basis()330 inline void SharedC3ApproxData::update_basis()
331 { update_basis(start_orders(), max_order()); }
332 
333 
discrepancy_type() const334 inline short SharedC3ApproxData::discrepancy_type() const
335 { return discrepancyType; }
336 
337 
start_orders() const338 inline const UShortArray& SharedC3ApproxData::start_orders() const
339 {
340   std::map<UShortArray, UShortArray>::const_iterator cit
341     = startOrdersMap.find(activeKey);
342   return (cit == startOrdersMap.end()) ? startOrders : cit->second;
343 }
344 
345 
start_orders()346 inline UShortArray& SharedC3ApproxData::start_orders()
347 {
348   std::map<UShortArray, UShortArray>::iterator it
349     = startOrdersMap.find(activeKey);
350   return (it == startOrdersMap.end()) ? startOrders : it->second;
351 }
352 
353 
max_order() const354 inline unsigned short SharedC3ApproxData::max_order() const
355 {
356   std::map<UShortArray, unsigned short>::const_iterator cit
357     = maxOrderMap.find(activeKey);
358   return (cit == maxOrderMap.end()) ? maxOrder : cit->second;
359 }
360 
361 
max_order()362 inline unsigned short& SharedC3ApproxData::max_order()
363 {
364   std::map<UShortArray, unsigned short>::iterator it
365     = maxOrderMap.find(activeKey);
366   return (it == maxOrderMap.end()) ? maxOrder : it->second;
367 }
368 
369 
start_rank() const370 inline size_t SharedC3ApproxData::start_rank() const
371 {
372   std::map<UShortArray, size_t>::const_iterator cit
373     = startRankMap.find(activeKey);
374   return (cit == startRankMap.end()) ? startRank : cit->second;
375 }
376 
377 
start_rank()378 inline size_t& SharedC3ApproxData::start_rank()
379 {
380   std::map<UShortArray, size_t>::iterator it = startRankMap.find(activeKey);
381   return (it == startRankMap.end()) ? startRank : it->second;
382 }
383 
384 
max_rank() const385 inline size_t SharedC3ApproxData::max_rank() const
386 {
387   std::map<UShortArray, size_t>::const_iterator cit
388     = maxRankMap.find(activeKey);
389   return (cit == maxRankMap.end()) ? maxRank : cit->second;
390 }
391 
392 
max_rank()393 inline size_t& SharedC3ApproxData::max_rank()
394 {
395   std::map<UShortArray, size_t>::iterator it = maxRankMap.find(activeKey);
396   return (it == maxRankMap.end()) ? maxRank : it->second;
397 }
398 
399 
400 //inline short SharedC3ApproxData::advancement_type() const
401 //{ return c3AdvancementType; }
402 
403 
404 /** simplified estimation for scalar-valued rank and order (e.g., from
405     start rank/order user specification)
406 inline size_t SharedC3ApproxData::
407 regression_size(size_t num_v, size_t rank, size_t order)
408 {
409   // Each dimension has its own rank within the product of function cores.
410   // This fn estimates for the case where rank and order are either constant
411   // across dimensions or averaged into a scalar.
412   // > the first and last core contribute p*r terms
413   // > the middle cores contribute r*r*p terms
414   size_t p = order+1.;
415   switch (num_v) {
416   case 1:  return p;         break; // collapses to a 1D PCE
417   case 2:  return 2.*p*rank; break; // first and last core, no middle
418   default: return p*rank*(2. + (num_v-2)*rank); break; // first,last,middle
419   }
420 }
421 */
422 
423 
424 /** simplified estimation for scalar-valued rank and vector-valued order
425     (e.g., from start rank/start order/dimension pref user specification) */
426 inline size_t SharedC3ApproxData::
regression_size(size_t num_v,size_t rank,size_t max_rank,const UShortArray & orders,unsigned short max_order)427 regression_size(size_t num_v, size_t rank, size_t max_rank,
428 		const UShortArray& orders, unsigned short max_order)
429 {
430   // Each dimension has its own rank within the product of function cores.
431   // This fn estimates for the case where rank and order are either constant
432   // across dimensions or averaged into a scalar.
433   // > the first and last core contribute p*r terms
434   // > the middle cores contribute r*r*p terms
435   unsigned short p;
436   switch (num_v) {
437   case 1:
438     p = std::min(orders[0], max_order) + 1;
439     return p; break; // collapses to 1D PCE
440   default: { // first, last, and num_v-2 middle cores
441     size_t core, num_vm1 = num_v - 1, sum, r = std::min(rank, max_rank);
442     p = std::min(orders[0],       max_order) + 1;  sum  = p; // first
443     p = std::min(orders[num_vm1], max_order) + 1;  sum += p; // last
444     for (core=1; core<num_vm1; ++core) {
445       p = std::min(orders[core], max_order) + 1;
446       sum += r * p;  // num_v-2 middle cores
447     }
448     return sum * r;  break;
449   }
450   }
451 }
452 
453 
regression_size()454 inline size_t SharedC3ApproxData::regression_size()
455 {
456   return regression_size(numVars, start_rank(), max_rank(),
457 			 start_orders(), max_order());
458 
459   /* If max regression size logic were proliferated to non-refinement cases,
460      could automate max helpers below based on adapt{Rank,Order}:
461   size_t max_r = max_rank(), regress_r = (adaptRank) ? max_r : start_rank();
462   unsigned short max_o = max_order();
463   if (adaptOrder) {
464     UShortArray max_orders(numVars, max_o);// no dim_pref; adapt is isotropic
465     return regression_size(numVars, regress_r, max_r,   max_orders,   max_o);
466   }
467   else
468     return regression_size(numVars, regress_r, max_r, start_orders(), max_o);
469   */
470 }
471 
472 
max_rank_regression_size()473 inline size_t SharedC3ApproxData::max_rank_regression_size()
474 {
475   size_t max_r = max_rank();
476   return regression_size(numVars, max_r, max_r, start_orders(), max_order());
477 }
478 
479 
max_order_regression_size()480 inline size_t SharedC3ApproxData::max_order_regression_size()
481 {
482   //UShortArray max_orders; RealVector dim_pref;//isotropic for now: no XML spec
483   //NonDIntegration::dimension_preference_to_anisotropic_order(max_o,
484   //  dim_pref, numVars, max_orders);
485 
486   unsigned short max_o = max_order();
487   UShortArray max_orders(numVars, max_o);// no dim_pref; adaptOrder is isotropic
488 
489   return regression_size(numVars, start_rank(), max_rank(), max_orders, max_o);
490 }
491 
492 
max_regression_size()493 inline size_t SharedC3ApproxData::max_regression_size()
494 {
495   //UShortArray max_orders; RealVector dim_pref;//isotropic for now: no XML spec
496   //NonDIntegration::dimension_preference_to_anisotropic_order(max_o,
497   //  dim_pref, numVars, max_orders);
498 
499   size_t max_r = max_rank();  unsigned short max_o = max_order();
500   UShortArray max_orders(numVars, max_o);// no dim_pref; adaptOrder is isotropic
501 
502   return regression_size(numVars, max_r, max_r, max_orders, max_o);
503 }
504 
505 
max_rank_advancement(bool r_advance)506 inline void SharedC3ApproxData::max_rank_advancement(bool r_advance)
507 { c3MaxRankAdvance[activeKey] = r_advance; }
508 
509 
max_order_advancement(bool o_advance)510 inline void SharedC3ApproxData::max_order_advancement(bool o_advance)
511 { c3MaxOrderAdvance[activeKey] = o_advance; }
512 
513 
514 inline void SharedC3ApproxData::
set_parameter(String var,const UShortArray & val)515 set_parameter(String var, const UShortArray& val)
516 {
517   if (var.compare("start_order") == 0)         startOrders = val;
518   else Cerr << "Unrecognized C3 parameter: " << var << std::endl;
519 }
520 
521 
set_parameter(String var,unsigned short val)522 inline void SharedC3ApproxData::set_parameter(String var, unsigned short val)
523 {
524   if (var.compare("kick_order")     == 0)        kickOrder = val;
525   else if (var.compare("max_order") == 0)         maxOrder = val;
526   else Cerr << "Unrecognized C3 parameter: " << var << std::endl;
527 }
528 
529 
set_parameter(String var,size_t val)530 inline void SharedC3ApproxData::set_parameter(String var, size_t val)
531 {
532   if (var.compare("start_rank")     == 0)        startRank = val;
533   else if (var.compare("kick_rank") == 0)         kickRank = val;
534   else if (var.compare("max_rank")  == 0)          maxRank = val;
535   else Cerr << "Unrecognized C3 parameter: " << var << std::endl;
536 }
537 
538 
set_parameter(String var,bool val)539 inline void SharedC3ApproxData::set_parameter(String var, bool val)
540 {
541   if (var.compare("adapt_rank") == 0)           adaptRank  = val;
542   else if (var.compare("adapt_order") == 0)     adaptOrder = val;
543   else Cerr << "Unrecognized C3 parameter: " << var << std::endl;
544 }
545 
546 
set_parameter(String var,short val)547 inline void SharedC3ApproxData::set_parameter(String var, short val)
548 {
549   if      (var.compare("regress_type")      == 0)       regressType = val;
550   else if (var.compare("discrepancy_type")  == 0)   discrepancyType = val;
551   else if (var.compare("alloc_control")     == 0)      allocControl = val;
552   else if (var.compare("combine_type")      == 0)       combineType = val;
553   else if (var.compare("advancement_type")  == 0) c3AdvancementType = val;
554   else Cerr << "Unrecognized C3 parameter: " << var << std::endl;
555 }
556 
557 
set_parameter(String var,double val)558 inline void SharedC3ApproxData::set_parameter(String var, double val)
559 {
560   if      (var.compare("solver_tol")          == 0)            solverTol = val;
561   else if (var.compare("solver_rounding_tol") == 0)    solverRoundingTol = val;
562   else if (var.compare("stats_rounding_tol")  == 0)     statsRoundingTol = val;
563   else if (var.compare("regularization_parameter") == 0) regressRegParam = val;
564   else Cerr << "Unrecognized C3 parameter: " << var << std::endl;
565 }
566 
567 
set_parameter(String var,int val)568 inline void SharedC3ApproxData::set_parameter(String var, int val)
569 {
570   if      (var.compare("max_cross_iterations")  == 0)        crossMaxIter = val;
571   else if (var.compare("max_solver_iterations") == 0) maxSolverIterations = val;
572   else if (var.compare("random_seed")           == 0)          randomSeed = val;
573   else Cerr << "Unrecognized C3 parameter: " << var << std::endl;
574 }
575 
576 
577 inline void SharedC3ApproxData::
set_active_parameter(String var,const UShortArray & val)578 set_active_parameter(String var, const UShortArray& val)
579 {
580   if (var.compare("start_order") == 0)
581     { startOrdersMap[activeKey] = val; /*update_basis();*/ }
582   else Cerr << "Unrecognized C3 active parameter: " << var << std::endl;
583 }
584 
585 
586 inline void SharedC3ApproxData::
set_active_parameter(String var,unsigned short val)587 set_active_parameter(String var, unsigned short val)
588 {
589   if (var.compare("max_order") == 0)
590     { maxOrderMap[activeKey] = val; /*if (adaptOrder) update_basis();*/ }
591   else Cerr << "Unrecognized C3 active parameter: " << var << std::endl;
592 }
593 
594 
set_active_parameter(String var,size_t val)595 inline void SharedC3ApproxData::set_active_parameter(String var, size_t val)
596 {
597   if      (var.compare("start_rank") == 0) startRankMap[activeKey] = val;
598   else if (var.compare("max_rank")   == 0)   maxRankMap[activeKey] = val;
599   else Cerr << "Unrecognized C3 active parameter: " << var << std::endl;
600 }
601 
602 
set_active_parameter(String var,int val)603 inline void SharedC3ApproxData::set_active_parameter(String var, int val)
604 {
605   if (var.compare("random_seed") == 0) randomSeed = val;
606   else Cerr << "Unrecognized C3 active parameter: " << var << std::endl;
607 }
608 
609 
610 inline void SharedC3ApproxData::
random_variables_key(const BitArray & random_vars_key)611 random_variables_key(const BitArray& random_vars_key)
612 {
613   // store incoming mask:
614   //ranVarsKey = random_vars_key;
615 
616   // convert incoming mask to a set of random indices:
617   if (random_vars_key.empty()) {
618     randomIndices.resize(numVars);
619     for (size_t i=0; i<numVars; ++i)
620       randomIndices[i] = i;
621   }
622   else {
623     // NonDExpansion::initialize_u_space_model() assigns startCAUV,numCAUV
624     // subset within numContinuousVars
625     size_t i, cntr, num_rand = random_vars_key.count();
626     randomIndices.resize(num_rand);
627     for (i=0, cntr=0; i<numVars; ++i)
628       if (random_vars_key[i])
629 	randomIndices[cntr++] = i;
630   }
631 }
632 
633 
634 //inline void SharedC3ApproxData::refinement_statistics_mode(short stats_mode)
635 //{ refineStatsMode = stats_mode; }
636 
637 
build()638 inline void SharedC3ApproxData::build()
639 {
640   // Ideally this would occur in post_build(), but for now there is only a
641   // SharedApproxData::build() that precedes Approximation::build()
642 
643   // formulation updates (rank,order increments/decrements) have been
644   // synchronized once build is complete (no longer need to force a rebuild):
645   formUpdated[activeKey] = false;
646 }
647 
648 
pop(bool save_surr_data)649 inline void SharedC3ApproxData::pop(bool save_surr_data)
650 {
651   std::map<UShortArray, size_t>::iterator it = poppedCounts.find(activeKey);
652   if (it == poppedCounts.end())
653     poppedCounts[activeKey] = 1;
654   else
655     ++it->second; // increment count
656 }
657 
658 
push_available()659 inline bool SharedC3ApproxData::push_available()
660 {
661   std::map<UShortArray, size_t>::iterator it = poppedCounts.find(activeKey);
662   return (it != poppedCounts.end() && it->second > 0);
663 }
664 
665 
push_index(const UShortArray & key)666 inline size_t SharedC3ApproxData::push_index(const UShortArray& key)
667 {
668   std::map<UShortArray, size_t>::iterator it = poppedCounts.find(key);
669   if (it == poppedCounts.end() || it->second == 0) {
670     Cerr << "Error: bad lookup in SharedC3ApproxData::push_index(key)"
671 	 << std::endl;
672     abort_handler(APPROX_ERROR);
673   }
674   // there should only be a single refinement candidate per level (as for
675   // uniform refinement cases in Pecos), but this is more general:
676   else
677     return it->second - 1; // last in, first out
678 }
679 
680 
post_push()681 inline void SharedC3ApproxData::post_push()
682 {
683   std::map<UShortArray, size_t>::iterator it = poppedCounts.find(activeKey);
684   if (it != poppedCounts.end() && it->second > 0)
685     --it->second; // decrement count
686 }
687 
688 } // namespace Dakota
689 
690 #endif
691