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:        Interface
10 //- Description:  Class implementation for abstract interface base class
11 //- Owner:        Michael Eldred
12 
13 #include "DakotaInterface.hpp"
14 #include "ProblemDescDB.hpp"
15 #include "DakotaVariables.hpp"
16 
17 #include "SysCallApplicInterface.hpp"
18 
19 #if defined(HAVE_SYS_WAIT_H) && defined(HAVE_UNISTD_H)
20 #include "ForkApplicInterface.hpp"
21 #elif defined(_WIN32) // or _MSC_VER (native MSVS compilers)
22 #include "SpawnApplicInterface.hpp"
23 #endif // HAVE_SYS_WAIT_H, HAVE_UNISTD_H
24 
25 // Direct interfaces
26 #ifdef DAKOTA_GRID
27 #include "GridApplicInterface.hpp"
28 #endif // DAKOTA_GRID
29 #ifdef DAKOTA_MATLAB
30 #include "MatlabInterface.hpp"
31 #endif // DAKOTA_MATLAB
32 #ifdef DAKOTA_PYTHON
33 #include "PythonInterface.hpp"
34 #endif // DAKOTA_PYTHON
35 #ifdef DAKOTA_SCILAB
36 #include "ScilabInterface.hpp"
37 #endif // DAKOTA_SCILAB
38 #include "TestDriverInterface.hpp"
39 
40 #include "ApproximationInterface.hpp"
41 
42 #ifdef HAVE_AMPL
43 #undef NO // avoid name collision from UTILIB
44 #include "external/ampl/asl.h"
45 #endif // HAVE_AMPL
46 
47 //#define DEBUG
48 
49 namespace Dakota {
50 
51 // Initialization of static interface ID counters
52 size_t Interface::noSpecIdNum = 0;
53 
54 
55 /** This constructor is the one which must build the base class data for all
56     inherited interfaces.  get_interface() instantiates a derived class letter
57     and the derived constructor selects this base class constructor in its
58     initialization list (to avoid the recursion of the base class constructor
59     calling get_interface() again).  Since this is the letter and the letter
60     IS the representation, interfaceRep is set to NULL. */
Interface(BaseConstructor,const ProblemDescDB & problem_db)61 Interface::Interface(BaseConstructor, const ProblemDescDB& problem_db):
62   interfaceType(problem_db.get_ushort("interface.type")),
63   interfaceId(problem_db.get_string("interface.id")),
64   analysisComponents(
65     problem_db.get_s2a("interface.application.analysis_components")),
66   algebraicMappings(false),
67   coreMappings(true), outputLevel(problem_db.get_short("method.output")),
68   currEvalId(0), fineGrainEvalCounters(outputLevel > NORMAL_OUTPUT),
69   evalIdCntr(0), newEvalIdCntr(0), evalIdRefPt(0), newEvalIdRefPt(0),
70   multiProcEvalFlag(false), ieDedMasterFlag(false),
71   // See base constructor in DakotaIterator.cpp for full discussion of output
72   // verbosity.  Interfaces support the full granularity in verbosity.
73   appendIfaceId(true), asl(NULL)
74 {
75 #ifdef DEBUG
76   outputLevel = DEBUG_OUTPUT;
77 #endif // DEBUG
78   if(interfaceId.empty())
79       interfaceId = user_auto_id();
80   // Process the algebraic_mappings file (an AMPL .nl file) to get the number
81   // of variables/responses (currently, the tags are converted to index arrays
82   // at evaluation time, using the passed vars and response).
83   // TO DO: parallel bcast of data or very proc reads file?
84   const String& ampl_file_name
85     = problem_db.get_string("interface.algebraic_mappings");
86   if (!ampl_file_name.empty()) {
87 #ifdef HAVE_AMPL
88     algebraicMappings = true;
89     bool hess_flag
90       = (problem_db.get_string("responses.hessian_type") == "analytic");
91     asl = (hess_flag) ? ASL_alloc(ASL_read_pfgh) : ASL_alloc(ASL_read_fg);
92     // allow user input of either stub or stub.nl
93     String stub = (strends(ampl_file_name, ".nl")) ?
94       String(ampl_file_name, 0, ampl_file_name.size() - 3) : ampl_file_name;
95     //std::ifstream ampl_nl(ampl_file_name);
96     fint stub_str_len = stub.size();
97     // BMA NOTE: casting away the constness as done historically in DakotaString
98     char* nonconst_stub = (char*) stub.c_str();
99     FILE* ampl_nl = jac0dim(nonconst_stub, stub_str_len);
100     if (!ampl_nl) {
101       Cerr << "\nError: failure opening " << ampl_file_name << std::endl;
102       abort_handler(IO_ERROR);
103     }
104     int rtn = (hess_flag) ? pfgh_read(ampl_nl, ASL_return_read_err)
105                           :   fg_read(ampl_nl, ASL_return_read_err);
106     if (rtn) {
107       Cerr << "\nError: AMPL processing problem with " << ampl_file_name
108 	   << std::endl;
109       abort_handler(IO_ERROR);
110     }
111 
112     // extract input/output tag lists
113     String row = stub + ".row", col = stub + ".col", ampl_tag;
114 
115     std::ifstream ampl_col(col.c_str());
116     if (!ampl_col) {
117       Cerr << "\nError: failure opening " << col << std::endl;
118       abort_handler(IO_ERROR);
119     }
120     algebraicVarTags.resize(n_var);
121     for (size_t i=0; i<n_var; i++) {
122       std::getline(ampl_col, ampl_tag);
123       if (ampl_col.good())
124 	algebraicVarTags[i] = ampl_tag;
125       else {
126 	Cerr << "\nError: failure reading AMPL col file " << col
127 	     << std::endl;
128 	abort_handler(IO_ERROR);
129       }
130     }
131 
132     std::ifstream ampl_row(row.c_str());
133     if (!ampl_row) {
134       Cerr << "\nError: failure opening " << row << std::endl;
135       abort_handler(IO_ERROR);
136     }
137     algebraicFnTags.resize(n_obj+n_con);
138     algebraicFnTypes.resize(n_obj+n_con);
139     algebraicConstraintWeights.resize(n_con);
140     for (size_t i=0; i<n_obj+n_con; i++) {
141       getline(ampl_row, ampl_tag);
142       if (ampl_row.good()) {
143 	algebraicFnTags[i] = ampl_tag;
144 	algebraicFnTypes[i] = algebraic_function_type(ampl_tag);
145       }
146       else {
147 	Cerr << "\nError: failure reading AMPL row file " << row
148 	     << std::endl;
149 	abort_handler(IO_ERROR);
150       }
151     }
152 
153 #ifdef DEBUG
154     Cout << ">>>>> algebraicVarTags =\n" << algebraicVarTags
155 	 << "\n>>>>> algebraicFnTags =\n" << algebraicFnTags
156 	 << "\n>>>>> algebraicFnTypes =\n" << algebraicFnTypes << std::endl;
157 #endif
158 
159 #else
160     Cerr << "\nError: algebraic_mappings not supported without the AMPL solver "
161 	 << "library provided with the Acro package." << std::endl;
162     abort_handler(-1);
163 #endif // HAVE_AMPL
164   }
165 }
166 
167 
Interface(NoDBBaseConstructor,size_t num_fns,short output_level)168 Interface::Interface(NoDBBaseConstructor, size_t num_fns, short output_level):
169   interfaceId(no_spec_id()), algebraicMappings(false), coreMappings(true),
170   outputLevel(output_level), currEvalId(0),
171   fineGrainEvalCounters(outputLevel > NORMAL_OUTPUT), evalIdCntr(0),
172   newEvalIdCntr(0), evalIdRefPt(0), newEvalIdRefPt(0), multiProcEvalFlag(false),
173   ieDedMasterFlag(false), appendIfaceId(true)
174 {
175 #ifdef DEBUG
176   outputLevel = DEBUG_OUTPUT;
177 #endif // DEBUG
178 }
179 
180 
181 /** used in Model envelope class instantiations */
Interface()182 Interface::Interface()
183 { }
184 
185 
186 /** Used in Model instantiation to build the envelope.  This constructor
187     only needs to extract enough data to properly execute get_interface, since
188     Interface::Interface(BaseConstructor, problem_db) builds the
189     actual base class data inherited by the derived interfaces. */
Interface(ProblemDescDB & problem_db)190 Interface::Interface(ProblemDescDB& problem_db):
191   // Set the rep pointer to the appropriate interface type
192   interfaceRep(get_interface(problem_db))
193 {
194   if (!interfaceRep) // bad type or insufficient memory
195     abort_handler(-1);
196 }
197 
198 
199 /** used only by the envelope constructor to initialize interfaceRep
200     to the appropriate derived type. */
get_interface(ProblemDescDB & problem_db)201 std::shared_ptr<Interface> Interface::get_interface(ProblemDescDB& problem_db)
202 {
203   const unsigned short interface_type = problem_db.get_ushort("interface.type");
204 
205   // In the case where a derived interface type has been selected for managing
206   // analysis_drivers, then this determines the letter instantiation and any
207   // algebraic mappings are overlayed by ApplicationInterface.
208   const String& algebraic_map_file
209     = problem_db.get_string("interface.algebraic_mappings");
210   if (interface_type == SYSTEM_INTERFACE)
211     return std::make_shared<SysCallApplicInterface>(problem_db);
212   else if (interface_type == FORK_INTERFACE) {
213 #if defined(HAVE_SYS_WAIT_H) && defined(HAVE_UNISTD_H) // includes CYGWIN/MINGW
214     return std::make_shared<ForkApplicInterface>(problem_db);
215 #elif defined(_WIN32) // or _MSC_VER (native MSVS compilers)
216     return std::make_shared<SpawnApplicInterface>(problem_db);
217 #else
218     Cerr << "Fork interface requested, but not enabled in this DAKOTA "
219 	 << "executable." << std::endl;
220     return std::shared_ptr<Interface>();
221 #endif
222   }
223 
224   else if (interface_type == TEST_INTERFACE)
225     return std::make_shared<TestDriverInterface>(problem_db);
226   // Note: in the case of a plug-in direct interface, this object gets replaced
227   // using Interface::assign_rep().  Error checking in DirectApplicInterface::
228   // derived_map_ac() should catch if this replacement fails to occur properly.
229 
230 #ifdef DAKOTA_GRID
231   else if (interface_type == GRID_INTERFACE)
232     return std::make_shared<GridApplicInterface>(problem_db);
233 #endif
234 
235   else if (interface_type == MATLAB_INTERFACE) {
236 #ifdef DAKOTA_MATLAB
237     return std::make_shared<MatlabInterface>(problem_db);
238 #else
239     Cerr << "Direct Matlab interface requested, but not enabled in this "
240 	 << "DAKOTA executable." << std::endl;
241     return std::shared_ptr<Interface>();
242 #endif
243   }
244 
245   else if (interface_type == PYTHON_INTERFACE) {
246 #ifdef DAKOTA_PYTHON
247     return std::make_shared<PythonInterface>(problem_db);
248 #else
249     Cerr << "Direct Python interface requested, but not enabled in this "
250 	 << "DAKOTA executable." << std::endl;
251     return std::shared_ptr<Interface>();
252 #endif
253   }
254 
255   else if (interface_type == SCILAB_INTERFACE) {
256 #ifdef DAKOTA_SCILAB
257     return std::make_shared<ScilabInterface>(problem_db);
258 #else
259     Cerr << "Direct Scilab interface requested, but not enabled in this "
260 	 << "DAKOTA executable." << std::endl;
261     return std::shared_ptr<Interface>();
262 #endif
263   }
264 
265   // Should not be needed since ApproximationInterface is plugged-in from
266   // DataFitSurrModel using Interface::assign_rep().
267   //else if (interface_type == APPROX_INTERFACE)
268   //  return std::make_shared<ApproximationInterface>(problem_db, num_acv, num_fns);
269 
270   // In the case where only algebraic mappings are used, then no derived map
271   // functionality is needed and ApplicationInterface is used for the letter.
272   else if (!algebraic_map_file.empty()) {
273 #ifdef DEBUG
274     Cout << ">>>>> new ApplicationInterface: " << algebraic_map_file
275 	 << std::endl;
276 #endif // DEBUG
277     return std::make_shared<ApplicationInterface>(problem_db);
278   }
279 
280   // If the interface type is empty (e.g., from default DataInterface creation
281   // in ProblemDescDB::check_input()), then ApplicationInterface is the letter.
282   else if (interface_type == DEFAULT_INTERFACE) {
283     Cerr << "Warning: empty interface type in Interface::get_interface()."
284 	 << std::endl;
285     return std::make_shared<ApplicationInterface>(problem_db);
286   }
287 
288   else {
289     Cerr << "Invalid interface: " << interface_enum_to_string(interface_type)
290 	 << std::endl;
291   }
292 
293   return std::shared_ptr<Interface>();
294 }
295 
296 
297 /** Copy constructor manages sharing of interfaceRep */
Interface(const Interface & interface_in)298 Interface::Interface(const Interface& interface_in):
299   interfaceRep(interface_in.interfaceRep)
300 { /* empty ctor */ }
301 
302 
operator =(const Interface & interface_in)303 Interface Interface::operator=(const Interface& interface_in)
304 {
305   interfaceRep = interface_in.interfaceRep;
306   return *this; // calls copy constructor since returned by value
307 }
308 
309 
~Interface()310 Interface::~Interface()
311 { /* empty dtor */ }
312 
313 
314 /** DEPRECATED but temporarily left for library mode clients needing to
315     MIGRATE TO shared_ptr API
316 
317     Similar to the assignment operator, the assign_rep() function
318     decrements referenceCount for the old interfaceRep and assigns the
319     new interfaceRep.  It is different in that it is used for
320     publishing derived class letters to existing envelopes, as opposed
321     to sharing representations among multiple envelopes (in
322     particular, assign_rep is passed a letter object and operator= is
323     passed an envelope object).  Letter assignment historically
324     supported two models as governed by ref_count_incr:
325 
326     \li ref_count_incr = true (removed): the incoming letter belongs
327     to another envelope.  In this case, increment the reference count
328     in the normal manner so that deallocation of the letter is handled
329     properly.
330 
331     \li ref_count_incr = false (always): the incoming letter is
332     instantiated on the fly and has no envelope.  This case is modeled
333     after get_interface(): a letter is dynamically allocated using new
334     and passed into assign_rep, the letter's reference count is not
335     incremented, and the letter is not remotely deleted (its memory
336     management is passed over to the envelope). */
assign_rep(Interface * interface_rep,bool ref_count_incr)337 void Interface::assign_rep(Interface* interface_rep, bool ref_count_incr)
338 {
339   interfaceRep.reset(interface_rep);
340 }
341 
342 
343 /** The assign_rep() function is used for publishing derived class
344     letters to existing envelopes, as opposed to sharing
345     representations among multiple envelopes (in particular,
346     assign_rep is passed a letter object and operator= is passed an
347     envelope object).
348 
349     Use case assumes the incoming letter is instantiated on the fly
350     and has no envelope.  This case is modeled after get_interface(): a
351     letter is dynamically allocated and passed into assign_rep (its
352     memory management is passed over to the envelope).
353 
354     If the letter happens to be managed by another envelope, it will
355     persist as long as the last envelope referencing it. */
assign_rep(std::shared_ptr<Interface> interface_rep)356 void Interface::assign_rep(std::shared_ptr<Interface> interface_rep)
357 {
358   interfaceRep = interface_rep;
359 }
360 
361 
fine_grained_evaluation_counters(size_t num_fns)362 void Interface::fine_grained_evaluation_counters(size_t num_fns)
363 {
364   if (interfaceRep) // envelope fwd to letter
365     interfaceRep->fine_grained_evaluation_counters(num_fns);
366   else if (!fineGrainEvalCounters) { // letter (not virtual)
367     init_evaluation_counters(num_fns);
368     fineGrainEvalCounters = true;
369   }
370 }
371 
372 
init_evaluation_counters(size_t num_fns)373 void Interface::init_evaluation_counters(size_t num_fns)
374 {
375   if (interfaceRep) // envelope fwd to letter
376     interfaceRep->init_evaluation_counters(num_fns);
377   else { // letter (not virtual)
378     //if (fnLabels.empty()) {
379     //  fnLabels.resize(num_fns);
380     //  build_labels(fnLabels, "response_fn_"); // generic resp fn labels
381     //}
382     if (fnValCounter.size() != num_fns) {
383       fnValCounter.assign(num_fns, 0);     fnGradCounter.assign(num_fns, 0);
384       fnHessCounter.assign(num_fns, 0);    newFnValCounter.assign(num_fns, 0);
385       newFnGradCounter.assign(num_fns, 0); newFnHessCounter.assign(num_fns, 0);
386       fnValRefPt.assign(num_fns, 0);       fnGradRefPt.assign(num_fns, 0);
387       fnHessRefPt.assign(num_fns, 0);      newFnValRefPt.assign(num_fns, 0);
388       newFnGradRefPt.assign(num_fns, 0);   newFnHessRefPt.assign(num_fns, 0);
389     }
390   }
391 }
392 
393 
set_evaluation_reference()394 void Interface::set_evaluation_reference()
395 {
396   if (interfaceRep) // envelope fwd to letter
397     interfaceRep->set_evaluation_reference();
398   else { // letter (not virtual)
399 
400     evalIdRefPt    = evalIdCntr;
401     newEvalIdRefPt = newEvalIdCntr;
402 
403     if (fineGrainEvalCounters) {
404       size_t i, num_fns = fnValCounter.size();
405       for (i=0; i<num_fns; i++) {
406 	fnValRefPt[i]     =     fnValCounter[i];
407 	newFnValRefPt[i]  =  newFnValCounter[i];
408 	fnGradRefPt[i]    =    fnGradCounter[i];
409 	newFnGradRefPt[i] = newFnGradCounter[i];
410 	fnHessRefPt[i]    =    fnHessCounter[i];
411 	newFnHessRefPt[i] = newFnHessCounter[i];
412       }
413     }
414   }
415 }
416 
417 
418 void Interface::
print_evaluation_summary(std::ostream & s,bool minimal_header,bool relative_count) const419 print_evaluation_summary(std::ostream& s, bool minimal_header,
420 			 bool relative_count) const
421 {
422   if (interfaceRep) // envelope fwd to letter
423     interfaceRep->print_evaluation_summary(s, minimal_header, relative_count);
424   else { // letter (not virtual)
425 
426     // standard evaluation summary
427     if (minimal_header) {
428       if (interfaceId.empty() || interfaceId == "NO_ID")
429 	s << "  Interface evaluations";
430       else
431 	s << "  " << interfaceId << " evaluations";
432     }
433     else {
434       s << "<<<<< Function evaluation summary";
435       if (!(interfaceId.empty() || interfaceId == "NO_ID"))
436 	s << " (" << interfaceId << ')';
437     }
438     int     fn_evals = (relative_count) ? evalIdCntr - evalIdRefPt
439                                         : evalIdCntr;
440     int new_fn_evals = (relative_count) ? newEvalIdCntr - newEvalIdRefPt
441                                         : newEvalIdCntr;
442     s << ": " << fn_evals << " total (" << new_fn_evals << " new, "
443       << fn_evals - new_fn_evals << " duplicate)\n";
444 
445     // detailed evaluation summary
446     if (fineGrainEvalCounters) {
447       size_t i, num_fns = std::min(fnValCounter.size(), fnLabels.size());
448       for (i=0; i<num_fns; i++) {
449 	int t_v = (relative_count) ?     fnValCounter[i] -     fnValRefPt[i]
450 	                           :     fnValCounter[i];
451 	int n_v = (relative_count) ?  newFnValCounter[i] -  newFnValRefPt[i]
452 	                           :  newFnValCounter[i];
453 	int t_g = (relative_count) ?    fnGradCounter[i] -    fnGradRefPt[i]
454 	                           :    fnGradCounter[i];
455 	int n_g = (relative_count) ? newFnGradCounter[i] - newFnGradRefPt[i]
456 	                           : newFnGradCounter[i];
457 	int t_h = (relative_count) ?    fnHessCounter[i] -    fnHessRefPt[i]
458 	                           :    fnHessCounter[i];
459 	int n_h = (relative_count) ? newFnHessCounter[i] - newFnHessRefPt[i]
460 	                           : newFnHessCounter[i];
461 	s << std::setw(15) << fnLabels[i] << ": "
462 	  << t_v << " val ("  << n_v << " n, " << t_v - n_v << " d), "
463 	  << t_g << " grad (" << n_g << " n, " << t_g - n_g << " d), "
464 	  << t_h << " Hess (" << n_h << " n, " << t_h - n_h << " d)\n";
465       }
466     }
467   }
468 }
469 
470 
471 /// default implementation just sets the list of eval ID tags;
472 /// derived classes containing additional models or interfaces should
473 /// override (currently no use cases)
474 void Interface::
eval_tag_prefix(const String & eval_id_str,bool append_iface_id)475 eval_tag_prefix(const String& eval_id_str, bool append_iface_id)
476 {
477   if (interfaceRep)
478     interfaceRep->eval_tag_prefix(eval_id_str, append_iface_id);
479   else {
480     evalTagPrefix = eval_id_str;
481     appendIfaceId = append_iface_id;
482   }
483 }
484 
485 
map(const Variables & vars,const ActiveSet & set,Response & response,bool asynch_flag)486 void Interface::map(const Variables& vars, const ActiveSet& set,
487 		    Response& response, bool asynch_flag)
488 {
489   if (interfaceRep) // envelope fwd to letter
490     interfaceRep->map(vars, set, response, asynch_flag);
491   else { // letter lacking redefinition of virtual fn.
492     Cerr << "Error: Letter lacking redefinition of virtual map function.\n"
493          << "No default map defined at Interface base class." << std::endl;
494     abort_handler(-1);
495   }
496 }
497 
498 
499 void Interface::
init_algebraic_mappings(const Variables & vars,const Response & response)500 init_algebraic_mappings(const Variables& vars, const Response& response)
501 {
502   size_t i, num_alg_vars = algebraicVarTags.size(),
503     num_alg_fns = algebraicFnTags.size();
504 
505   algebraicACVIndices.resize(num_alg_vars);
506   algebraicACVIds.resize(num_alg_vars);
507   StringMultiArrayConstView acv_labels = vars.all_continuous_variable_labels();
508   SizetMultiArrayConstView  acv_ids    = vars.all_continuous_variable_ids();
509   for (i=0; i<num_alg_vars; ++i) {
510     // Note: variable mappings only support continuous variables.
511     //       discrete variables are not directly supported by ASL interface.
512     size_t acv_index = find_index(acv_labels, algebraicVarTags[i]);
513     //size_t adv_index = find_index(adv_labels, algebraicVarTags[i]);
514     if (acv_index == _NPOS) { // && adv_index == _NPOS) {
515       Cerr << "\nError: AMPL column label " << algebraicVarTags[i] << " does "
516 	   <<"not exist in DAKOTA continuous variable descriptors.\n"
517 	   << std::endl;
518       abort_handler(INTERFACE_ERROR);
519     }
520     else {
521       algebraicACVIndices[i] = acv_index;
522       //algebraicADVIndices[i] = adv_index;
523       algebraicACVIds[i] = acv_ids[acv_index];
524     }
525   }
526 
527   algebraicFnIndices.resize(num_alg_fns);
528   const StringArray& fn_labels = response.function_labels();
529   for (size_t i=0; i<num_alg_fns; ++i) {
530     size_t fn_index = Pecos::find_index(fn_labels, algebraicFnTags[i]);
531     if (fn_index == _NPOS) {
532       Cerr << "\nError: AMPL row label " << algebraicFnTags[i] << " does not "
533 	   <<"exist in DAKOTA response descriptors.\n" << std::endl;
534       abort_handler(INTERFACE_ERROR);
535     }
536     else
537       algebraicFnIndices[i] = fn_index;
538   }
539 }
540 
541 
542 void Interface::
asv_mapping(const ActiveSet & total_set,ActiveSet & algebraic_set,ActiveSet & core_set)543 asv_mapping(const ActiveSet& total_set, ActiveSet& algebraic_set,
544 	    ActiveSet& core_set)
545 {
546   const ShortArray& total_asv = total_set.request_vector();
547   const SizetArray& total_dvv = total_set.derivative_vector();
548 
549   // algebraic_asv/dvv:
550 
551   // the algebraic active set is defined over reduced algebraic function
552   // and variable spaces, rather than the original spaces.  This simplifies
553   // algebraic_mappings() and allows direct copies of data from AMPL.
554   size_t i, num_alg_fns = algebraicFnTags.size(),
555     num_alg_vars = algebraicVarTags.size();
556   ShortArray algebraic_asv(num_alg_fns);
557   SizetArray algebraic_dvv(num_alg_vars);
558   for (i=0; i<num_alg_fns; i++) // map total_asv to algebraic_asv
559     algebraic_asv[i] = total_asv[algebraicFnIndices[i]];
560 
561   algebraic_set.request_vector(algebraic_asv);
562   algebraic_set.derivative_vector(algebraic_dvv);
563   algebraic_set.derivative_start_value(1);
564 
565   // core_asv/dvv:
566 
567   // for now, core_asv is the same as total_asv, since there is no mechanism
568   // yet to determine if the algebraic_mapping portion is the complete
569   // definition (for which core_asv requests could be turned off).
570   core_set.request_vector(total_asv);
571   core_set.derivative_vector(total_dvv);
572 }
573 
574 
575 void Interface::
asv_mapping(const ActiveSet & algebraic_set,ActiveSet & total_set)576 asv_mapping(const ActiveSet& algebraic_set, ActiveSet& total_set)
577 {
578   const ShortArray& algebraic_asv = algebraic_set.request_vector();
579   size_t i, num_alg_fns = algebraicFnTags.size();
580   for (i=0; i<num_alg_fns; i++) // map algebraic_asv to total_asv
581     total_set.request_value(algebraic_asv[i], algebraicFnIndices[i]);
582 }
583 
584 
585 void Interface::
algebraic_mappings(const Variables & vars,const ActiveSet & algebraic_set,Response & algebraic_response)586 algebraic_mappings(const Variables& vars, const ActiveSet& algebraic_set,
587 		   Response& algebraic_response)
588 {
589 #ifdef HAVE_AMPL
590   // make sure cur_ASL is pointing to the ASL of this interface
591   // this is important for problems with multiple interfaces
592   set_cur_ASL(asl);
593   const ShortArray& algebraic_asv = algebraic_set.request_vector();
594   const SizetArray& algebraic_dvv = algebraic_set.derivative_vector();
595   size_t i, num_alg_fns = algebraic_asv.size(),
596     num_alg_vars = algebraic_dvv.size();
597   bool grad_flag = false, hess_flag = false;
598   for (i=0; i<num_alg_fns; ++i) {
599     if (algebraic_asv[i] & 2)
600       grad_flag = true;
601     if (algebraic_asv[i] & 4)
602       hess_flag = true;
603   }
604 
605   // dak_a_c_vars (DAKOTA space) -> nl_vars (reduced AMPL space)
606   const RealVector& dak_a_c_vars = vars.all_continuous_variables();
607   //IntVector  dak_a_d_vars = vars.all_discrete_variables();
608   Real* nl_vars = new Real [num_alg_vars];
609   for (i=0; i<num_alg_vars; i++)
610     nl_vars[i] = dak_a_c_vars[algebraicACVIndices[i]];
611 
612   // nl_vars -> algebraic_response
613   algebraic_response.reset_inactive(); // zero inactive data
614   Real fn_val; RealVector fn_grad; RealSymMatrix fn_hess;
615   fint err = 0;
616   for (i=0; i<num_alg_fns; i++) {
617     // nl_vars -> response fns via AMPL
618     if (algebraic_asv[i] & 1) {
619       if (algebraicFnTypes[i] > 0)
620 	fn_val = objval(algebraicFnTypes[i]-1, nl_vars, &err);
621       else
622 	fn_val = conival(-1-algebraicFnTypes[i], nl_vars, &err);
623       if (err) {
624 	Cerr << "\nError: AMPL processing failure in objval().\n" << std::endl;
625 	abort_handler(INTERFACE_ERROR);
626       }
627       algebraic_response.function_value(fn_val, i);
628     }
629     // nl_vars -> response grads via AMPL
630     if (algebraic_asv[i] & 6) { // need grad for Hessian
631       fn_grad = algebraic_response.function_gradient_view(i);
632       if (algebraicFnTypes[i] > 0)
633 	objgrd(algebraicFnTypes[i]-1, nl_vars, fn_grad.values(), &err);
634       else
635 	congrd(-1-algebraicFnTypes[i], nl_vars, fn_grad.values(), &err);
636       if (err) {
637 	Cerr << "\nError: AMPL processing failure in objgrad().\n" << std::endl;
638 	abort_handler(INTERFACE_ERROR);
639       }
640     }
641     // nl_vars -> response Hessians via AMPL
642     if (algebraic_asv[i] & 4) {
643       fn_hess = algebraic_response.function_hessian_view(i);
644       // the fullhess calls must follow corresp call to objgrad/congrad
645       if (algebraicFnTypes[i] > 0)
646 	fullhes(fn_hess.values(), num_alg_vars, algebraicFnTypes[i]-1,
647 		NULL, NULL);
648       else {
649 	algebraicConstraintWeights.assign(algebraicConstraintWeights.size(), 0);
650 	algebraicConstraintWeights[-1-algebraicFnTypes[i]] = 1;
651 	fullhes(fn_hess.values(), num_alg_vars, num_alg_vars, NULL,
652 		&algebraicConstraintWeights[0]);
653       }
654     }
655   }
656   delete [] nl_vars;
657   algebraic_response.function_labels(algebraicFnTags);
658 #ifdef DEBUG
659   Cout << ">>>>> algebraic_response.fn_labels\n"
660        << algebraic_response.function_labels() << std::endl;
661 #endif // DEBUG
662 
663   if (outputLevel > NORMAL_OUTPUT)
664     Cout << "Algebraic mapping applied.\n";
665 #endif // HAVE_AMPL
666 }
667 
668 
669 /** This function will get invoked even when only algebraic mappings are
670     active (no core mappings from derived_map), since the AMPL
671     algebraic_response may be ordered differently from the total_response.
672     In this case, the core_response object is unused. */
673 void Interface::
response_mapping(const Response & algebraic_response,const Response & core_response,Response & total_response)674 response_mapping(const Response& algebraic_response,
675 		 const Response& core_response, Response& total_response)
676 {
677   const ShortArray& total_asv = total_response.active_set_request_vector();
678   const SizetArray& total_dvv = total_response.active_set_derivative_vector();
679   size_t i, j, k, num_total_fns = total_asv.size(),
680     num_total_vars = total_dvv.size();
681   bool grad_flag = false, hess_flag = false;
682   for (i=0; i<num_total_fns; ++i) {
683     if (total_asv[i] & 2)
684       grad_flag = true;
685     if (total_asv[i] & 4)
686       hess_flag = true;
687   }
688 
689   // core_response contributions to total_response:
690 
691   if (coreMappings) {
692     total_response.reset_inactive();
693     const ShortArray& core_asv = core_response.active_set_request_vector();
694     size_t num_core_fns = core_asv.size();
695     for (i=0; i<num_core_fns; ++i) {
696       if (core_asv[i] & 1)
697 	total_response.function_value(core_response.function_value(i), i);
698       if (core_asv[i] & 2)
699 	total_response.function_gradient(
700 	  core_response.function_gradient_view(i), i);
701       if (core_asv[i] & 4)
702 	total_response.function_hessian(core_response.function_hessian(i), i);
703     }
704   }
705   else {
706     // zero all response data before adding algebraic data to it
707     total_response.reset();
708   }
709 
710   // algebraic_response contributions to total_response:
711 
712   const ShortArray& algebraic_asv
713     = algebraic_response.active_set_request_vector();
714   size_t num_alg_fns = algebraic_asv.size(),
715     num_alg_vars = algebraic_response.active_set_derivative_vector().size();
716   if (num_alg_fns > num_total_fns) {
717     Cerr << "Error: response size mismatch in Interface::response_mapping()."
718 	 << std::endl;
719     abort_handler(-1);
720   }
721   if ( (grad_flag || hess_flag) && num_alg_vars > num_total_vars) {
722     Cerr << "Error: derivative variables size mismatch in Interface::"
723          << "response_mapping()." << std::endl;
724     abort_handler(-1);
725   }
726   SizetArray algebraic_dvv_indices;
727   if (grad_flag || hess_flag) {
728     algebraic_dvv_indices.resize(num_alg_vars);
729     using Pecos::find_index;
730     for (i=0; i<num_alg_vars; ++i)
731       algebraic_dvv_indices[i] = find_index(total_dvv, algebraicACVIds[i]);
732       // Note: _NPOS return is handled below
733   }
734   // augment total_response
735   const RealVector& algebraic_fn_vals = algebraic_response.function_values();
736   const RealMatrix& algebraic_fn_grads
737     = algebraic_response.function_gradients();
738   const RealSymMatrixArray& algebraic_fn_hessians
739     = algebraic_response.function_hessians();
740   RealVector total_fn_vals = total_response.function_values_view();
741   for (i=0; i<num_alg_fns; ++i) {
742     size_t fn_index = algebraicFnIndices[i];
743     if (algebraic_asv[i] & 1)
744       total_fn_vals[fn_index] += algebraic_fn_vals[i];
745     if (algebraic_asv[i] & 2) {
746       const Real* algebraic_fn_grad = algebraic_fn_grads[i];
747       RealVector total_fn_grad
748 	= total_response.function_gradient_view(fn_index);
749       for (j=0; j<num_alg_vars; j++) {
750 	size_t dvv_index = algebraic_dvv_indices[j];
751 	if (dvv_index != _NPOS)
752 	  total_fn_grad[dvv_index] += algebraic_fn_grad[j];
753       }
754     }
755     if (algebraic_asv[i] & 4) {
756       const RealSymMatrix& algebraic_fn_hess = algebraic_fn_hessians[i];
757       RealSymMatrix total_fn_hess
758 	= total_response.function_hessian_view(fn_index);
759       for (j=0; j<num_alg_vars; ++j) {
760 	size_t dvv_index_j = algebraic_dvv_indices[j];
761 	if (dvv_index_j != _NPOS) {
762 	  for (k=0; k<=j; ++k) {
763 	    size_t dvv_index_k = algebraic_dvv_indices[k];
764 	    if (dvv_index_k != _NPOS)
765 	      total_fn_hess(dvv_index_j,dvv_index_k) +=	algebraic_fn_hess(j,k);
766 	  }
767 	}
768       }
769     }
770   }
771 
772   // output response sets:
773 
774   if (outputLevel == DEBUG_OUTPUT) {
775     if (coreMappings) Cout << "core_response:\n" << core_response;
776     Cout << "algebraic_response:\n" << algebraic_response
777 	 << "total_response:\n"     << total_response << '\n';
778   }
779 }
780 
781 
final_eval_id_tag(int iface_eval_id)782 String Interface::final_eval_id_tag(int iface_eval_id)
783 {
784   if (interfaceRep)
785     return interfaceRep->final_eval_id_tag(iface_eval_id);
786 
787   if (appendIfaceId)
788     return evalTagPrefix + "." + std::to_string(iface_eval_id);
789   return evalTagPrefix;
790 }
791 
792 
algebraic_function_type(String functionTag)793 int Interface::algebraic_function_type(String functionTag)
794 {
795 #ifdef HAVE_AMPL
796   int i;
797   for (i=0; i<n_obj; i++)
798     if (strcontains(functionTag, obj_name(i)))
799       return i+1;
800   for (i=0; i<n_con; i++)
801     if (strcontains(functionTag, con_name(i)))
802       return -(i+1);
803 
804   Cerr << "Error: No function type available for \'" << functionTag << "\' "
805        << "via algebraic_mappings interface." << std::endl;
806   abort_handler(INTERFACE_ERROR);
807 #else
808   return 0;
809 #endif // HAVE_AMPL
810 }
811 
synchronize()812 const IntResponseMap& Interface::synchronize()
813 {
814   if (!interfaceRep) { // letter lacking redefinition of virtual fn.
815     Cerr << "Error: Letter lacking redefinition of virtual synchronize() "
816 	 << "function.\nNo default defined at Interface base class."
817 	 << std::endl;
818     abort_handler(-1);
819   }
820 
821   return interfaceRep->synchronize();
822 }
823 
824 
synchronize_nowait()825 const IntResponseMap& Interface::synchronize_nowait()
826 {
827   if (!interfaceRep) { // letter lacking redefinition of virtual fn.
828     Cerr << "Error: Letter lacking redefinition of virtual synchronize_nowait"
829 	 << "() function.\nNo default defined at Interface base class."
830 	 << std::endl;
831     abort_handler(-1);
832   }
833 
834   return interfaceRep->synchronize_nowait();
835 }
836 
837 
cache_unmatched_response(int raw_id)838 void Interface::cache_unmatched_response(int raw_id)
839 {
840   if (interfaceRep) // envelope fwd to letter
841     interfaceRep->cache_unmatched_response(raw_id);
842   else { // base definition; not virtual
843     IntRespMIter rr_it = rawResponseMap.find(raw_id);
844     if (rr_it != rawResponseMap.end()) {
845       cachedResponseMap.insert(*rr_it);
846       rawResponseMap.erase(rr_it);
847     }
848   }
849 }
850 
851 
serve_evaluations()852 void Interface::serve_evaluations()
853 {
854   if (interfaceRep) // envelope fwd to letter
855     interfaceRep->serve_evaluations();
856   else { // letter lacking redefinition of virtual fn.
857     Cerr << "Error: Letter lacking redefinition of virtual serve_evaluations "
858 	 << "function.\nNo default serve_evaluations defined at Interface"
859 	 << " base class." << std::endl;
860     abort_handler(-1);
861   }
862 }
863 
864 
stop_evaluation_servers()865 void Interface::stop_evaluation_servers()
866 {
867   if (interfaceRep) // envelope fwd to letter
868     interfaceRep->stop_evaluation_servers();
869   else { // letter lacking redefinition of virtual fn.
870     Cerr << "Error: Letter lacking redefinition of virtual stop_evaluation_"
871 	 << "servers fn.\nNo default stop_evaluation_servers defined at "
872 	 << "Interface base class." << std::endl;
873     abort_handler(-1);
874   }
875 }
876 
877 
init_communicators(const IntArray & message_lengths,int max_eval_concurrency)878 void Interface::init_communicators(const IntArray& message_lengths,
879 				   int max_eval_concurrency)
880 {
881   if (interfaceRep) // envelope fwd to letter
882     interfaceRep->init_communicators(message_lengths, max_eval_concurrency);
883   else { // letter lacking redefinition of virtual fn.
884     // ApproximationInterfaces: do nothing
885   }
886 }
887 
888 
set_communicators(const IntArray & message_lengths,int max_eval_concurrency)889 void Interface::set_communicators(const IntArray& message_lengths,
890 				  int max_eval_concurrency)
891 {
892   if (interfaceRep) // envelope fwd to letter
893     interfaceRep->set_communicators(message_lengths, max_eval_concurrency);
894   else { // letter lacking redefinition of virtual fn.
895     // ApproximationInterfaces: do nothing
896   }
897 }
898 
899 
900 /*
901 void Interface::free_communicators()
902 {
903   if (interfaceRep) // envelope fwd to letter
904     interfaceRep->free_communicators();
905   else { // letter lacking redefinition of virtual fn.
906     // default is no-op
907   }
908 }
909 */
910 
911 
init_serial()912 void Interface::init_serial()
913 {
914   if (interfaceRep) // envelope fwd to letter
915     interfaceRep->init_serial();
916   else { // letter lacking redefinition of virtual fn.
917     // ApproximationInterfaces: do nothing
918   }
919 }
920 
921 
asynch_local_evaluation_concurrency() const922 int Interface::asynch_local_evaluation_concurrency() const
923 {
924   if (interfaceRep) // envelope fwd to letter
925     return interfaceRep->asynch_local_evaluation_concurrency();
926   else // letter lacking redefinition of virtual fn.
927     return 0; // default (redefined only for ApplicationInterfaces)
928 }
929 
930 
interface_synchronization() const931 short Interface::interface_synchronization() const
932 {
933   if (interfaceRep) // envelope fwd to letter
934     return interfaceRep->interface_synchronization(); // ApplicationInterfaces
935   else // letter lacking redefinition of virtual fn.
936     return SYNCHRONOUS_INTERFACE; // default (ApproximationInterfaces)
937 }
938 
939 
minimum_points(bool constraint_flag) const940 int Interface::minimum_points(bool constraint_flag) const
941 {
942   if (interfaceRep) // envelope fwd to letter
943     return interfaceRep->minimum_points(constraint_flag);
944   else // letter lacking redefinition of virtual fn.
945     return 0; // default (currently redefined only for ApproximationInterfaces)
946 }
947 
948 
recommended_points(bool constraint_flag) const949 int Interface::recommended_points(bool constraint_flag) const
950 {
951   if (interfaceRep) // envelope fwd to letter
952     return interfaceRep->recommended_points(constraint_flag);
953   else // letter lacking redefinition of virtual fn.
954     return 0; // default (currently redefined only for ApproximationInterfaces)
955 }
956 
957 
active_model_key(const UShortArray & mi_key)958 void Interface::active_model_key(const UShortArray& mi_key)
959 {
960   if (interfaceRep) // envelope fwd to letter
961     interfaceRep->active_model_key(mi_key);
962   // else: default implementation is no-op
963 }
964 
965 
clear_model_keys()966 void Interface::clear_model_keys()
967 {
968   if (interfaceRep) // envelope fwd to letter
969     interfaceRep->clear_model_keys();
970   // else: default implementation is no-op
971 }
972 
973 
approximation_function_indices(const IntSet & approx_fn_indices)974 void Interface::approximation_function_indices(const IntSet& approx_fn_indices)
975 {
976   if (interfaceRep) // envelope fwd to letter
977     interfaceRep->approximation_function_indices(approx_fn_indices);
978   // else: default implementation is no-op
979 }
980 
981 
982 /*
983 void Interface::link_multilevel_approximation_data()
984 {
985   if (interfaceRep) // envelope fwd to letter
986     interfaceRep->link_multilevel_approximation_data();
987   else { // letter lacking redefinition of virtual fn.
988     Cerr << "Error: Letter lacking redefinition of virtual link_multilevel_"
989 	 << "approximation_data() function.\n       This interface does not "
990 	 << "support multilevel data." << std::endl;
991     abort_handler(-1);
992   }
993 }
994 */
995 
996 
997 void Interface::
update_approximation(const Variables & vars,const IntResponsePair & response_pr)998 update_approximation(const Variables& vars, const IntResponsePair& response_pr)
999 {
1000   if (interfaceRep) // envelope fwd to letter
1001     interfaceRep->update_approximation(vars, response_pr);
1002   else { // letter lacking redefinition of virtual fn.
1003     Cerr << "Error: Letter lacking redefinition of virtual update_approximation"
1004          << "(Variables, IntResponsePair) function.\n       This interface "
1005 	 << "does not support approximation updating." << std::endl;
1006     abort_handler(-1);
1007   }
1008 }
1009 
1010 
1011 void Interface::
update_approximation(const RealMatrix & samples,const IntResponseMap & resp_map)1012 update_approximation(const RealMatrix& samples, const IntResponseMap& resp_map)
1013 {
1014   if (interfaceRep) // envelope fwd to letter
1015     interfaceRep->update_approximation(samples, resp_map);
1016   else { // letter lacking redefinition of virtual fn.
1017     Cerr << "Error: Letter lacking redefinition of virtual update_approximation"
1018          << "(RealMatrix, IntResponseMap) function.\n       This interface "
1019 	 << "does not support approximation updating." << std::endl;
1020     abort_handler(-1);
1021   }
1022 }
1023 
1024 
1025 void Interface::
update_approximation(const VariablesArray & vars_array,const IntResponseMap & resp_map)1026 update_approximation(const VariablesArray& vars_array,
1027 		     const IntResponseMap& resp_map)
1028 {
1029   if (interfaceRep) // envelope fwd to letter
1030     interfaceRep->update_approximation(vars_array, resp_map);
1031   else { // letter lacking redefinition of virtual fn.
1032     Cerr << "Error: Letter lacking redefinition of virtual update_approximation"
1033          << "(VariablesArray, IntResponseMap) function.\n       This interface "
1034 	 << "does not support approximation updating." << std::endl;
1035     abort_handler(-1);
1036   }
1037 }
1038 
1039 
1040 void Interface::
append_approximation(const Variables & vars,const IntResponsePair & response_pr)1041 append_approximation(const Variables& vars, const IntResponsePair& response_pr)
1042 {
1043   if (interfaceRep) // envelope fwd to letter
1044     interfaceRep->append_approximation(vars, response_pr);
1045   else { // letter lacking redefinition of virtual fn.
1046     Cerr << "Error: Letter lacking redefinition of virtual append_approximation"
1047 	 << "(Variables, IntResponsePair) function.\n       This interface "
1048 	 << "does not support approximation appending." << std::endl;
1049     abort_handler(-1);
1050   }
1051 }
1052 
1053 
1054 void Interface::
append_approximation(const RealMatrix & samples,const IntResponseMap & resp_map)1055 append_approximation(const RealMatrix& samples, const IntResponseMap& resp_map)
1056 {
1057   if (interfaceRep) // envelope fwd to letter
1058     interfaceRep->append_approximation(samples, resp_map);
1059   else { // letter lacking redefinition of virtual fn.
1060     Cerr << "Error: Letter lacking redefinition of virtual append_approximation"
1061          << "(RealMatrix, IntResponseMap) function.\n       This interface "
1062 	 << "does not support approximation appending." << std::endl;
1063     abort_handler(-1);
1064   }
1065 }
1066 
1067 
1068 void Interface::
append_approximation(const VariablesArray & vars_array,const IntResponseMap & resp_map)1069 append_approximation(const VariablesArray& vars_array,
1070 		     const IntResponseMap& resp_map)
1071 {
1072   if (interfaceRep) // envelope fwd to letter
1073     interfaceRep->append_approximation(vars_array, resp_map);
1074   else { // letter lacking redefinition of virtual fn.
1075     Cerr << "Error: Letter lacking redefinition of virtual append_approximation"
1076          << "(VariablesArray, IntResponseMap) function.\n       This interface "
1077 	 << "does not support approximation appending." << std::endl;
1078     abort_handler(-1);
1079   }
1080 }
1081 
1082 
1083 void Interface::
build_approximation(const RealVector & c_l_bnds,const RealVector & c_u_bnds,const IntVector & di_l_bnds,const IntVector & di_u_bnds,const RealVector & dr_l_bnds,const RealVector & dr_u_bnds)1084 build_approximation(const RealVector&  c_l_bnds, const RealVector&  c_u_bnds,
1085 		    const IntVector&  di_l_bnds, const IntVector&  di_u_bnds,
1086 		    const RealVector& dr_l_bnds, const RealVector& dr_u_bnds)
1087 {
1088   if (interfaceRep) // envelope fwd to letter
1089     interfaceRep->build_approximation(c_l_bnds, c_u_bnds, di_l_bnds, di_u_bnds,
1090 				      dr_l_bnds, dr_u_bnds);
1091   else { // letter lacking redefinition of virtual fn.
1092     Cerr << "Error: Letter lacking redefinition of virtual build_approximation"
1093          << "() function.\n       This interface does not support "
1094 	 << "approximations." << std::endl;
1095     abort_handler(-1);
1096   }
1097 }
1098 
1099 
export_approximation()1100 void Interface::export_approximation()
1101 {
1102   if (interfaceRep) // envelope fwd to letter
1103     interfaceRep->export_approximation();
1104   else { // letter lacking redefinition of virtual fn.
1105     Cerr << "Error: Letter lacking redefinition of virtual export_approximation"
1106          << "() function.\n       This interface does not support exporting "
1107 	 << "approximations." << std::endl;
1108     abort_handler(-1);
1109   }
1110 }
1111 
1112 
rebuild_approximation(const BitArray & rebuild_fns)1113 void Interface::rebuild_approximation(const BitArray& rebuild_fns)
1114 {
1115   if (interfaceRep) // envelope fwd to letter
1116     interfaceRep->rebuild_approximation(rebuild_fns);
1117   else { // letter lacking redefinition of virtual fn.
1118     Cerr << "Error: Letter lacking redefinition of virtual rebuild_"
1119 	 << "approximation() function.\n       This interface does not "
1120 	 << "support approximations." << std::endl;
1121     abort_handler(-1);
1122   }
1123 }
1124 
1125 
pop_approximation(bool save_data)1126 void Interface::pop_approximation(bool save_data)
1127 {
1128   if (interfaceRep) // envelope fwd to letter
1129     interfaceRep->pop_approximation(save_data);
1130   else { // letter lacking redefinition of virtual fn.
1131     Cerr << "Error: Letter lacking redefinition of virtual pop_approximation"
1132 	 << "(bool)\n       function. This interface does not support "
1133 	 << "approximation\n       data removal." << std::endl;
1134     abort_handler(-1);
1135   }
1136 }
1137 
1138 
push_approximation()1139 void Interface::push_approximation()
1140 {
1141   if (interfaceRep) // envelope fwd to letter
1142     interfaceRep->push_approximation();
1143   else { // letter lacking redefinition of virtual fn.
1144     Cerr << "Error: Letter lacking redefinition of virtual push_"
1145 	 << "approximation() function.\n       This interface does not "
1146 	 << "support approximation data retrieval." << std::endl;
1147     abort_handler(-1);
1148   }
1149 }
1150 
1151 
push_available()1152 bool Interface::push_available()
1153 {
1154   if (!interfaceRep) { // letter lacking redefinition of virtual fn.
1155     Cerr << "Error: Letter lacking redefinition of virtual push_"
1156 	 << "available() function.\n       This interface does not "
1157 	 << "support approximation data retrieval." << std::endl;
1158     abort_handler(-1);
1159   }
1160 
1161   return interfaceRep->push_available();
1162 }
1163 
1164 
finalize_approximation()1165 void Interface::finalize_approximation()
1166 {
1167   if (interfaceRep) // envelope fwd to letter
1168     interfaceRep->finalize_approximation();
1169   else { // letter lacking redefinition of virtual fn.
1170     Cerr << "Error: Letter lacking redefinition of virtual finalize_"
1171 	 << "approximation() function.\n       This interface does not "
1172 	 << "support approximation finalization." << std::endl;
1173     abort_handler(-1);
1174   }
1175 }
1176 
1177 
clear_inactive()1178 void Interface::clear_inactive()
1179 {
1180   if (interfaceRep) // envelope fwd to letter
1181     interfaceRep->clear_inactive();
1182   //else // letter lacking redefinition of virtual fn.
1183   //  default: no inactive data to clear
1184 }
1185 
1186 
combine_approximation()1187 void Interface::combine_approximation()
1188 {
1189   if (interfaceRep) // envelope fwd to letter
1190     interfaceRep->combine_approximation();
1191   else { // letter lacking redefinition of virtual fn.
1192     Cerr << "Error: Letter lacking redefinition of virtual combine_"
1193 	 << "approximation() function.\n       This interface does not "
1194 	 << "support approximation combination." << std::endl;
1195     abort_handler(-1);
1196   }
1197 }
1198 
1199 
combined_to_active(bool clear_combined)1200 void Interface::combined_to_active(bool clear_combined)
1201 {
1202   if (interfaceRep) // envelope fwd to letter
1203     interfaceRep->combined_to_active(clear_combined);
1204   else { // letter lacking redefinition of virtual fn.
1205     Cerr << "Error: Letter lacking redefinition of virtual combined_to_active()"
1206 	 << " function.\n       This interface does not support approximation"
1207 	 << " combination." << std::endl;
1208     abort_handler(-1);
1209   }
1210 }
1211 
1212 
advancement_available()1213 bool Interface::advancement_available()
1214 {
1215   if (interfaceRep) return interfaceRep->advancement_available();
1216   else              return true; // only a few cases throttle advancements
1217 }
1218 
1219 
formulation_updated() const1220 bool Interface::formulation_updated() const
1221 {
1222   if (!interfaceRep) { // letter lacking redefinition of virtual fn.
1223     Cerr << "Error: Letter lacking redefinition of virtual formulation_updated"
1224 	 << "() function.\n       This interface does not define approximation "
1225 	 << "formulations." << std::endl;
1226     abort_handler(-1);
1227   }
1228 
1229   return interfaceRep->formulation_updated();
1230 }
1231 
1232 
formulation_updated(bool update)1233 void Interface::formulation_updated(bool update)
1234 {
1235   if (interfaceRep)
1236     interfaceRep->formulation_updated(update);
1237   else { // letter lacking redefinition of virtual fn.
1238     Cerr << "Error: Letter lacking redefinition of virtual formulation_updated"
1239 	 << "() function.\n       This interface does not define approximation "
1240 	 << "formulations." << std::endl;
1241     abort_handler(-1);
1242   }
1243 }
1244 
1245 
1246 Real2DArray Interface::
cv_diagnostics(const StringArray & metric_types,unsigned num_folds)1247 cv_diagnostics(const StringArray& metric_types, unsigned num_folds)
1248 {
1249   if (!interfaceRep) { // letter lacking redefinition of virtual fn.
1250     Cerr << "Error: Letter lacking redefinition of virtual cv_diagnostics()"
1251 	 << "function.\n       This interface does not "
1252 	 << "support cross-validation diagnostics." << std::endl;
1253     abort_handler(-1);
1254   }
1255 
1256   return interfaceRep->cv_diagnostics(metric_types, num_folds);
1257 }
1258 
1259 
challenge_diagnostics(const String & metric_type,const RealMatrix & challenge_pts)1260 RealArray Interface::challenge_diagnostics(const String& metric_type,
1261 					    const RealMatrix& challenge_pts)
1262 {
1263   if (!interfaceRep) { // letter lacking redefinition of virtual fn.
1264     Cerr << "Error: Letter lacking redefinition of virtual challenge_"
1265 	 << "diagnostics() function.\n       This interface does not "
1266 	 << "support challenge data diagnostics." << std::endl;
1267     abort_handler(-1);
1268   }
1269 
1270   return interfaceRep->challenge_diagnostics(metric_type, challenge_pts);
1271 }
1272 
1273 
clear_current_active_data()1274 void Interface::clear_current_active_data()
1275 {
1276   if (interfaceRep) // envelope fwd to letter
1277     interfaceRep->clear_current_active_data();
1278   //else // letter lacking redefinition of virtual fn.
1279     // ApplicationInterfaces: do nothing
1280 }
1281 
1282 
clear_active_data()1283 void Interface::clear_active_data()
1284 {
1285   if (interfaceRep) // envelope fwd to letter
1286     interfaceRep->clear_active_data();
1287   //else // letter lacking redefinition of virtual fn.
1288     // ApplicationInterfaces: do nothing
1289 }
1290 
1291 
shared_approximation()1292 SharedApproxData& Interface::shared_approximation()
1293 {
1294   if (!interfaceRep) { // letter lacking redefinition of virtual fn.
1295     Cerr << "Error: Letter lacking redefinition of virtual shared_approximation"
1296          << "() function.\nThis interface does not support approximations."
1297 	 << std::endl;
1298     abort_handler(-1);
1299   }
1300 
1301   // envelope fwd to letter
1302   return interfaceRep->shared_approximation();
1303 }
1304 
1305 
approximations()1306 std::vector<Approximation>& Interface::approximations()
1307 {
1308   if (!interfaceRep) { // letter lacking redefinition of virtual fn.
1309     Cerr << "Error: Letter lacking redefinition of virtual approximations() "
1310 	 << "function.\n       This interface does not support approximations."
1311 	 << std::endl;
1312     abort_handler(-1);
1313   }
1314 
1315   // envelope fwd to letter
1316   return interfaceRep->approximations();
1317 }
1318 
1319 
approximation_data(size_t fn_index)1320 const Pecos::SurrogateData& Interface::approximation_data(size_t fn_index)
1321 {
1322   if (!interfaceRep) { // letter lacking redefinition of virtual fn.
1323     Cerr << "Error: Letter lacking redefinition of virtual approximation_data "
1324 	 << "function.\n       This interface does not support approximations."
1325 	 << std::endl;
1326     abort_handler(-1);
1327   }
1328 
1329   // envelope fwd to letter
1330   return interfaceRep->approximation_data(fn_index);
1331 }
1332 
1333 
approximation_coefficients(bool normalized)1334 const RealVectorArray& Interface::approximation_coefficients(bool normalized)
1335 {
1336   if (!interfaceRep) { // letter lacking redefinition of virtual fn.
1337     Cerr << "Error: Letter lacking redefinition of virtual approximation_"
1338 	 << "coefficients function.\n       This interface does not support "
1339          << "approximations." << std::endl;
1340     abort_handler(-1);
1341   }
1342 
1343   // envelope fwd to letter
1344   return interfaceRep->approximation_coefficients(normalized);
1345 }
1346 
1347 
1348 void Interface::
approximation_coefficients(const RealVectorArray & approx_coeffs,bool normalized)1349 approximation_coefficients(const RealVectorArray& approx_coeffs,
1350 			   bool normalized)
1351 {
1352   if (interfaceRep) // envelope fwd to letter
1353     interfaceRep->approximation_coefficients(approx_coeffs, normalized);
1354   else { // letter lacking redefinition of virtual fn.
1355     Cerr << "Error: Letter lacking redefinition of virtual approximation_"
1356 	 << "coefficients function.\n       This interface does not support "
1357          << "approximations." << std::endl;
1358     abort_handler(-1);
1359   }
1360 }
1361 
1362 
approximation_variances(const Variables & vars)1363 const RealVector& Interface::approximation_variances(const Variables& vars)
1364 {
1365   if (!interfaceRep) { // letter lacking redefinition of virtual fn.
1366     Cerr << "Error: Letter lacking redefinition of virtual approximation_"
1367 	 << "variances function.\n       This interface does not support "
1368          << "approximations." << std::endl;
1369     abort_handler(-1);
1370   }
1371 
1372   // envelope fwd to letter
1373   return interfaceRep->approximation_variances(vars);
1374 }
1375 
1376 
analysis_drivers() const1377 const StringArray& Interface::analysis_drivers() const
1378 {
1379   if (!interfaceRep) { // letter lacking redefinition of virtual fn.
1380     Cerr << "Error: Letter lacking redefinition of virtual analysis_drivers "
1381 	 << "function." << std::endl;
1382     abort_handler(-1);
1383   }
1384 
1385   // envelope fwd to letter
1386   return interfaceRep->analysis_drivers();
1387 }
1388 
analysis_components() const1389 const String2DArray & Interface::analysis_components() const
1390 {
1391   if(interfaceRep)
1392     return interfaceRep->analysis_components();
1393   return analysisComponents;
1394 }
1395 
evaluation_cache() const1396 bool Interface::evaluation_cache() const
1397 {
1398   if (interfaceRep)
1399     return interfaceRep->evaluation_cache();
1400   else // letter lacking redefinition of virtual fn.
1401     return false; // default
1402 }
1403 
1404 
restart_file() const1405 bool Interface::restart_file() const
1406 {
1407   if (interfaceRep)
1408     return interfaceRep->restart_file();
1409   else // letter lacking redefinition of virtual fn.
1410     return false; // default
1411 }
1412 
1413 
file_cleanup() const1414 void Interface::file_cleanup() const
1415 {
1416   if (interfaceRep)
1417     interfaceRep->file_cleanup();
1418   // else no-op
1419 }
1420 
1421 /** Rationale: The parser allows multiple user-specified interfaces with
1422     empty (unspecified) ID. However, only a single Interface with empty
1423     ID can be constructed (if it's the only one present, or the "last
1424     one parsed"). Therefore decided to prefer NO_ID over NO_ID_<num>
1425     for consistency with interface NO_ID convention. Additionally, NO_ID
1426     is preferred over NO_INTERFACE_ID (contrast with Iterator and Model)
1427     to preserve backward compatibility
1428  */
user_auto_id()1429 String Interface::user_auto_id()
1430 {
1431   // // increment and then use the current ID value
1432   // return String("NO_ID_") + std::to_string(++userAutoIdNum);
1433   return String("NO_ID");
1434 }
1435 
1436 /** Rationale: For now NOSPEC_ID_ is chosen due to historical
1437     id="NO_SPECIFICATION" used for internally-constructed
1438     Iterators. Longer-term, consider auto-generating an ID that
1439     includes the context from which the method is constructed, e.g.,
1440     the parent method or model's ID, together with its name. */
no_spec_id()1441 String Interface::no_spec_id()
1442 {
1443   // increment and then use the current ID value
1444   return String("NOSPEC_INTERFACE_ID_") + std::to_string(++noSpecIdNum);
1445 }
1446 } // namespace Dakota
1447