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:       ParamStudy
10 //- Description: Implementation code for the ParamStudy class
11 //- Owner:       Mike Eldred
12 #include <exception>
13 #include "dakota_system_defs.hpp"
14 #include "dakota_tabular_io.hpp"
15 #include "ParamStudy.hpp"
16 #include "ProblemDescDB.hpp"
17 #include "ParallelLibrary.hpp"
18 #include "PolynomialApproximation.hpp"
19 
20 static const char rcsId[]="@(#) $Id: ParamStudy.cpp 7024 2010-10-16 01:24:42Z mseldre $";
21 
22 //#define DEBUG
23 
24 
25 namespace Dakota {
26 
ParamStudy(ProblemDescDB & problem_db,Model & model)27 ParamStudy::ParamStudy(ProblemDescDB& problem_db, Model& model):
28   PStudyDACE(problem_db, model)
29 {
30   // use allVariables instead of default allSamples
31   compactMode = false;
32 
33   // Extract specification from ProblemDescDB, perform sanity checking, and
34   // compute/estimate maxEvalConcurrency.
35   bool err_flag = false;
36   switch (methodName) {
37   case LIST_PARAMETER_STUDY: {
38     const RealVector& pt_list
39       = probDescDB.get_rv("method.parameter_study.list_of_points");
40     if (pt_list.empty()) {
41       const String& pt_fname
42 	= probDescDB.get_string("method.pstudy.import_file");
43       unsigned short tabular_format
44 	= probDescDB.get_ushort("method.pstudy.import_format");
45       bool active_only
46 	= probDescDB.get_bool("method.pstudy.import_active_only");
47       if (load_distribute_points(pt_fname, tabular_format, active_only))
48 	err_flag = true;
49     }
50     else if (distribute_list_of_points(pt_list))
51       err_flag = true;
52     break;
53   }
54   case VECTOR_PARAMETER_STUDY: {
55     const RealVector& step_vector
56       = probDescDB.get_rv("method.parameter_study.step_vector");
57     if (step_vector.empty()) { // final_point & num_steps spec.
58       // check length and distribute
59       if (check_final_point(
60 	  probDescDB.get_rv("method.parameter_study.final_point")))
61 	err_flag = true;
62       // check value
63       if (check_num_steps(
64 	  probDescDB.get_int("method.parameter_study.num_steps")))
65 	err_flag = true;
66       // precompute steps (using construct-time initialPoint) and perform error
67       // checks only if in check mode; else avoid additional overhead and rely
68       // on run-time checks for run-time initialPoint.
69       if (numSteps && parallelLib.command_line_check()) {
70 	initialCVPoint  = iteratedModel.continuous_variables();      // view
71 	initialDIVPoint = iteratedModel.discrete_int_variables();    // view
72 	initialDSVPoint.resize(boost::extents[numDiscreteStringVars]);
73 	initialDSVPoint = iteratedModel.discrete_string_variables(); // copy
74 	initialDRVPoint = iteratedModel.discrete_real_variables();   // view
75 	final_point_to_step_vector(); // covers check_ranges_sets(numSteps)
76       }
77     }
78     else { // step_vector & num_steps spec.
79       // check length and distribute
80       if (check_step_vector(step_vector))
81 	err_flag = true;
82        // check value
83      if (check_num_steps(
84 	  probDescDB.get_int("method.parameter_study.num_steps")))
85 	err_flag = true;
86       // discrete initial pts needed for check_sets(); reassigned in pre-run
87       initialDIVPoint = iteratedModel.discrete_int_variables();    // view
88       initialDSVPoint.resize(boost::extents[numDiscreteStringVars]);
89       initialDSVPoint = iteratedModel.discrete_string_variables(); // copy
90       initialDRVPoint = iteratedModel.discrete_real_variables();   // view
91       if (check_ranges_sets(numSteps))
92 	err_flag = true;
93     }
94     break;
95   }
96   case CENTERED_PARAMETER_STUDY:
97     if (check_step_vector(
98 	probDescDB.get_rv("method.parameter_study.step_vector")))
99       err_flag = true;
100     if (check_steps_per_variable(
101 	probDescDB.get_iv("method.parameter_study.steps_per_variable")))
102       err_flag = true;
103     initialDIVPoint = iteratedModel.discrete_int_variables();    // view
104     initialDSVPoint.resize(boost::extents[numDiscreteStringVars]);
105     initialDSVPoint = iteratedModel.discrete_string_variables(); // copy
106     initialDRVPoint = iteratedModel.discrete_real_variables();   // view
107     if (check_ranges_sets(contStepsPerVariable, discIntStepsPerVariable,
108 			  discStringStepsPerVariable, discRealStepsPerVariable))
109       err_flag = true;
110     break;
111   case MULTIDIM_PARAMETER_STUDY:
112     if (check_variable_partitions(probDescDB.get_usa("method.partitions")))
113       err_flag = true;
114     if (check_finite_bounds())
115       err_flag = true;
116     // precompute steps (using construct-time bounds) and perform error checks
117     // only if in check mode; else avoid additional overhead and rely on
118     // run-time checks for run-time bounds.
119     if (parallelLib.command_line_check())
120       distribute_partitions();
121     break;
122   default:
123     Cerr << "\nError: bad methodName (" << method_enum_to_string(methodName)
124 	 << ") in ParamStudy constructor." << std::endl;
125     err_flag = true;
126   }
127   if (err_flag)
128     abort_handler(METHOD_ERROR);
129 
130   maxEvalConcurrency *= numEvals;
131 }
132 
resize()133 bool ParamStudy::resize()
134 {
135   bool parent_reinit_comms = PStudyDACE::resize();
136 
137   // TODO:  To get resize() working, move contents of ParamStudy::pre_run()
138   //        to ParamStudy::initialize_run() before Analyzer::initialize_run()
139   //        is called. This populates allVariables. If the model is a
140   //        RecastModel, call inverse_transform_variables() on each entry in
141   //        allVariables to resize and transform to the RecastModel. This call
142   //        to inverse_transform_variables() must occur after
143   //        Analyzer::initialize_run(). Also in ActiveSubspaceModel,
144   //        inverse_transform_variables() is not yet implemented.
145 
146   Cerr << "\nError: Resizing is not yet supported in method "
147        << method_enum_to_string(methodName) << "." << std::endl;
148   abort_handler(METHOD_ERROR);
149 
150   return parent_reinit_comms;
151 }
152 
153 
pre_run()154 void ParamStudy::pre_run()
155 {
156   Analyzer::pre_run();
157 
158   // Capture any changes in initialCVPoint resulting from the strategy layer's
159   // passing of best variable info between iterators.  If no such variable
160   // passing has occurred, then this reassignment is merely repetitive of the
161   // one in the ParamStudy constructor.  If there is a final_point
162   // specification, then contStepVector and numSteps must be (re)computed.
163   const Variables& vars = iteratedModel.current_variables();
164   const SharedVariablesData& svd = vars.shared_data();
165   if (methodName == VECTOR_PARAMETER_STUDY ||
166       methodName == CENTERED_PARAMETER_STUDY) {
167     copy_data(vars.continuous_variables(),      initialCVPoint);  // copy
168     copy_data(vars.discrete_int_variables(),    initialDIVPoint); // copy
169     initialDSVPoint.resize(boost::extents[numDiscreteStringVars]);
170     initialDSVPoint = vars.discrete_string_variables();           // copy
171     copy_data(vars.discrete_real_variables(),   initialDRVPoint); // copy
172   }
173 
174   size_t av_size = allVariables.size();
175   if (av_size != numEvals) {
176     allVariables.resize(numEvals);
177     for (size_t i=av_size; i<numEvals; ++i)
178       allVariables[i] = Variables(svd); // use minimal data ctor
179     if ( outputLevel > SILENT_OUTPUT &&
180 	 ( methodName == VECTOR_PARAMETER_STUDY ||
181 	   methodName == CENTERED_PARAMETER_STUDY ) )
182       allHeaders.resize(numEvals);
183   }
184 
185   switch (methodName) {
186   case LIST_PARAMETER_STUDY:
187     if (outputLevel > SILENT_OUTPUT)
188       Cout << "\nList parameter study for " << numEvals << " samples\n\n";
189     sample();
190     break;
191   case VECTOR_PARAMETER_STUDY:
192     if (!contStepVector.empty()       || !discIntStepVector.empty() ||
193 	!discStringStepVector.empty() || !discRealStepVector.empty()) {
194       // step_vector & num_steps
195       if (outputLevel > SILENT_OUTPUT) {
196 	Cout << "\nVector parameter study for " << numSteps
197 	     << " steps starting from\n";
198 	write_ordered(Cout, svd.active_components_totals(), initialCVPoint,
199 		      initialDIVPoint, initialDSVPoint, initialDRVPoint);
200 	Cout << "with a step vector of\n";
201 	write_ordered(Cout, svd.active_components_totals(), contStepVector,
202 		      discIntStepVector, discStringStepVector,
203 		      discRealStepVector);
204 	Cout << '\n';
205       }
206     }
207     else { // final_point & num_steps
208       if (outputLevel > SILENT_OUTPUT) {
209 	Cout << "\nVector parameter study from\n";
210 	write_ordered(Cout, svd.active_components_totals(), initialCVPoint,
211 		      initialDIVPoint, initialDSVPoint, initialDRVPoint);
212 	Cout << "to\n";
213 	write_ordered(Cout, svd.active_components_totals(), finalCVPoint,
214 		      finalDIVPoint, finalDSVPoint, finalDRVPoint);
215 	Cout << "using " << numSteps << " steps\n\n";
216       }
217       if (numSteps) // define step vectors from initial, final, & num steps
218 	final_point_to_step_vector();
219     }
220     vector_loop();
221     break;
222   case CENTERED_PARAMETER_STUDY:
223     if (outputLevel > SILENT_OUTPUT) {
224       Cout << "\nCentered parameter study with steps per variable\n";
225       write_ordered(Cout, svd.active_components_totals(), contStepsPerVariable,
226 		    discIntStepsPerVariable, discStringStepsPerVariable,
227 		    discRealStepsPerVariable);
228       Cout << "and increments of\n";
229       write_ordered(Cout, svd.active_components_totals(), contStepVector,
230 		    discIntStepVector, discStringStepVector,
231 		    discRealStepVector);
232       Cout << "with the following center point:\n";
233       write_ordered(Cout, svd.active_components_totals(), initialCVPoint,
234 		    initialDIVPoint, initialDSVPoint, initialDRVPoint);
235       Cout << '\n';
236     }
237     centered_loop();
238     break;
239   case MULTIDIM_PARAMETER_STUDY:
240     if (outputLevel > SILENT_OUTPUT) {
241       Cout << "\nMultidimensional parameter study variable partitions of\n";
242       write_ordered(Cout, svd.active_components_totals(), contVarPartitions,
243 		    discIntVarPartitions, discStringVarPartitions,
244 		    discRealVarPartitions);
245     }
246     distribute_partitions();
247     multidim_loop();
248     break;
249   default:
250     Cerr << "\nError: bad methodName (" << method_enum_to_string(methodName)
251 	 << ") in ParamStudy::pre_run()." << std::endl;
252     abort_handler(METHOD_ERROR);
253   }
254 }
255 
256 
core_run()257 void ParamStudy::core_run()
258 {
259 
260   archive_allocate_sets();
261   // perform the evaluations; multidim exception
262   bool log_resp_flag = (methodName == MULTIDIM_PARAMETER_STUDY)
263     ? (!subIteratorFlag) : false;
264   bool log_best_flag = (numObjFns || numLSqTerms); // opt or NLS data set
265   evaluate_parameter_sets(iteratedModel, log_resp_flag, log_best_flag);
266 }
267 
archive_model_variables(const Model & model,size_t idx) const268 void ParamStudy::archive_model_variables(const Model& model, size_t idx) const
269 {
270   // Let's try to write resultsDB stuff here - RWH
271   if(resultsDB.active())
272   {
273     const RealVector& c_vars  = model.continuous_variables();
274     const IntVector & di_vars = model.discrete_int_variables();
275     StringMultiArrayConstView ds_vars = model.discrete_string_variables();
276     const RealVector& dr_vars = model.discrete_real_variables();
277 
278     if( numContinuousVars )
279       resultsDB.insert_into
280 	( run_identifier(),
281 	  {String("parameter_sets"), String("continuous_variables")},
282 	  c_vars,  idx );
283     if( numDiscreteIntVars )
284       resultsDB.insert_into
285 	( run_identifier(),
286 	  {String("parameter_sets"), String("discrete_integer_variables")},
287 	  di_vars, idx );
288     if( numDiscreteStringVars )
289       resultsDB.insert_into
290 	( run_identifier(),
291 	  {String("parameter_sets"), String("discrete_string_variables")},
292 	  ds_vars, idx );
293     if( numDiscreteRealVars )
294       resultsDB.insert_into
295 	( run_identifier(),
296 	  {String("parameter_sets"), String("discrete_real_variables")},
297 	  dr_vars, idx );
298 
299     if (methodName == CENTERED_PARAMETER_STUDY)
300       archive_cps_vars(model, idx);
301   }
302 }
303 
304 
archive_model_response(const Response & response,size_t idx) const305 void ParamStudy::archive_model_response(const Response& response, size_t idx) const
306 {
307   // Let's try to write resultsDB stuff here - RWH
308   if(resultsDB.active())
309   {
310     const RealVector& resp_vec = response.function_values();
311     resultsDB.insert_into
312       ( run_identifier(),
313 	{String("parameter_sets"), String("responses")}, resp_vec, idx );
314 
315     if (methodName == CENTERED_PARAMETER_STUDY)
316       archive_cps_resp(response, idx);
317   }
318 }
319 
320 
archive_allocate_sets() const321 void ParamStudy::archive_allocate_sets() const
322 {
323   if(resultsDB.active())
324   {
325     size_t num_evals = (compactMode) ? allSamples.numCols() : allVariables.size();
326 
327     StringMultiArrayConstView cv_labels
328                 = iteratedModel.continuous_variable_labels();
329     StringMultiArrayConstView div_labels
330                 = iteratedModel.discrete_int_variable_labels();
331     StringMultiArrayConstView dsv_labels
332                 = iteratedModel.discrete_string_variable_labels();
333     StringMultiArrayConstView drv_labels
334                 = iteratedModel.discrete_real_variable_labels();
335 
336     const StringArray& resp_labels
337                 = iteratedModel.response_labels();
338 
339     if( numContinuousVars ) {
340       DimScaleMap scales;
341       scales.emplace(1, StringScale("variables", cv_labels));
342       resultsDB.allocate_matrix
343 	( run_identifier(),
344 	  {String("parameter_sets"), String("continuous_variables")},
345           Dakota::ResultsOutputType::REAL, num_evals, numContinuousVars,
346 	  scales );
347     }
348     if( numDiscreteIntVars ) {
349       DimScaleMap scales;
350       scales.emplace(1, StringScale("variables", div_labels));
351       resultsDB.allocate_matrix
352 	( run_identifier(),
353 	  {String("parameter_sets"), String("discrete_integer_variables")},
354           Dakota::ResultsOutputType::INTEGER, num_evals, numDiscreteIntVars,
355 	  scales );
356     }
357     if( numDiscreteStringVars ) {
358       DimScaleMap scales;
359       scales.emplace(1, StringScale("variables", dsv_labels));
360       resultsDB.allocate_matrix
361 	( run_identifier(),
362 	  {String("parameter_sets"), String("discrete_string_variables")},
363           Dakota::ResultsOutputType::STRING, num_evals, numDiscreteStringVars,
364 	  scales );
365     }
366     if( numDiscreteRealVars ) {
367       DimScaleMap scales;
368       scales.emplace(1, StringScale("variables", drv_labels));
369       resultsDB.allocate_matrix
370 	( run_identifier(),
371 	  {String("parameter_sets"), String("discrete_real_variables")},
372           Dakota::ResultsOutputType::REAL, num_evals, numDiscreteRealVars,
373 	  scales );
374     }
375     DimScaleMap scales;
376     scales.emplace(1, StringScale("responses", resp_labels));
377     resultsDB.allocate_matrix
378       ( run_identifier(), {String("parameter_sets"), String("responses")},
379         Dakota::ResultsOutputType::REAL, num_evals, numFunctions, scales );
380 
381     if (methodName == CENTERED_PARAMETER_STUDY)
382       archive_allocate_cps();
383   }
384 
385 }
386 
post_input()387 void ParamStudy::post_input()
388 {
389   // call convenience function from Analyzer
390   read_variables_responses(numEvals, numContinuousVars + numDiscreteIntVars +
391 			   numDiscreteStringVars + numDiscreteRealVars);
392 }
393 
394 
post_run(std::ostream & s)395 void ParamStudy::post_run(std::ostream& s)
396 {
397   bool log_resp_flag = (!subIteratorFlag);
398   if (methodName == MULTIDIM_PARAMETER_STUDY && log_resp_flag) {
399     pStudyDACESensGlobal.compute_correlations(allVariables, allResponses,
400       iteratedModel.discrete_set_string_values()); // to map string variable
401                                                    // values back to indices
402     if(resultsDB.active()) {
403       StringMultiArrayConstView
404         cv_labels  = iteratedModel.continuous_variable_labels(),
405         div_labels = iteratedModel.discrete_int_variable_labels(),
406         dsv_labels = iteratedModel.discrete_string_variable_labels(),
407         drv_labels = iteratedModel.discrete_real_variable_labels();
408       pStudyDACESensGlobal.archive_correlations(run_identifier(), resultsDB, cv_labels,
409                                         div_labels, dsv_labels, drv_labels,
410                                         iteratedModel.response_labels());
411     }
412 
413   }
414 
415   Analyzer::post_run(s);
416 }
417 
418 
sample()419 void ParamStudy::sample()
420 {
421   // populate allVariables
422   for (size_t i=0; i<numEvals; ++i) {
423     if (numContinuousVars)
424       allVariables[i].continuous_variables(listCVPoints[i]);
425     if (numDiscreteIntVars)
426       allVariables[i].discrete_int_variables(listDIVPoints[i]);
427     if (numDiscreteStringVars)
428       allVariables[i].discrete_string_variables(
429 	listDSVPoints[boost::indices[i][idx_range(0, numDiscreteStringVars)]]);
430     if (numDiscreteRealVars)
431       allVariables[i].discrete_real_variables(listDRVPoints[i]);
432   }
433   // free up redundant memory
434   listCVPoints.clear();
435   listDIVPoints.clear();
436   listDSVPoints.resize(boost::extents[0][0]);
437   listDRVPoints.clear();
438 }
439 
440 
vector_loop()441 void ParamStudy::vector_loop()
442 {
443   // Steps along a n-dimensional vector through numSteps additions of
444   // continuous/discrete step vectors.  The step is an absolute step defining
445   // magnitude & direction.  The number of fn. evaluations in the study is
446   // numSteps + 1 since the initial point is also evaluated.
447 
448   const BitArray&      di_set_bits = iteratedModel.discrete_int_sets();
449   const IntSetArray&    dsi_values = iteratedModel.discrete_set_int_values();
450   const StringSetArray& dss_values = iteratedModel.discrete_set_string_values();
451   const RealSetArray&   dsr_values = iteratedModel.discrete_set_real_values();
452   size_t i, j, dsi_cntr;
453 
454   for (i=0; i<=numSteps; ++i) {
455     Variables& vars = allVariables[i];
456 
457     // active continuous
458     for (j=0; j<numContinuousVars; ++j)
459       c_step(j, i, vars);
460 
461     // active discrete int: ranges and sets
462     for (j=0, dsi_cntr=0; j<numDiscreteIntVars; ++j)
463       if (di_set_bits[j]) dsi_step(j, i, dsi_values[dsi_cntr++], vars);
464       else                dri_step(j, i, vars);
465 
466     // active discrete string: sets only
467     for (j=0; j<numDiscreteStringVars; ++j)
468       dss_step(j, i, dss_values[j], vars);
469 
470     // active discrete real: sets only
471     for (j=0; j<numDiscreteRealVars; ++j)
472       dsr_step(j, i, dsr_values[j], vars);
473 
474     // store each output header in allHeaders
475     if (outputLevel > SILENT_OUTPUT) {
476       String& h_string = allHeaders[i];
477       h_string.clear();
478       if (iteratedModel.asynch_flag())
479 	h_string += "\n\n";
480       if (numSteps == 0) // Allow numSteps == 0 case
481 	h_string += ">>>>> Initial_point only (no steps)\n";
482       h_string += ">>>>> Vector parameter study evaluation for ";
483       h_string += std::to_string(i*100./numSteps);
484       h_string += "% along vector\n";
485     }
486   }
487 }
488 
489 
centered_loop()490 void ParamStudy::centered_loop()
491 {
492   size_t k, cntr = 0, dsi_cntr = 0;
493   String cv_str("cv"), div_str("div"), dsv_str("dsv"), drv_str("drv");
494 
495   // Always evaluate center point, even if steps_per_variable = 0
496   if (outputLevel > SILENT_OUTPUT)
497     allHeaders[cntr] = (iteratedModel.asynch_flag()) ?
498       "\n\n>>>>> Centered parameter study evaluation for center point\n" :
499       ">>>>> Centered parameter study evaluation for center point\n";
500   if (numContinuousVars)
501     allVariables[cntr].continuous_variables(initialCVPoint);
502   if (numDiscreteIntVars)
503     allVariables[cntr].discrete_int_variables(initialDIVPoint);
504   if (numDiscreteStringVars)
505     allVariables[cntr].discrete_string_variables(
506       initialDSVPoint[boost::indices[idx_range(0, numDiscreteStringVars)]]);
507   if (numDiscreteRealVars)
508     allVariables[cntr].discrete_real_variables(initialDRVPoint);
509   ++cntr;
510 
511   // Evaluate +/- steps for each continuous variable
512   for (k=0; k<numContinuousVars; ++k) {
513     int i, num_steps_k = contStepsPerVariable[k];
514     for (i=-num_steps_k; i<=num_steps_k; ++i)
515       if (i) {
516 	Variables& vars = allVariables[cntr];
517 	reset(vars); c_step(k, i, vars);
518 	if (outputLevel > SILENT_OUTPUT) centered_header(cv_str, k, i, cntr);
519 	++cntr;
520       }
521   }
522 
523   // Evaluate +/- steps for each discrete int variable
524   const BitArray&   di_set_bits = iteratedModel.discrete_int_sets();
525   const IntSetArray& dsi_values = iteratedModel.discrete_set_int_values();
526   for (k=0; k<numDiscreteIntVars; ++k) {
527     int i, num_steps_k = discIntStepsPerVariable[k];
528     if (di_set_bits[k]) {
529       const IntSet& dsi_vals_k = dsi_values[dsi_cntr];
530       for (i=-num_steps_k; i<=num_steps_k; ++i)
531 	if (i) {
532 	  Variables& vars = allVariables[cntr];
533 	  reset(vars); dsi_step(k, i, dsi_vals_k, vars);
534 	  if (outputLevel > SILENT_OUTPUT) centered_header(div_str, k, i, cntr);
535 	  ++cntr;
536 	}
537       ++dsi_cntr;
538     }
539     else {
540       for (i=-num_steps_k; i<=num_steps_k; ++i)
541 	if (i) {
542 	  Variables& vars = allVariables[cntr];
543 	  reset(vars); dri_step(k, i, vars);
544 	  if (outputLevel > SILENT_OUTPUT) centered_header(div_str, k, i, cntr);
545 	  ++cntr;
546 	}
547     }
548   }
549 
550   // Evaluate +/- steps for each discrete string variable
551   const StringSetArray& dss_values = iteratedModel.discrete_set_string_values();
552   for (k=0; k<numDiscreteStringVars; ++k) {
553     int i, num_steps_k = discStringStepsPerVariable[k];
554     const StringSet& dss_vals_k = dss_values[k];
555     for (i=-num_steps_k; i<=num_steps_k; ++i)
556       if (i) {
557 	Variables& vars = allVariables[cntr];
558 	reset(vars); dss_step(k, i, dss_vals_k, vars);
559 	if (outputLevel > SILENT_OUTPUT) centered_header(dsv_str, k, i, cntr);
560 	++cntr;
561       }
562   }
563 
564   // Evaluate +/- steps for each discrete real variable
565   const RealSetArray& dsr_values = iteratedModel.discrete_set_real_values();
566   for (k=0; k<numDiscreteRealVars; ++k) {
567     int i, num_steps_k = discRealStepsPerVariable[k];
568     const RealSet& dsr_vals_k = dsr_values[k];
569     for (i=-num_steps_k; i<=num_steps_k; ++i)
570       if (i) {
571 	Variables& vars = allVariables[cntr];
572 	reset(vars); dsr_step(k, i, dsr_vals_k, vars);
573 	if (outputLevel > SILENT_OUTPUT) centered_header(drv_str, k, i, cntr);
574 	++cntr;
575       }
576   }
577 }
578 
579 
multidim_loop()580 void ParamStudy::multidim_loop()
581 {
582   // Perform a multidimensional parameter study based on the number of
583   // partitions specified for each variable.
584 
585   const BitArray&      di_set_bits = iteratedModel.discrete_int_sets();
586   const IntSetArray&    dsi_values = iteratedModel.discrete_set_int_values();
587   const StringSetArray& dss_values = iteratedModel.discrete_set_string_values();
588   const RealSetArray&   dsr_values = iteratedModel.discrete_set_real_values();
589   size_t i, j, p_cntr, dsi_cntr,
590     num_c_di_vars    = numContinuousVars + numDiscreteIntVars,
591     num_c_di_ds_vars = num_c_di_vars + numDiscreteStringVars,
592     num_vars = num_c_di_ds_vars + numDiscreteRealVars;
593   UShortArray multidim_indices(num_vars, 0), partition_limits(num_vars);
594   copy_data_partial(contVarPartitions, partition_limits, 0);
595   copy_data_partial(discIntVarPartitions, partition_limits, numContinuousVars);
596   copy_data_partial(discStringVarPartitions, partition_limits, num_c_di_vars);
597   copy_data_partial(discRealVarPartitions, partition_limits, num_c_di_ds_vars);
598 
599   for (i=0; i<numEvals; ++i) {
600     Variables& vars = allVariables[i];
601     p_cntr = 0;
602     // active continuous
603     for (j=0; j<numContinuousVars; ++j, ++p_cntr)
604       c_step(j, multidim_indices[p_cntr], vars);
605     // active discrete int: ranges and sets
606     for (j=0, dsi_cntr=0; j<numDiscreteIntVars; ++j, ++p_cntr)
607       if (di_set_bits[j])
608 	dsi_step(j, multidim_indices[p_cntr], dsi_values[dsi_cntr++], vars);
609       else
610 	dri_step(j, multidim_indices[p_cntr], vars);
611     // active discrete string: sets only
612     for (j=0; j<numDiscreteStringVars; ++j, ++p_cntr)
613       dss_step(j, multidim_indices[p_cntr], dss_values[j], vars);
614     // active discrete real: sets only
615     for (j=0; j<numDiscreteRealVars; ++j, ++p_cntr)
616       dsr_step(j, multidim_indices[p_cntr], dsr_values[j], vars);
617     // increment the multidimensional index set
618     Pecos::SharedPolyApproxData::increment_indices(multidim_indices,
619 						   partition_limits, true);
620   }
621 }
622 
623 
624 /** Load from file and distribute points; using this function to
625     manage construction of the temporary arrays.  Historically all
626     data was read as a real (mixture of values and indices), but now
627     points_file is valued-based (reals, integers, strings) so file
628     input matches tabular data output.  Return false on success. */
629 bool ParamStudy::
load_distribute_points(const String & points_filename,unsigned short tabular_format,bool active_only)630 load_distribute_points(const String& points_filename,
631 		       unsigned short tabular_format,
632 		       bool active_only)
633 {
634   bool err = false;
635 
636   // don't know the size until the file is read, so the reader grows
637   // the containers as the read takes place
638 
639   // the easiest way to read is with a variables object
640   // read all variables in spec order into a temporary Variables
641   Variables vars(iteratedModel.current_variables().copy());
642 
643   // then map the active data from that variables object into the
644   // list*Points arrays and validate it
645 
646   // TODO: validate the read values of inactive variables
647 
648   // Could read into these dynamically or into a temporary and then allocate
649   numEvals = TabularIO::
650     read_data_tabular(points_filename, "List Parameter Study",
651 		      listCVPoints, listDIVPoints, listDSVPoints, listDRVPoints,
652 		      tabular_format, active_only,
653 		      iteratedModel.current_variables().copy());
654   if (numEvals == 0) err = true;
655 
656 
657   // validation of data: consider moving reader into this class and
658   // validating while reading...
659   for (size_t i=0; i<numEvals; ++i) {
660 
661     // validate continuous values read
662     const RealVector& c_lb = iteratedModel.continuous_lower_bounds();
663     const RealVector& c_ub = iteratedModel.continuous_upper_bounds();
664 
665     for (size_t j=0; j<numContinuousVars; ++j)
666       if (listCVPoints[i][j] < c_lb[j] || listCVPoints[i][j] > c_ub[j]) {
667 	Cerr << "\nError: list value " << listCVPoints[i][j]
668 	     << " outside bounds for continuous variable " << j+1 << '.'
669 	     << std::endl;
670 	err = true;
671       }
672 
673     // validate discrete integers (sets and ranges) read
674     const BitArray& di_set_bits = iteratedModel.discrete_int_sets();
675     const IntSetArray& dsi_vals = iteratedModel.discrete_set_int_values();
676     const IntVector& di_lb = iteratedModel.discrete_int_lower_bounds();
677     const IntVector& di_ub = iteratedModel.discrete_int_upper_bounds();
678 
679     for (size_t j=0, dsi_cntr=0; j<numDiscreteIntVars; ++j)
680       if (di_set_bits[j]) {
681 	// set values
682 	if (set_value_to_index(listDIVPoints[i][j], dsi_vals[dsi_cntr])
683 	    == _NPOS) {
684 	  Cerr << "\nError: list value " << listDIVPoints[i][j]
685 	       << " not admissble for discrete int set " << dsi_cntr+1 << '.'
686 	       << std::endl;
687 	  err = true;
688 	}
689 	++dsi_cntr;
690       }
691       else {
692 	// range values: validate bounds
693 	if (listDIVPoints[i][j] < di_lb[j] || listDIVPoints[i][j] > di_ub[j]) {
694 	  Cerr << "\nError: list value " << listDIVPoints[i][j]
695 	       << " outside bounds for discrete int range variable " << j+1
696 	       << '.' << std::endl;
697 	  err = true;
698 	}
699       }
700 
701     // validate discrete string sets read
702     const StringSetArray& dss_vals = iteratedModel.discrete_set_string_values();
703     for (size_t j=0; j<numDiscreteStringVars; ++j)
704       if (set_value_to_index(listDSVPoints[i][j], dss_vals[j]) == _NPOS) {
705         Cerr << "\nError: list value " << listDSVPoints[i][j]
706 	     << " not admissible for discrete string set " << j+1 << '.'
707 	     << std::endl;
708         err = true;
709       }
710 
711     const RealSetArray& dsr_vals = iteratedModel.discrete_set_real_values();
712     for (size_t j=0; j<numDiscreteRealVars; ++j)
713       if (set_value_to_index(listDRVPoints[i][j], dsr_vals[j]) == _NPOS) {
714         Cerr << "\nError: list value " << listDRVPoints[i][j]
715 	     << " not admissible for discrete real set " << j+1 << '.'
716 	     << std::endl;
717         err = true;
718       }
719 
720   } // for each eval
721 
722   return err;
723 
724 }
725 
726 
727 /** Parse list of points into typed data containers; list_of_pts will
728     contain values for continuous and discrete integer range, but
729     indices for all discrete set types (int, string, real) */
distribute_list_of_points(const RealVector & list_of_pts)730 bool ParamStudy::distribute_list_of_points(const RealVector& list_of_pts)
731 {
732   size_t i, j, dsi_cntr, start, len_lop = list_of_pts.length(),
733     num_vars = numContinuousVars     + numDiscreteIntVars
734              + numDiscreteStringVars + numDiscreteRealVars;
735   if (len_lop % num_vars) {
736     Cerr << "\nError: length of list_of_points ("  << len_lop
737 	 << ") must be evenly divisable among number of active variables ("
738 	 << num_vars << ")." << std::endl;
739     return true;
740   }
741   numEvals = len_lop / num_vars;
742   if (numContinuousVars)   listCVPoints.resize(numEvals);
743   if (numDiscreteIntVars)  listDIVPoints.resize(numEvals);
744   if (numDiscreteStringVars)
745     listDSVPoints.resize(boost::extents[numEvals][numDiscreteStringVars]);
746   if (numDiscreteRealVars) listDRVPoints.resize(numEvals);
747 
748   const BitArray&      di_set_bits = iteratedModel.discrete_int_sets();
749   const IntSetArray&    dsi_values = iteratedModel.discrete_set_int_values();
750   const StringSetArray& dss_values = iteratedModel.discrete_set_string_values();
751   const RealSetArray&   dsr_values = iteratedModel.discrete_set_real_values();
752 
753   bool err = false;
754   RealVector empty_rv; IntVector empty_iv; StringMultiArray empty_sa;
755   for (i=0, start=0; i<numEvals; ++i) {
756     RealVector& list_cv_i  = (numContinuousVars)  ? listCVPoints[i]  : empty_rv;
757     IntVector&  list_div_i = (numDiscreteIntVars) ? listDIVPoints[i] : empty_iv;
758     StringMultiArrayView list_dsv_i = (numDiscreteStringVars) ?
759       listDSVPoints[boost::indices[i][idx_range(0, numDiscreteStringVars)]] :
760       empty_sa[boost::indices[idx_range(0, 0)]];
761     RealVector& list_drv_i = (numDiscreteRealVars) ?
762       listDRVPoints[i] : empty_rv;
763     IntVector div_combined, dsv_indices, drv_indices;
764 
765     // take a view of each sample and partition it into {c,di,dr} components
766     RealVector all_sample(Teuchos::View, const_cast<Real*>(&list_of_pts[start]),
767 			  num_vars);
768     // if list_of_pts contains range and set values:
769     //distribute(all_sample, list_cv_i, list_div_i, list_dsv_i, list_drv_i);
770     // if list_of_pts contains range values and set indices:
771     distribute(all_sample, list_cv_i, div_combined, dsv_indices, drv_indices);
772     start += num_vars;
773 
774     // Promote set indices to admissible set values
775     if (numDiscreteIntVars) list_div_i.sizeUninitialized(numDiscreteIntVars);
776     for (j=0, dsi_cntr=0; j<numDiscreteIntVars; ++j) {
777       if (di_set_bits[j]) {
778 	// if set values:
779 	//if (set_value_to_index(list_div_i[j], dsi_values[dsi_cntr]) == _NPOS){
780 	//  Cerr << "\nError: list value " << list_div_i[j]<< " not admissible "
781 	//       << "for discrete int set " << dsi_cntr+1 << '.' << std::endl;
782 	//  err = true;
783 	//}
784 	// if set indices:
785         try {
786           list_div_i[j]
787             = set_index_to_value(div_combined[j], dsi_values[dsi_cntr]);
788         } catch(std::out_of_range e) {
789           Cerr << e.what() << " for variable '"
790             << iteratedModel.discrete_int_variable_labels()[j] << "' in method '"
791             << method_id() << "'\n";
792           abort_handler(-1);
793         }
794 	++dsi_cntr;
795       }
796       else // range values
797 	list_div_i[j] = div_combined[j];
798     }
799 
800     for (j=0; j<numDiscreteStringVars; ++j) {
801       // if set values:
802       //if (set_value_to_index(list_dsv_i[j], dss_values[j]) == _NPOS) {
803       //  Cerr << "\nError: list value " << list_dsv_i[j] << " not admissible "
804       //       << "for discrete string set " << j+1 << '.' << std::endl;
805       //  err = true;
806       //}
807       // if set indices:
808       try {
809           list_dsv_i[j] = set_index_to_value(dsv_indices[j], dss_values[j]);
810       } catch(std::out_of_range e) {
811           Cerr << e.what() << " for variable '"
812             << iteratedModel.discrete_string_variable_labels()[j] << "' in method '"
813             << method_id() << "'\n";
814           abort_handler(-1);
815       }
816     }
817 
818     if (numDiscreteRealVars) list_drv_i.sizeUninitialized(numDiscreteRealVars);
819     for (j=0; j<numDiscreteRealVars; ++j) {
820       // if set values:
821       //if (set_value_to_index(list_drv_i[j], dsr_values[j]) == _NPOS) {
822       //  Cerr << "\nError: list value " << list_drv_i[j] << " not admissible "
823       //       << "for discrete real set " << j+1 << '.' << std::endl;
824       //  err = true;
825       //}
826       // if set indices:
827       try {
828           list_drv_i[j] = set_index_to_value(drv_indices[j], dsr_values[j]);
829       } catch (std::out_of_range e) {
830           Cerr << e.what() << " for variable '"
831             << iteratedModel.discrete_real_variable_labels()[j] << "' in method '"
832             << method_id() << "'\n";
833           abort_handler(-1);
834       }
835     }
836   }
837 
838 #ifdef DEBUG
839   Cout << "distribute_list_of_points():\n";
840   for (i=0; i<numEvals; ++i) {
841     if (numContinuousVars)
842       Cout << "Eval " << i << " continuous:\n" << listCVPoints[i];
843     if (numDiscreteIntVars)
844       Cout << "Eval " << i << " discrete int:\n" << listDIVPoints[i];
845     if (numDiscreteStringVars) {
846       Cout << "Eval " << i << " discrete string:\n";
847       write_data(Cout,
848 	listDSVPoints[boost::indices[i][idx_range(0, numDiscreteStringVars)]]);
849     }
850     if (numDiscreteRealVars)
851       Cout << "Eval " << i << " discrete real:\n" << listDRVPoints[i];
852   }
853 #endif // DEBUG
854 
855   return err;
856 }
857 
858 
distribute_partitions()859 void ParamStudy::distribute_partitions()
860 {
861   contStepVector.sizeUninitialized(numContinuousVars);
862   discIntStepVector.sizeUninitialized(numDiscreteIntVars);
863   discStringStepVector.sizeUninitialized(numDiscreteStringVars);
864   discRealStepVector.sizeUninitialized(numDiscreteRealVars);
865 
866   initialCVPoint.sizeUninitialized(numContinuousVars);
867   initialDIVPoint.sizeUninitialized(numDiscreteIntVars);
868   initialDSVPoint.resize(boost::extents[numDiscreteStringVars]);
869   initialDRVPoint.sizeUninitialized(numDiscreteRealVars);
870 
871   const RealVector&          c_vars = iteratedModel.continuous_variables();
872   const IntVector&          di_vars = iteratedModel.discrete_int_variables();
873   StringMultiArrayConstView ds_vars = iteratedModel.discrete_string_variables();
874   const RealVector&         dr_vars = iteratedModel.discrete_real_variables();
875 
876   const RealVector&  c_l_bnds = iteratedModel.continuous_lower_bounds();
877   const RealVector&  c_u_bnds = iteratedModel.continuous_upper_bounds();
878   const IntVector&  di_l_bnds = iteratedModel.discrete_int_lower_bounds();
879   const IntVector&  di_u_bnds = iteratedModel.discrete_int_upper_bounds();
880   const RealVector& dr_l_bnds = iteratedModel.discrete_real_lower_bounds();
881   const RealVector& dr_u_bnds = iteratedModel.discrete_real_upper_bounds();
882 
883   const BitArray&      di_set_bits = iteratedModel.discrete_int_sets();
884   const IntSetArray&    dsi_values = iteratedModel.discrete_set_int_values();
885   const StringSetArray& dss_values = iteratedModel.discrete_set_string_values();
886   const RealSetArray&   dsr_values = iteratedModel.discrete_set_real_values();
887 
888   size_t i, dsi_cntr; unsigned short part;
889   for (i=0; i<numContinuousVars; ++i) {
890     part = contVarPartitions[i];
891     if (part) {
892       initialCVPoint[i] = c_l_bnds[i];
893       contStepVector[i] = (c_u_bnds[i] - c_l_bnds[i]) / part;
894     }
895     else
896       { initialCVPoint[i] = c_vars[i]; contStepVector[i] = 0.; }
897   }
898   for (i=0, dsi_cntr=0; i<numDiscreteIntVars; ++i) {
899     part = discIntVarPartitions[i];
900     if (part) {
901       initialDIVPoint[i] = di_l_bnds[i];
902       int range = (di_set_bits[i]) ? dsi_values[dsi_cntr].size() - 1 :
903 	                             di_u_bnds[i] - di_l_bnds[i];
904       discIntStepVector[i] = integer_step(range, part);
905     }
906     else
907       { initialDIVPoint[i] = di_vars[i]; discIntStepVector[i] = 0; }
908     // must increment the discrete set integer counter even if no partition:
909     if (di_set_bits[i]) ++dsi_cntr;
910   }
911   for (i=0; i<numDiscreteStringVars; ++i) {
912     part = discStringVarPartitions[i];
913     if (part) {
914       const StringSet& dss_vals_i = dss_values[i];
915       initialDSVPoint[i]      = *dss_vals_i.begin();
916       discStringStepVector[i] = integer_step(dss_vals_i.size() - 1, part);
917     }
918     else
919       { initialDSVPoint[i] = ds_vars[i]; discStringStepVector[i] = 0; }
920   }
921   for (i=0; i<numDiscreteRealVars; ++i) {
922     part = discRealVarPartitions[i];
923     if (part) {
924       initialDRVPoint[i]    = dr_l_bnds[i];
925       discRealStepVector[i] = integer_step(dsr_values[i].size() - 1, part);
926     }
927     else
928       { initialDRVPoint[i] = dr_vars[i]; discRealStepVector[i] = 0; }
929   }
930 
931 #ifdef DEBUG
932   Cout << "distribute_partitions():\n";
933   if (numContinuousVars)
934     Cout << "c_vars:\n"   << c_vars   << "c_l_bnds:\n"       << c_l_bnds
935 	 << "c_u_bnds:\n" << c_u_bnds << "initialCVPoint:\n" << initialCVPoint
936 	 << "contStepVector:\n" << contStepVector;
937   if (numDiscreteIntVars)
938     Cout << "di_vars:\n" << di_vars << "di_l_bnds:\n" << di_l_bnds
939 	 << "di_u_bnds:\n" << di_u_bnds
940 	 << "initialDIVPoint:\n" << initialDIVPoint
941 	 << "discIntStepVector:\n" << discIntStepVector;
942   if (numDiscreteStringVars) {
943     Cout << "ds_vars:\n";              write_data(Cout, ds_vars);
944     Cout << "initialDSVPoint:\n";      write_data(Cout, initialDSVPoint);
945     Cout << "discStringStepVector:\n"; write_data(Cout, discStringStepVector);
946   }
947   if (numDiscreteRealVars)
948     Cout << "dr_vars:\n" << dr_vars << "dr_l_bnds:\n" << dr_l_bnds
949 	 << "dr_u_bnds:\n" << dr_u_bnds
950 	 << "initialDRVPoint:\n" << initialDRVPoint
951 	 << "discRealStepVector:\n" << discRealStepVector;
952 #endif // DEBUG
953 }
954 
955 
final_point_to_step_vector()956 void ParamStudy::final_point_to_step_vector()
957 {
958   //RealVector cv_final, drv_final; IntVector div_final;
959   //StringMultiArray dsv_final;
960   //distribute(finalPoint, cv_final, div_final, dsv_final, drv_final);
961 
962   const BitArray&      di_set_bits = iteratedModel.discrete_int_sets();
963   const IntSetArray&    dsi_values = iteratedModel.discrete_set_int_values();
964   const StringSetArray& dss_values = iteratedModel.discrete_set_string_values();
965   const RealSetArray&   dsr_values = iteratedModel.discrete_set_real_values();
966   size_t j, dsi_cntr;
967 
968   // active continuous
969   contStepVector.sizeUninitialized(numContinuousVars);
970   for (j=0; j<numContinuousVars; ++j)
971     contStepVector[j] = (finalCVPoint[j] - initialCVPoint[j]) / numSteps;
972 
973   // active discrete int: ranges and sets
974   discIntStepVector.sizeUninitialized(numDiscreteIntVars);
975   for (j=0, dsi_cntr=0; j<numDiscreteIntVars; ++j)
976     if (di_set_bits[j]) {
977       discIntStepVector[j] = index_step(
978         set_value_to_index(initialDIVPoint[j], dsi_values[dsi_cntr]),
979 	// for final point defined as index:
980         finalDIVPoint[j], numSteps);
981 	// for final point defined as admissible value:
982         //set_value_to_index(div_final[j], dsi_values[dsi_cntr]), numSteps);
983       ++dsi_cntr;
984     }
985     else
986       discIntStepVector[j]
987 	= integer_step(finalDIVPoint[j] - initialDIVPoint[j], numSteps);
988 
989   // active discrete string: sets only
990   discStringStepVector.sizeUninitialized(numDiscreteStringVars);
991   for (j=0; j<numDiscreteStringVars; ++j)
992     discStringStepVector[j] = index_step(
993       set_value_to_index(initialDSVPoint[j], dss_values[j]),
994       // for final point defined as index:
995       finalDSVPoint[j], numSteps);
996       // for final point defined as admissible value:
997       //set_value_to_index(dsv_final[j], dss_values[j]), numSteps);
998 
999   // active discrete real: sets only
1000   discRealStepVector.sizeUninitialized(numDiscreteRealVars);
1001   for (j=0; j<numDiscreteRealVars; ++j)
1002     discRealStepVector[j] = index_step(
1003       set_value_to_index(initialDRVPoint[j], dsr_values[j]),
1004       // for final point defined as index:
1005       finalDRVPoint[j], numSteps);
1006       // for final point defined as admissible value:
1007       //set_value_to_index(drv_final[j], dsr_values[j]), numSteps);
1008 
1009 #ifdef DEBUG
1010   Cout << "final_point_to_step_vector():\n";
1011   if (numContinuousVars)
1012     Cout << "continuous step vector:\n" << contStepVector;
1013   if (numDiscreteIntVars)
1014     Cout << "discrete int step vector:\n" << discIntStepVector;
1015   if (numDiscreteStringVars) {
1016     Cout << "discrete string step vector:\n";
1017     write_data(Cout, discStringStepVector);
1018   }
1019   if (numDiscreteRealVars)
1020     Cout << "discrete real step vector:\n" << discRealStepVector;
1021 #endif // DEBUG
1022 }
1023 
1024 
1025 bool ParamStudy::
check_sets(const IntVector & c_steps,const IntVector & di_steps,const IntVector & ds_steps,const IntVector & dr_steps)1026 check_sets(const IntVector& c_steps,  const IntVector& di_steps,
1027 	   const IntVector& ds_steps, const IntVector& dr_steps)
1028 {
1029   // checks for vector and centered cases: admissibility of step vectors
1030   // and number of steps among int/real sets
1031   // > check terminal set indices for out of range
1032   // > don't enforce that range variables remain within bounds (for now)
1033   // Note: this check is performed at construct time and is dependent on the
1034   // initial points; therefore, it is not a definitive check in the case of
1035   // multi-iterator execution with updated initial points.  Nonetheless,
1036   // verify proper set support for specified steps.
1037 
1038   const BitArray&      di_set_bits = iteratedModel.discrete_int_sets();
1039   const IntSetArray&    dsi_values = iteratedModel.discrete_set_int_values();
1040   const StringSetArray& dss_values = iteratedModel.discrete_set_string_values();
1041   const RealSetArray&   dsr_values = iteratedModel.discrete_set_real_values();
1042   size_t j, dsi_cntr;
1043   bool err = false;
1044 
1045   // active discrete int: ranges and sets
1046   for (j=0, dsi_cntr=0; j<numDiscreteIntVars; ++j)
1047     if (di_set_bits[j]) {
1048       const IntSet& dsi_vals_j = dsi_values[dsi_cntr];
1049       int terminal_index = set_value_to_index(initialDIVPoint[j], dsi_vals_j)
1050 	+ discIntStepVector[j] * di_steps[j];
1051       if (terminal_index < 0 || terminal_index >= dsi_vals_j.size()) {
1052 	Cerr << "\nError: ParamStudy index " << terminal_index
1053 	     << " not admissible for discrete int set of size "
1054 	     << dsi_vals_j.size() << '.' << std::endl;
1055 	err = true;
1056       }
1057       ++dsi_cntr;
1058     }
1059 
1060   // active discrete string: sets only
1061   for (j=0; j<numDiscreteStringVars; ++j) {
1062     const StringSet& dss_vals_j = dss_values[j];
1063     int terminal_index = set_value_to_index(initialDSVPoint[j], dss_vals_j)
1064       + discStringStepVector[j] * ds_steps[j];
1065     if (terminal_index < 0 || terminal_index >= dss_vals_j.size()) {
1066       Cerr << "\nError: ParamStudy index " << terminal_index
1067 	   << " not admissible for discrete string set of size "
1068 	   << dss_vals_j.size() << '.' << std::endl;
1069       err = true;
1070     }
1071   }
1072 
1073   // active discrete real: sets only
1074   for (j=0; j<numDiscreteRealVars; ++j) {
1075     const RealSet& dsr_vals_j = dsr_values[j];
1076     int terminal_index = set_value_to_index(initialDRVPoint[j], dsr_vals_j)
1077       + discRealStepVector[j] * dr_steps[j];
1078     if (terminal_index < 0 || terminal_index >= dsr_vals_j.size()) {
1079       Cerr << "\nError: ParamStudy index " << terminal_index
1080 	   << " not admissible for discrete real set of size "
1081 	   << dsr_vals_j.size() << '.' << std::endl;
1082       err = true;
1083     }
1084   }
1085 
1086   return err;
1087 }
1088 
1089 
archive_allocate_cps() const1090 void ParamStudy::archive_allocate_cps() const
1091 {
1092   StringMultiArrayConstView cv_labels
1093     = iteratedModel.continuous_variable_labels();
1094   StringMultiArrayConstView div_labels
1095     = iteratedModel.discrete_int_variable_labels();
1096   StringMultiArrayConstView dsv_labels
1097     = iteratedModel.discrete_string_variable_labels();
1098   StringMultiArrayConstView drv_labels
1099     = iteratedModel.discrete_real_variable_labels();
1100   const StringArray& resp_labels
1101     = iteratedModel.response_labels();
1102 
1103   DimScaleMap resp_scales;
1104   resp_scales.emplace(1, StringScale("responses", resp_labels));
1105 
1106   // For centered parameter study, allocate a group per variable
1107   for (size_t i=0; i<numContinuousVars; ++i) {
1108     resultsDB.allocate_vector
1109       ( run_identifier(),
1110 	{String("variable_slices"), cv_labels[i], String("steps")},
1111 	Dakota::ResultsOutputType::REAL,
1112 	2*contStepsPerVariable[i] + 1 );
1113     resultsDB.allocate_matrix
1114       (run_identifier(),
1115        {String("variable_slices"), cv_labels[i], String("responses")},
1116        Dakota::ResultsOutputType::REAL,
1117        2*contStepsPerVariable[i] + 1, numFunctions, resp_scales );
1118   }
1119   for (size_t i=0; i<numDiscreteIntVars; ++i) {
1120     resultsDB.allocate_vector\
1121       ( run_identifier(),
1122 	{String("variable_slices"), div_labels[i], String("steps")},
1123 	Dakota::ResultsOutputType::INTEGER,
1124 	2*discIntStepsPerVariable[i] + 1 );
1125     resultsDB.allocate_matrix
1126       ( run_identifier(),
1127 	{"variable_slices", div_labels[i], String("responses")},
1128 	Dakota::ResultsOutputType::REAL,
1129 	2*discIntStepsPerVariable[i] + 1, numFunctions, resp_scales );
1130   }
1131   for (size_t i=0; i<numDiscreteStringVars; ++i) {
1132     resultsDB.allocate_vector
1133       ( run_identifier(),
1134 	{String("variable_slices"), dsv_labels[i], String("steps")},
1135 	Dakota::ResultsOutputType::STRING,
1136 	2*discStringStepsPerVariable[i] + 1 );
1137     resultsDB.allocate_matrix
1138       ( run_identifier(),
1139 	{String("variable_slices"), dsv_labels[i], String("responses")},
1140 	Dakota::ResultsOutputType::REAL,
1141 	2*discStringStepsPerVariable[i] + 1, numFunctions, resp_scales );
1142   }
1143   for (size_t i=0; i<numDiscreteRealVars; ++i) {
1144     resultsDB.allocate_vector
1145       ( run_identifier(),
1146 	{String("variable_slices"), drv_labels[i], String("steps")},
1147 	Dakota::ResultsOutputType::REAL,
1148 	2*discRealStepsPerVariable[i] + 1 );
1149     resultsDB.allocate_matrix
1150       ( run_identifier(),
1151 	{String("variable_slices"), drv_labels[i], String("responses")},
1152 	Dakota::ResultsOutputType::REAL,
1153 	2*discRealStepsPerVariable[i] + 1, numFunctions, resp_scales );
1154   }
1155 }
1156 
archive_cps_vars(const Model & model,size_t idx) const1157 void ParamStudy::archive_cps_vars(const Model& model, size_t idx) const
1158 {
1159   const RealVector& c_vars  = model.continuous_variables();
1160   const IntVector & di_vars = model.discrete_int_variables();
1161   StringMultiArrayConstView ds_vars = model.discrete_string_variables();
1162   const RealVector& dr_vars = model.discrete_real_variables();
1163 
1164   StringMultiArrayConstView cv_labels
1165     = iteratedModel.continuous_variable_labels();
1166   StringMultiArrayConstView div_labels
1167     = iteratedModel.discrete_int_variable_labels();
1168   StringMultiArrayConstView dsv_labels
1169     = iteratedModel.discrete_string_variable_labels();
1170   StringMultiArrayConstView drv_labels
1171     = iteratedModel.discrete_real_variable_labels();
1172   const StringArray& resp_labels
1173     = iteratedModel.response_labels();
1174 
1175   // center point: store values in midpoint of each var's step results
1176   if (idx == 0) {
1177     for (size_t i=0; i<numContinuousVars; ++i)
1178       resultsDB.insert_into
1179 	( run_identifier(),
1180 	  {String("variable_slices"), cv_labels[i], String("steps")},
1181 	  c_vars[i], contStepsPerVariable[i] );
1182     for (size_t i=0; i<numDiscreteIntVars; ++i)
1183       resultsDB.insert_into
1184 	( run_identifier(),
1185 	  {String("variable_slices"), div_labels[i], String("steps")},
1186 	  di_vars[i], discIntStepsPerVariable[i] );
1187     for (size_t i=0; i<numDiscreteStringVars; ++i)
1188       resultsDB.insert_into
1189 	( run_identifier(),
1190 	  {String("variable_slices"), dsv_labels[i], String("steps")},
1191 	  ds_vars[i], discStringStepsPerVariable[i] );
1192     for (size_t i=0; i<numDiscreteRealVars; ++i)
1193       resultsDB.insert_into
1194 	( run_identifier(),
1195 	  {String("variable_slices"), drv_labels[i], String("steps")},
1196 	  dr_vars[i], discRealStepsPerVariable[i] );
1197     return;
1198   }
1199 
1200   // non-center points; get the variable and within-variable step indices
1201   size_t var_idx = 0, step_idx = 0;
1202   index_to_var_step(idx, var_idx, step_idx);
1203 
1204   if (var_idx < numContinuousVars) {
1205     size_t cv_idx = var_idx;
1206     resultsDB.insert_into
1207       ( run_identifier(),
1208 	{String("variable_slices"), cv_labels[cv_idx], String("steps")},
1209 	c_vars[cv_idx], step_idx );
1210   }
1211   else if (var_idx < numContinuousVars + numDiscreteIntVars) {
1212     size_t div_idx = var_idx - numContinuousVars;
1213     resultsDB.insert_into
1214       ( run_identifier(),
1215         {String("variable_slices"), div_labels[div_idx], String("steps")},
1216         di_vars[div_idx], step_idx );
1217   }
1218   else if (var_idx <
1219 	   numContinuousVars + numDiscreteIntVars + numDiscreteStringVars) {
1220     size_t dsv_idx = var_idx - numContinuousVars - numDiscreteIntVars;
1221     resultsDB.insert_into
1222       ( run_identifier(),
1223 	{String("variable_slices"), dsv_labels[dsv_idx], String("steps")},
1224 	ds_vars[dsv_idx], step_idx );
1225   }
1226   else {
1227     size_t drv_idx =
1228       var_idx - numContinuousVars - numDiscreteIntVars - numDiscreteStringVars;
1229     resultsDB.insert_into
1230       ( run_identifier(),
1231         {String("variable_slices"), drv_labels[drv_idx], String("steps")},
1232         dr_vars[drv_idx], step_idx );
1233   }
1234 }
1235 
1236 
archive_cps_resp(const Response & response,size_t idx) const1237 void ParamStudy::archive_cps_resp(const Response& response, size_t idx) const
1238 {
1239   StringMultiArrayConstView cv_labels
1240     = iteratedModel.continuous_variable_labels();
1241   StringMultiArrayConstView div_labels
1242     = iteratedModel.discrete_int_variable_labels();
1243   StringMultiArrayConstView dsv_labels
1244     = iteratedModel.discrete_string_variable_labels();
1245   StringMultiArrayConstView drv_labels
1246     = iteratedModel.discrete_real_variable_labels();
1247   const StringArray& resp_labels
1248     = iteratedModel.response_labels();
1249 
1250   const RealVector& resp_vec = response.function_values();
1251 
1252   // center point: store values in midpoint of each var's response results
1253   if (idx == 0) {
1254     for (size_t i=0; i<numContinuousVars; ++i)
1255       resultsDB.insert_into
1256 	( run_identifier(),
1257 	  {String("variable_slices"), cv_labels[i], String("responses")},
1258 	  resp_vec, contStepsPerVariable[i] );
1259     for (size_t i=0; i<numDiscreteIntVars; ++i)
1260       resultsDB.insert_into
1261 	( run_identifier(),
1262 	  {String("variable_slices"), div_labels[i], String("responses")},
1263 	  resp_vec, discIntStepsPerVariable[i] );
1264     for (size_t i=0; i<numDiscreteStringVars; ++i)
1265       resultsDB.insert_into
1266 	( run_identifier(),
1267 	  {String("variable_slices"), dsv_labels[i], String("responses")},
1268 	  resp_vec, discStringStepsPerVariable[i] );
1269     for (size_t i=0; i<numDiscreteRealVars; ++i)
1270       resultsDB.insert_into
1271 	( run_identifier(),
1272 	  {String("variable_slices"), drv_labels[i], String("responses")},
1273 	  resp_vec, discRealStepsPerVariable[i] );
1274     return;
1275   }
1276 
1277   // non-center points; get the variable and within-variable step indices
1278    size_t var_idx = 0, step_idx = 0;
1279    index_to_var_step(idx, var_idx, step_idx);
1280 
1281    if (var_idx < numContinuousVars) {
1282      size_t cv_idx = var_idx;
1283      resultsDB.insert_into
1284        ( run_identifier(),
1285 	 {String("variable_slices"), cv_labels[cv_idx], String("responses")},
1286 	 resp_vec, step_idx );
1287    }
1288    else if (var_idx < numContinuousVars + numDiscreteIntVars) {
1289      size_t div_idx = var_idx - numContinuousVars;
1290      resultsDB.insert_into
1291        ( run_identifier(),
1292 	 {String("variable_slices"), div_labels[div_idx], String("responses")},
1293 	 resp_vec, step_idx );
1294    }
1295    else if (var_idx <
1296 	    numContinuousVars + numDiscreteIntVars + numDiscreteStringVars) {
1297      size_t dsv_idx = var_idx - numContinuousVars - numDiscreteIntVars;
1298      resultsDB.insert_into
1299        ( run_identifier(),
1300 	 {String("variable_slices"), dsv_labels[dsv_idx], String("responses")},
1301 	 resp_vec, step_idx );
1302    }
1303    else {
1304      size_t drv_idx =
1305        var_idx - numContinuousVars - numDiscreteIntVars - numDiscreteStringVars;
1306      resultsDB.insert_into
1307        ( run_identifier(),
1308 	 {String("variable_slices"), drv_labels[drv_idx], String("responses")},
1309 	 resp_vec, step_idx );
1310    }
1311 }
1312 
1313 
index_to_var_step(const size_t study_idx,size_t & var_idx,size_t & step_idx) const1314 void ParamStudy::index_to_var_step(const size_t study_idx,
1315 				   size_t& var_idx, size_t& step_idx) const
1316 {
1317   size_t num_vars = numContinuousVars + numDiscreteIntVars
1318     + numDiscreteStringVars + numDiscreteRealVars;
1319 
1320   // 0 <= study_idx <= sum_i(2*spv[i])
1321 
1322   // the zero-th eval is the center point; the steps for the first
1323   // variable start at offset index = 1
1324   size_t offset = 1;
1325   for (var_idx = 0; var_idx < num_vars; ++var_idx) {
1326     if (study_idx < offset + 2*stepsPerVariable[var_idx])
1327       break;
1328     offset += 2*stepsPerVariable[var_idx];
1329   }
1330 
1331   // determine the index into the var_idx-th variable steps,
1332   // accounting for the missing center point in the middle, where
1333   // step_idx is the middle index
1334   step_idx = ( study_idx - offset < stepsPerVariable[var_idx] ) ?
1335     (study_idx - offset) : (study_idx - offset + 1);
1336 }
1337 
1338 
1339 } // namespace Dakota
1340