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 #include <cstdlib>
10 #include <cmath>
11 #include <iostream>
12 #include <fstream>
13 #include <string>
14 #include <vector>
15 #include <map>
16 #include <algorithm>
17 #include <cctype>
18 
19 enum var_t { W, T, R, E, X, Y };
20 
21 
main(int argc,char ** argv)22 int main(int argc, char** argv)
23 {
24 
25   // This test problem is an OUU example from Applied Research Associates
26   // (42nd AIAA SDM conference, April 2001).
27 
28   std::ifstream fin(argv[1]);
29   if (!fin) {
30     std::cerr << "\nError: failure opening " << argv[1] << std::endl;
31     exit(-1);
32   }
33   size_t i, j, num_vars, num_fns, num_deriv_vars;
34   std::string vars_text, fns_text, dvv_text;
35 
36   // define the std::string to enumeration map
37   std::map<std::string, var_t> var_t_map;
38   var_t_map["w"] = W; var_t_map["t"] = T;
39   var_t_map["r"] = R; var_t_map["e"] = E;
40   var_t_map["x"] = X; var_t_map["y"] = Y;
41 
42   // Get the parameter std::vector and ignore the labels
43   fin >> num_vars >> vars_text;
44   std::map<var_t, double> vars;
45   std::vector<var_t> labels(num_vars);
46   double var_i; std::string label_i; var_t v_i;
47   std::map<std::string, var_t>::iterator v_iter;
48   for (i=0; i<num_vars; i++) {
49     fin >> var_i >> label_i;
50     transform(label_i.begin(), label_i.end(), label_i.begin(),
51 	      (int(*)(int))tolower);
52     v_iter = var_t_map.find(label_i);
53     if (v_iter == var_t_map.end()) {
54       std::cerr << "Error: label \"" << label_i << "\" not supported in analysis "
55 	   << "driver." << std::endl;
56       exit(-1);
57     }
58     else
59       v_i = v_iter->second;
60     vars[v_i] = var_i;
61     labels[i] = v_i;
62   }
63 
64   // Get the ASV std::vector and ignore the labels
65   fin >> num_fns >> fns_text;
66   std::vector<short> ASV(num_fns);
67   for (i=0; i<num_fns; i++) {
68     fin >> ASV[i];
69     fin.ignore(256, '\n');
70   }
71 
72   // Get the DVV std::vector and ignore the labels
73   fin >> num_deriv_vars >> dvv_text;
74   std::vector<var_t> DVV(num_deriv_vars);
75   unsigned int dvv_i;
76   for (i=0; i<num_deriv_vars; i++) {
77     fin >> dvv_i;
78     fin.ignore(256, '\n');
79     DVV[i] = labels[dvv_i-1];
80   }
81 
82   if (num_vars != 4 && num_vars != 6) {
83     std::cerr << "Error: Wrong number of variables in mod_cantilever test fn."
84 	 << std::endl;
85     exit(-1);
86   }
87   if (num_fns < 2 || num_fns > 3) {
88     std::cerr << "Error: wrong number of response functions in mod_cantilever test "
89 	 << "fn." << std::endl;
90     exit(-1);
91   }
92 
93   // Compute the cross-sectional area, stress, and displacement of the
94   // cantilever beam.  This simulator is unusual in that it supports both
95   // the case of design variable insertion and the case of design variable
96   // augmentation.  It does not support mixed insertion/augmentation.  In
97   // the 6 variable case, w,t,R,E,X,Y are all passed in; in the 4 variable
98   // case, w,t assume local values.
99   std::map<var_t, double>::iterator m_iter = vars.find(W);
100   double w = (m_iter == vars.end()) ? 2.5 : m_iter->second; // beam width
101   m_iter = vars.find(T);
102   double t = (m_iter == vars.end()) ? 2.5 : m_iter->second; // beam thickness
103   double r = vars[R]; // yield strength
104   double e = vars[E]; // Young's modulus
105   double x = vars[X]; // horizontal load
106   double y = vars[Y]; // vertical load
107 
108   // allow f,c1,c2 (optimization) or just c1,c2 (calibration)
109   bool objective; size_t c1i, c2i;
110   if (num_fns == 2) { objective = false; c1i = 0; c2i = 1; }
111   else              { objective = true;  c1i = 1; c2i = 2; }
112 
113   // UQ limit state <= 0: don't scale stress by random variable r
114   //double g_stress = stress - r;
115   //double g_disp   = displ  - D0;
116 
117   // Compute the results and output them directly to argv[2] (the NO_FILTER
118   // option is used).  Response tags are optional; output them for ease of
119   // results readability.
120   double D0 = 2.2535, L = 100., area = w*t, w_sq = w*w, t_sq = t*t,
121     r_sq = r*r, x_sq = x*x, y_sq = y*y;
122   double stress = 600.*y/w/t_sq + 600.*x/w_sq/t;
123   double D1 = 4.*pow(L,3)/e/area, D2 = pow(y/t_sq, 2)+pow(x/w_sq, 2);
124   double D3 = D1/sqrt(D2),        displ = D1*sqrt(D2);
125 
126   std::ofstream fout(argv[2]); // do not instantiate until ready to write results
127   if (!fout) {
128     std::cerr << "\nError: failure creating " << argv[2] << std::endl;
129     exit(-1);
130   }
131   fout.precision(15); // 16 total digits
132   fout.setf(std::ios::scientific);
133   fout.setf(std::ios::right);
134 
135   // **** f:
136   if (objective && (ASV[0] & 1))
137     fout << "                     " << area << '\n';
138 
139   // **** c1:
140   if (ASV[c1i] & 1)
141     fout << "                     " << stress - r << '\n';
142 
143   // **** c2:
144   if (ASV[c2i] & 1)
145     fout << "                     " << displ - D0 << '\n';
146 
147   // **** df/dx:
148   if (objective && (ASV[0] & 2)) {
149     fout << "[ ";
150     for (i=0; i<num_deriv_vars; i++)
151       switch (DVV[i]) {
152       case W:  fout << t << ' '; break; // design var derivative
153       case T:  fout << w << ' '; break; // design var derivative
154       default: fout << "0. ";    break; // uncertain var derivative
155       }
156     fout << "]\n";
157   }
158 
159   // **** dc1/dx:
160   if (ASV[c1i] & 2) {
161     fout << "[ ";
162     for (i=0; i<num_deriv_vars; i++)
163       switch (DVV[i]) {
164       case W: fout << -600.*(y/t + 2.*x/w)/w_sq/t << ' '; break; // des var
165       case T: fout << -600.*(2.*y/t + x/w)/w/t_sq << ' '; break; // des var
166       case R: fout << "-1. ";             break; // uncertain var deriv
167       case E: fout << "0. ";              break; // uncertain var deriv
168       case X: fout << 600./w_sq/t << ' '; break; // uncertain var deriv
169       case Y: fout << 600./w/t_sq << ' '; break; // uncertain var deriv
170       }
171     fout << "]\n";
172   }
173 
174   // **** dc2/dx:
175   if (ASV[c2i] & 2) {
176     fout << "[ ";
177     for (i=0; i<num_deriv_vars; i++)
178       switch (DVV[i]) {
179       case W: fout << -D3*2.*x_sq/w_sq/w_sq/w - displ/w << ' '; break; // dv
180       case T: fout << -D3*2.*y_sq/t_sq/t_sq/t - displ/t << ' '; break; // dv
181       case R: fout << "0. ";                  break; // unc var deriv
182       case E: fout << -displ/E        << ' '; break; // unc var deriv
183       case X: fout <<  D3*x/w_sq/w_sq << ' '; break; // unc var deriv
184       case Y: fout <<  D3*y/t_sq/t_sq << ' '; break; // unc var deriv
185       }
186     fout << "]\n";
187   }
188 
189   /* Alternative modification: take E out of displ denominator to remove
190      singularity in tail (at 20 std deviations).  In PCE/SC testing, this
191      had minimal impact and did not justify the nonstandard form.
192 
193   double D0 = 2.2535, L = 100., area = w*t, w_sq = w*w, t_sq = t*t,
194     r_sq = r*r, x_sq = x*x, y_sq = y*y;
195   double stress = 600.*y/w/t_sq + 600.*x/w_sq/t;
196   double D1 = 4.*pow(L,3)/area, D2 = pow(y/t_sq, 2)+pow(x/w_sq, 2);
197   double D3 = D1/sqrt(D2),      D4 = D1*sqrt(D2);
198 
199   // **** c2:
200   if (ASV[c2i] & 1)
201     fout << "                     " << D4 - D0*e << '\n';
202 
203   // **** dc2/dx:
204   if (ASV[c2i] & 2) {
205     fout << "[ ";
206     for (i=0; i<num_deriv_vars; i++)
207       switch (DVV[i]) {
208       case W: fout << -D3*2.*x_sq/w_sq/w_sq/w - D4/w << ' '; break; // des var
209       case T: fout << -D3*2.*y_sq/t_sq/t_sq/t - D4/t << ' '; break; // des var
210       case R: fout << "0. ";                  break; // unc var deriv
211       case E: fout << -D0             << ' '; break; // unc var deriv
212       case X: fout <<  D3*x/w_sq/w_sq << ' '; break; // unc var deriv
213       case Y: fout <<  D3*y/t_sq/t_sq << ' '; break; // unc var deriv
214       }
215     fout << "]\n";
216   }
217   */
218 
219   fout.flush();
220   fout.close();
221   return 0;
222 }
223