1 /* _______________________________________________________________________
2
3 PECOS: Parallel Environment for Creation Of Stochastics
4 Copyright (c) 2011, Sandia National Laboratories.
5 This software is distributed under the GNU Lesser General Public License.
6 For more information, see the README file in the top Pecos directory.
7 _______________________________________________________________________ */
8
9 //- Class: DiscrepancyCalculator
10 //- Description: Implementation code for the DiscrepancyCalculator class
11 //- Owner: Mike Eldred
12 //- Checked by:
13
14 #include "DiscrepancyCalculator.hpp"
15 #include "SurrogateData.hpp"
16
17 static const char rcsId[]="@(#) $Id: DiscrepancyCalculator.cpp 7024 2010-10-16 01:24:42Z mseldre $";
18
19
20 namespace Pecos {
21
22 bool DiscrepancyCalculator::
check_multiplicative(Real truth_fn,Real approx_fn,short corr_order)23 check_multiplicative(Real truth_fn, Real approx_fn, short corr_order)
24 {
25 // Multiplicative will fail if response functions are near zero.
26 // 0th order: a truth_val == 0 causes a zero scaling which will cause
27 // optimization failure; an approx_val == 0 will cause a
28 // division by zero FPE.
29 // 1st/2nd order: a truth_val == 0 is OK (so long as the total scaling
30 // function != 0); an approx_val == 0 will cause a division
31 // by zero FPE.
32 return
33 ( std::fabs(approx_fn) < Pecos::SMALL_NUMBER ||
34 ( corr_order == 0 && std::fabs(truth_fn) < Pecos::SMALL_NUMBER ) );
35 }
36
37
38 bool DiscrepancyCalculator::
check_multiplicative(const RealVector & truth_fns,const RealVector & approx_fns,short corr_order)39 check_multiplicative(const RealVector& truth_fns, const RealVector& approx_fns,
40 short corr_order)
41 {
42 bool bad_scaling = false;
43 size_t i, num_fns = std::min(truth_fns.length(), approx_fns.length());
44 for (i=0; i<num_fns; ++i)
45 if ( std::fabs(approx_fns[i]) < Pecos::SMALL_NUMBER ||
46 ( corr_order == 0 && std::fabs(truth_fns[i]) < Pecos::SMALL_NUMBER ) )
47 { bad_scaling = true; break; }
48
49 return bad_scaling;
50 }
51
52
53 void DiscrepancyCalculator::
compute_additive(Real truth_fn,Real approx_fn,Real & discrep_fn)54 compute_additive(Real truth_fn, Real approx_fn, Real& discrep_fn)
55 {
56 // -----------------------------
57 // Additive 0th order correction
58 // -----------------------------
59 discrep_fn = truth_fn - approx_fn;
60 }
61
62
63 void DiscrepancyCalculator::
compute_additive(const RealVector & truth_grad,const RealVector & approx_grad,RealVector & discrep_grad)64 compute_additive(const RealVector& truth_grad, const RealVector& approx_grad,
65 RealVector& discrep_grad)
66 {
67 // -----------------------------
68 // Additive 1st order correction
69 // -----------------------------
70 size_t v, num_v = std::min(truth_grad.length(), approx_grad.length());
71 if (discrep_grad.length() != num_v) discrep_grad.sizeUninitialized(num_v);
72 for (v=0; v<num_v; ++v)
73 discrep_grad[v] = truth_grad[v] - approx_grad[v];
74 }
75
76
77 void DiscrepancyCalculator::
compute_additive(const RealSymMatrix & truth_hess,const RealSymMatrix & approx_hess,RealSymMatrix & discrep_hess)78 compute_additive(const RealSymMatrix& truth_hess,
79 const RealSymMatrix& approx_hess, RealSymMatrix& discrep_hess)
80 {
81 // -----------------------------
82 // Additive 2nd order correction
83 // -----------------------------
84 size_t r, c, num_v = std::min(truth_hess.numRows(), approx_hess.numRows());
85 if (discrep_hess.numRows() != num_v)
86 discrep_hess.shapeUninitialized(num_v);
87 for (r=0; r<num_v; ++r)
88 for (c=0; c<=r; ++c) // lower half
89 discrep_hess(r,c) = truth_hess(r,c) - approx_hess(r,c);
90 }
91
92
93 void DiscrepancyCalculator::
compute_multiplicative(Real truth_fn,Real approx_fn,Real & discrep_fn)94 compute_multiplicative(Real truth_fn, Real approx_fn, Real& discrep_fn)
95 {
96 // -----------------------------------
97 // Multiplicative 0th order correction
98 // -----------------------------------
99 discrep_fn = truth_fn / approx_fn;
100 }
101
102
103 void DiscrepancyCalculator::
compute_multiplicative(Real truth_fn,const RealVector & truth_grad,Real approx_fn,const RealVector & approx_grad,RealVector & discrep_grad)104 compute_multiplicative(Real truth_fn, const RealVector& truth_grad,
105 Real approx_fn, const RealVector& approx_grad,
106 RealVector& discrep_grad)
107 {
108 // -----------------------------------
109 // Multiplicative 1st order correction
110 // -----------------------------------
111 // The beta-correction method is based on the work of Chang and Haftka,
112 // and Alexandrov. It is a multiplicative correction like the "scaled"
113 // correction method, but it uses gradient information to achieve
114 // 1st-order consistency (matches the high-fidelity function values and
115 // the high-fidelity gradients at the center of the approximation region).
116 size_t v, num_v = std::min(truth_grad.length(), approx_grad.length());
117 if (discrep_grad.length() != num_v) discrep_grad.sizeUninitialized(num_v);
118 Real ratio = truth_fn / approx_fn;
119 for (v=0; v<num_v; ++v)
120 discrep_grad[v] = (truth_grad[v] - approx_grad[v] * ratio) / approx_fn;
121 }
122
123
124 void DiscrepancyCalculator::
compute_multiplicative(Real truth_fn,const RealVector & truth_grad,const RealSymMatrix & truth_hess,Real approx_fn,const RealVector & approx_grad,const RealSymMatrix & approx_hess,RealSymMatrix & discrep_hess)125 compute_multiplicative(Real truth_fn, const RealVector& truth_grad,
126 const RealSymMatrix& truth_hess,
127 Real approx_fn, const RealVector& approx_grad,
128 const RealSymMatrix& approx_hess,
129 RealSymMatrix& discrep_hess)
130 {
131 // -----------------------------------
132 // Multiplicative 2nd order correction
133 // -----------------------------------
134 size_t r, c, num_v = std::min(truth_hess.numRows(), approx_hess.numRows());
135 if (discrep_hess.numRows() != num_v)
136 discrep_hess.shapeUninitialized(num_v);
137 // consider use of Teuchos assign and operator-=
138 Real ratio2 = 2. * truth_fn / approx_fn, approx_sq = approx_fn * approx_fn;
139 for (r=0; r<num_v; ++r)
140 for (c=0; c<=r; ++c) // lower half
141 discrep_hess(r,c) = ( truth_hess(r,c) * approx_fn - approx_hess(r,c) *
142 truth_fn + ratio2 * approx_grad[r] * approx_grad[c] - truth_grad[r] *
143 approx_grad[c] - approx_grad[r] * truth_grad[c] ) / approx_sq;
144 }
145
146
147 void DiscrepancyCalculator::
compute(const SDRArray & hf_sdr_array,const SDRArray & lf_sdr_array,SDRArray & delta_sdr_array,short combine_type)148 compute(const SDRArray& hf_sdr_array, const SDRArray& lf_sdr_array,
149 SDRArray& delta_sdr_array, short combine_type)
150 {
151 size_t i, num_pts = std::min(hf_sdr_array.size(), lf_sdr_array.size());
152
153 // Note: SurrogateData::size_active_sdr() is used to allocate delta_sdr_array
154
155 switch (combine_type) {
156 case MULT_COMBINE:
157 for (i=0; i<num_pts; ++i) {
158 const SurrogateDataResp& lf_sdr = lf_sdr_array[i];
159 const SurrogateDataResp& hf_sdr = hf_sdr_array[i];
160 SurrogateDataResp& delta_sdr = delta_sdr_array[i];
161 short delta_bits = delta_sdr.active_bits();
162 short corr_order = (delta_bits & 2) ? 1 : 0;
163 if (check_multiplicative(hf_sdr.response_function(),
164 lf_sdr.response_function(), corr_order)) {
165 PCerr << "Error: numerical FPE in computing multiplicative discrepancy."
166 << "\n Please change to additive discrepancy." << std::endl;
167 abort_handler(-1);
168 }
169 if (delta_bits & 1)
170 compute_multiplicative(hf_sdr.response_function(),
171 lf_sdr.response_function(),
172 delta_sdr.response_function_view());
173 if (delta_bits & 2) {
174 RealVector delta_grad(delta_sdr.response_gradient_view());
175 compute_multiplicative(hf_sdr.response_function(),
176 hf_sdr.response_gradient(),
177 lf_sdr.response_function(),
178 lf_sdr.response_gradient(), delta_grad);
179 }
180 if (delta_bits & 4) {
181 RealSymMatrix delta_hess(delta_sdr.response_hessian_view());
182 compute_multiplicative(hf_sdr.response_function(),
183 hf_sdr.response_gradient(),
184 hf_sdr.response_hessian(),
185 lf_sdr.response_function(),
186 lf_sdr.response_gradient(),
187 lf_sdr.response_hessian(), delta_hess);
188 }
189 }
190 break;
191 default: //case ADD_COMBINE: (correction specification not required)
192 for (i=0; i<num_pts; ++i) {
193 const SurrogateDataResp& lf_sdr = lf_sdr_array[i];
194 const SurrogateDataResp& hf_sdr = hf_sdr_array[i];
195 SurrogateDataResp& delta_sdr = delta_sdr_array[i];
196 short delta_bits = delta_sdr.active_bits();
197 if (delta_bits & 1)
198 compute_additive(hf_sdr.response_function(), lf_sdr.response_function(),
199 delta_sdr.response_function_view());
200 if (delta_bits & 2) {
201 RealVector delta_grad(delta_sdr.response_gradient_view());
202 compute_additive(hf_sdr.response_gradient(), lf_sdr.response_gradient(),
203 delta_grad);
204 }
205 if (delta_bits & 4) {
206 RealSymMatrix delta_hess(delta_sdr.response_hessian_view());
207 compute_additive(hf_sdr.response_hessian(), lf_sdr.response_hessian(),
208 delta_hess);
209 }
210 }
211 break;
212 }
213 }
214
215
216 void DiscrepancyCalculator::
compute(SurrogateData & surr_data,const UShortArray & delta_key,short combine_type)217 compute(SurrogateData& surr_data, const UShortArray& delta_key,
218 short combine_type)
219 {
220 UShortArray hf_key, lf_key; extract_keys(delta_key, hf_key, lf_key);
221
222 const std::map<UShortArray, SDRArray>& resp_map
223 = surr_data.response_data_map();
224 std::map<UShortArray, SDRArray>::const_iterator
225 lf_cit = resp_map.find(lf_key), hf_cit = resp_map.find(hf_key);
226 if (lf_cit == resp_map.end() || hf_cit == resp_map.end()) {
227 PCerr << "Error: key lookup failure for individual fidelity in Discrepancy"
228 << "Calculator::compute()" << std::endl;
229 abort_handler(-1);
230 }
231
232 surr_data.active_key(delta_key);
233 surr_data.variables_data(surr_data.variables_data(hf_key)); // shallow copies
234 surr_data.anchor_index(surr_data.anchor_index(hf_key));
235 surr_data.pop_count_stack(surr_data.pop_count_stack(hf_key));
236
237 // TO DO: do this more incrementally (based on curr state of delta sdr_array)
238 const SDRArray& hf_sdr_array = hf_cit->second;
239 surr_data.size_active_sdr(hf_sdr_array);
240 compute(hf_sdr_array, lf_cit->second, surr_data.response_data(),combine_type);
241
242 // compute discrepancy faults from scratch (aggregates LF,HF failures)
243 surr_data.data_checks();
244 }
245
246 } // namespace Pecos
247