1 #define _USE_MATH_DEFINES 11 #include <boost/random/mersenne_twister.hpp> 12 #include <boost/random/uniform_real_distribution.hpp> 13 #include <boost/random/variate_generator.hpp> 15 #include <Eigen/Dense> 18 #include "function_dispatcher.h" 19 #include "json_object.h" 20 #include "lognormal_dist.h" 21 #include "normal_dist.h" 22 #include "normal_multivar.h" 23 #include "numeric_utils.h" 24 #include "vlachos_et_al.h" 27 double rupture_distance,
double vs30,
29 unsigned int num_spectra,
30 unsigned int num_sims)
32 moment_magnitude_{moment_magnitude / 6.0},
33 rupture_dist_{(rupture_distance + 5.0) / 30.0},
35 orientation_{orientation},
39 num_spectra_{num_spectra},
41 seed_value_{std::numeric_limits<int>::infinity()},
42 model_parameters_{18} {
43 model_name_ =
"VlachosEtAl";
45 double site_soft = 0.0, site_medium = 0.0, site_hard = 0.0;
48 }
else if (vs30 <= 450.0) {
55 Eigen::VectorXd conditional_means(7);
58 1.0, moment_magnitude_, std::log(rupture_dist_),
59 moment_magnitude_ * std::log(rupture_dist_), site_soft * std::log(vs30_),
60 site_medium * std::log(vs30_), site_hard * std::log(vs30_);
65 Eigen::MatrixXd beta(18, 7);
68 -1.1417, 1.0917, 1.9125, -0.9696, 0.0971, 0.3476, -0.6740,
69 1.8052,-1.8381, -3.5874, 3.7895, 0.3236, 0.5497, 0.2876,
70 1.8969,-1.8819, -2.0818, 1.9000, -0.3520, -0.6959, -0.0025,
71 1.6627,-1.6922, -1.2509, 1.1880, -0.5170, -1.0157, -0.1041,
72 3.8703,-3.4745, -0.0816, 0.0166, 0.4904, 0.8697, 0.3179,
73 1.1043,-1.1852, -1.0068, 0.9388, -0.5603, -0.8855, -0.3174,
74 1.1935,-1.2922, -0.7028, 0.6975, -0.6629, -1.1075, -0.4542,
75 1.7895,-1.5014, -0.0300, -0.1306, 0.4526, 0.7132, 0.1522,
76 -3.6404, 3.3189, -0.5316, 0.3874, -0.3757, -0.8334, 0.1006,
77 -2.2742, 2.1454, 0.6315, -0.6620, 0.1093, -0.1028, -0.0479,
78 0.6930, -0.6202, 1.8037, -1.6064, 0.0727, -0.1498, -0.0722,
79 1.3003, -1.2004, -1.2210, 1.0623, -0.0252, 0.1885, 0.0069,
80 0.4604, -0.4087, -0.5057, 0.4486, 0.1073, -0.0219, -0.1352,
81 2.2304, -2.0398, -0.1364, 0.1910, 0.2425, 0.1801, 0.3233,
82 2.3806, -2.2011, -0.3256, 0.2226, -0.0221, 0.0970, 0.0762,
83 0.2057, -0.1714, 0.3385, -0.2229, 0.0802, 0.2649, 0.0396,
84 -7.6011, 6.8507, -2.3609, 0.9201, -0.7508, -0.7903, -0.6204,
85 -6.3472, 5.8241, 3.2994, -2.8774, -0.1411, -0.5298, -0.0203;
89 Eigen::VectorXd variance(18);
92 0.90, 0.80, 0.78, 0.74, 0.66, 0.73, 0.72, 0.70, 0.69,
93 0.78, 0.90, 0.90, 0.90, 0.90, 0.80, 0.90, 0.35, 0.80;
97 Eigen::MatrixXd correlation_matrix(18, 18);
100 1.0000, 0.0382, -0.0912, -0.0701, -0.0214, -0.0849, -0.0545, -0.0185, 0.0270, -0.0122, 0.0059, -0.0344, -0.0342, 0.0409, -0.0137, -0.0168, -0.0990, -0.6701,
101 0.0382, 1.0000, -0.1159, -0.1856, 0.0681, -0.2018, -0.2765, -0.0304, -0.1719, -0.1157, -0.0347, -0.0277, -0.0189, 0.0357, 0.0657, -0.0070, 0.3690, -0.0510,
102 -0.0912, -0.1159, 1.0000, 0.9467, 0.4123, 0.4815, 0.4240, 0.2120, 0.1070, -0.1898, 0.0506, -0.0661, -0.0380, 0.0260, 0.0506, -0.0317, -0.0278, 0.0245,
103 -0.0701, -0.1856, 0.9467, 1.0000, 0.4075, 0.4891, 0.4940, 0.2285, 0.2009, -0.1709, 0.0365, -0.0579, -0.0999, 0.0467, 0.0410, 0.0027, -0.0966, 0.0631,
104 -0.0214, 0.0681, 0.4123, 0.4075, 1.0000, 0.1772, 0.1337, 0.7315, -0.0066, -0.2787, 0.0703, -0.0541, -0.0453, 0.1597, 0.0792, 0.0220, 0.0606, -0.0844,
105 -0.0849, -0.2018, 0.4815, 0.4891, 0.1772, 1.0000, 0.9448, 0.3749, 0.1682, -0.0831, 0.0124, -0.1236, -0.0346, -0.0054, 0.0877, -0.0197, -0.0867, 0.0281,
106 -0.0545, -0.2765, 0.4240, 0.4940, 0.1337, 0.9448, 1.0000, 0.3530, 0.2305, -0.0546, -0.0223, -0.0782, -0.0872, 0.0074, 0.0999, 0.0066, -0.1358, 0.0626,
107 -0.0185, -0.0304, 0.2120, 0.2285, 0.7315, 0.3749, 0.3530, 1.0000, 0.1939, -0.0617, -0.0017, -0.0942, -0.0332, 0.0813, 0.0810, -0.0032, -0.0870, -0.0599,
108 0.0270, -0.1719, 0.1070, 0.2009, -0.0066, 0.1682, 0.2305, 0.1939, 1.0000, -0.1851, -0.2073, -0.0756, -0.1637, -0.0865, 0.0699, -0.0485, -0.2153, 0.0320,
109 -0.0122, -0.1157, -0.1898, -0.1709, -0.2787, -0.0831, -0.0546, -0.0617, -0.1851, 1.0000, 0.2139, 0.0769, 0.1391, 0.0769, -0.1838, 0.0377, -0.1615, 0.1000,
110 0.0059, -0.0347, 0.0506, 0.0365, 0.0703, 0.0124, -0.0223, -0.0017, -0.2073, 0.2139, 1.0000, -0.1102, -0.0530, 0.0791, 0.0012, 0.0090, -0.0236, 0.0037,
111 -0.0344, -0.0277, -0.0661, -0.0579, -0.0541, -0.1236, -0.0782, -0.0942, -0.0756, 0.0769, -0.1102, 1.0000, -0.2562, -0.0406, 0.3154, 0.0065, -0.0093, -0.0354,
112 -0.0342, -0.0189, -0.0380, -0.0999, -0.0453, -0.0346, -0.0872, -0.0332, -0.1637, 0.1391, -0.0530, -0.2562, 1.0000, -0.1836, -0.1624, -0.5646, 0.0216, 0.0243,
113 0.0409, 0.0357, 0.0260, 0.0467, 0.1597, -0.0054, 0.0074, 0.0813, -0.0865, 0.0769, 0.0791, -0.0406, -0.1836, 1.0000, 0.1624, 0.1989, 0.0549, -0.0411,
114 -0.0137, 0.0657, 0.0506, 0.0410, 0.0792, 0.0877, 0.0999, 0.0810, 0.0699, -0.1838, 0.0012, 0.3154, -0.1624, 0.1624, 1.0000, 0.1552, 0.0844, -0.0637,
115 -0.0168, -0.0070, -0.0317, 0.0027, 0.0220, -0.0197, 0.0066, -0.0032, -0.0485, 0.0377, 0.0090, 0.0065, -0.5646, 0.1989, 0.1552, 1.0000, 0.0058, 0.0503,
116 -0.0990, 0.3690, -0.0278, -0.0966, 0.0606, -0.0867, -0.1358, -0.0870, -0.2153, -0.1615, -0.0236, -0.0093, 0.0216, 0.0549, 0.0844, 0.0058, 1.0000, -0.0930,
117 -0.6701, -0.0510, 0.0245, 0.0631, -0.0844, 0.0281, 0.0626, -0.0599, 0.0320, 0.1000, 0.0037, -0.0354, 0.0243, -0.0411, -0.0637, 0.0503, -0.0930, 1.0000;
121 means_ = beta * conditional_means;
125 (variance.array().sqrt()).matrix());
130 "MultivariateNormal");
131 sample_generator_->generate(parameter_realizations_, means_, covariance_,
133 parameter_realizations_.transposeInPlace();
136 model_parameters_[0] =
138 "LognormalDist", std::move(-1.735), std::move(0.523));
139 model_parameters_[1] =
141 "LognormalDist", std::move(1.009), std::move(0.422));
142 model_parameters_[2] =
144 "NormalDist", std::move(0.249), std::move(1.759));
145 model_parameters_[3] =
147 "NormalDist", std::move(0.768), std::move(1.958));
148 model_parameters_[4] =
150 "LognormalDist", std::move(2.568), std::move(0.557));
151 model_parameters_[5] =
153 "NormalDist", std::move(0.034), std::move(1.471));
154 model_parameters_[6] =
156 "NormalDist", std::move(0.441), std::move(1.733));
157 model_parameters_[7] =
159 "LognormalDist", std::move(3.356), std::move(0.473));
160 model_parameters_[8] =
162 "BetaDist", std::move(2.516), std::move(9.174));
163 model_parameters_[9] =
165 "BetaDist", std::move(3.582), std::move(15.209));
166 model_parameters_[10] =
168 "LognormalDist", std::move(0.746), std::move(0.404));
169 model_parameters_[11] =
171 ->
create(
"StudentstDist", std::move(0.205), std::move(0.232),
173 model_parameters_[12] =
175 "InverseGaussianDist", std::move(0.499), std::move(0.213));
176 model_parameters_[13] =
178 "LognormalDist", std::move(0.702), std::move(0.435));
179 model_parameters_[14] =
181 ->
create(
"StudentstDist", std::move(0.792), std::move(0.157),
183 model_parameters_[15] =
185 "InverseGaussianDist", std::move(0.350), std::move(0.170));
186 model_parameters_[16] =
188 "LognormalDist", std::move(9.470), std::move(1.317));
189 model_parameters_[17] =
191 "LognormalDist", std::move(3.658), std::move(0.375));
194 auto std_normal_dist =
196 "NormalDist", std::move(0.0), std::move(1.0));
198 physical_parameters_.resize(parameter_realizations_.rows(),
199 parameter_realizations_.cols());
202 for (
unsigned int i = 0; i < parameter_realizations_.rows(); ++i) {
203 for (
unsigned int j = 0; j < model_parameters_.size(); ++j) {
204 physical_parameters_(i, j) =
205 (model_parameters_[j]->inv_cumulative_dist_func(
206 std_normal_dist->cumulative_dist_func(
207 std::vector<double>{parameter_realizations_(i, j)})))[0];
214 double rupture_distance,
double vs30,
216 unsigned int num_spectra,
217 unsigned int num_sims,
220 moment_magnitude_{moment_magnitude / 6.0},
221 rupture_dist_{(rupture_distance + 5.0) / 30.0},
223 orientation_{orientation},
227 num_spectra_{num_spectra},
229 seed_value_{seed_value},
230 model_parameters_{18} {
231 model_name_ =
"VlachosEtAl";
233 double site_soft = 0.0, site_medium = 0.0, site_hard = 0.0;
236 }
else if (vs30 <= 450.0) {
243 Eigen::VectorXd conditional_means(7);
246 1.0, moment_magnitude_, std::log(rupture_dist_),
247 moment_magnitude_ * std::log(rupture_dist_), site_soft * std::log(vs30_),
248 site_medium * std::log(vs30_), site_hard * std::log(vs30_);
253 Eigen::MatrixXd beta(18, 7);
256 -1.1417, 1.0917, 1.9125, -0.9696, 0.0971, 0.3476, -0.6740,
257 1.8052,-1.8381, -3.5874, 3.7895, 0.3236, 0.5497, 0.2876,
258 1.8969,-1.8819, -2.0818, 1.9000, -0.3520, -0.6959, -0.0025,
259 1.6627,-1.6922, -1.2509, 1.1880, -0.5170, -1.0157, -0.1041,
260 3.8703,-3.4745, -0.0816, 0.0166, 0.4904, 0.8697, 0.3179,
261 1.1043,-1.1852, -1.0068, 0.9388, -0.5603, -0.8855, -0.3174,
262 1.1935,-1.2922, -0.7028, 0.6975, -0.6629, -1.1075, -0.4542,
263 1.7895,-1.5014, -0.0300, -0.1306, 0.4526, 0.7132, 0.1522,
264 -3.6404, 3.3189, -0.5316, 0.3874, -0.3757, -0.8334, 0.1006,
265 -2.2742, 2.1454, 0.6315, -0.6620, 0.1093, -0.1028, -0.0479,
266 0.6930, -0.6202, 1.8037, -1.6064, 0.0727, -0.1498, -0.0722,
267 1.3003, -1.2004, -1.2210, 1.0623, -0.0252, 0.1885, 0.0069,
268 0.4604, -0.4087, -0.5057, 0.4486, 0.1073, -0.0219, -0.1352,
269 2.2304, -2.0398, -0.1364, 0.1910, 0.2425, 0.1801, 0.3233,
270 2.3806, -2.2011, -0.3256, 0.2226, -0.0221, 0.0970, 0.0762,
271 0.2057, -0.1714, 0.3385, -0.2229, 0.0802, 0.2649, 0.0396,
272 -7.6011, 6.8507, -2.3609, 0.9201, -0.7508, -0.7903, -0.6204,
273 -6.3472, 5.8241, 3.2994, -2.8774, -0.1411, -0.5298, -0.0203;
277 Eigen::VectorXd variance(18);
280 0.90, 0.80, 0.78, 0.74, 0.66, 0.73, 0.72, 0.70, 0.69,
281 0.78, 0.90, 0.90, 0.90, 0.90, 0.80, 0.90, 0.35, 0.80;
285 Eigen::MatrixXd correlation_matrix(18, 18);
287 correlation_matrix <<
288 1.0000, 0.0382, -0.0912, -0.0701, -0.0214, -0.0849, -0.0545, -0.0185, 0.0270, -0.0122, 0.0059, -0.0344, -0.0342, 0.0409, -0.0137, -0.0168, -0.0990, -0.6701,
289 0.0382, 1.0000, -0.1159, -0.1856, 0.0681, -0.2018, -0.2765, -0.0304, -0.1719, -0.1157, -0.0347, -0.0277, -0.0189, 0.0357, 0.0657, -0.0070, 0.3690, -0.0510,
290 -0.0912, -0.1159, 1.0000, 0.9467, 0.4123, 0.4815, 0.4240, 0.2120, 0.1070, -0.1898, 0.0506, -0.0661, -0.0380, 0.0260, 0.0506, -0.0317, -0.0278, 0.0245,
291 -0.0701, -0.1856, 0.9467, 1.0000, 0.4075, 0.4891, 0.4940, 0.2285, 0.2009, -0.1709, 0.0365, -0.0579, -0.0999, 0.0467, 0.0410, 0.0027, -0.0966, 0.0631,
292 -0.0214, 0.0681, 0.4123, 0.4075, 1.0000, 0.1772, 0.1337, 0.7315, -0.0066, -0.2787, 0.0703, -0.0541, -0.0453, 0.1597, 0.0792, 0.0220, 0.0606, -0.0844,
293 -0.0849, -0.2018, 0.4815, 0.4891, 0.1772, 1.0000, 0.9448, 0.3749, 0.1682, -0.0831, 0.0124, -0.1236, -0.0346, -0.0054, 0.0877, -0.0197, -0.0867, 0.0281,
294 -0.0545, -0.2765, 0.4240, 0.4940, 0.1337, 0.9448, 1.0000, 0.3530, 0.2305, -0.0546, -0.0223, -0.0782, -0.0872, 0.0074, 0.0999, 0.0066, -0.1358, 0.0626,
295 -0.0185, -0.0304, 0.2120, 0.2285, 0.7315, 0.3749, 0.3530, 1.0000, 0.1939, -0.0617, -0.0017, -0.0942, -0.0332, 0.0813, 0.0810, -0.0032, -0.0870, -0.0599,
296 0.0270, -0.1719, 0.1070, 0.2009, -0.0066, 0.1682, 0.2305, 0.1939, 1.0000, -0.1851, -0.2073, -0.0756, -0.1637, -0.0865, 0.0699, -0.0485, -0.2153, 0.0320,
297 -0.0122, -0.1157, -0.1898, -0.1709, -0.2787, -0.0831, -0.0546, -0.0617, -0.1851, 1.0000, 0.2139, 0.0769, 0.1391, 0.0769, -0.1838, 0.0377, -0.1615, 0.1000,
298 0.0059, -0.0347, 0.0506, 0.0365, 0.0703, 0.0124, -0.0223, -0.0017, -0.2073, 0.2139, 1.0000, -0.1102, -0.0530, 0.0791, 0.0012, 0.0090, -0.0236, 0.0037,
299 -0.0344, -0.0277, -0.0661, -0.0579, -0.0541, -0.1236, -0.0782, -0.0942, -0.0756, 0.0769, -0.1102, 1.0000, -0.2562, -0.0406, 0.3154, 0.0065, -0.0093, -0.0354,
300 -0.0342, -0.0189, -0.0380, -0.0999, -0.0453, -0.0346, -0.0872, -0.0332, -0.1637, 0.1391, -0.0530, -0.2562, 1.0000, -0.1836, -0.1624, -0.5646, 0.0216, 0.0243,
301 0.0409, 0.0357, 0.0260, 0.0467, 0.1597, -0.0054, 0.0074, 0.0813, -0.0865, 0.0769, 0.0791, -0.0406, -0.1836, 1.0000, 0.1624, 0.1989, 0.0549, -0.0411,
302 -0.0137, 0.0657, 0.0506, 0.0410, 0.0792, 0.0877, 0.0999, 0.0810, 0.0699, -0.1838, 0.0012, 0.3154, -0.1624, 0.1624, 1.0000, 0.1552, 0.0844, -0.0637,
303 -0.0168, -0.0070, -0.0317, 0.0027, 0.0220, -0.0197, 0.0066, -0.0032, -0.0485, 0.0377, 0.0090, 0.0065, -0.5646, 0.1989, 0.1552, 1.0000, 0.0058, 0.0503,
304 -0.0990, 0.3690, -0.0278, -0.0966, 0.0606, -0.0867, -0.1358, -0.0870, -0.2153, -0.1615, -0.0236, -0.0093, 0.0216, 0.0549, 0.0844, 0.0058, 1.0000, -0.0930,
305 -0.6701, -0.0510, 0.0245, 0.0631, -0.0844, 0.0281, 0.0626, -0.0599, 0.0320, 0.1000, 0.0037, -0.0354, 0.0243, -0.0411, -0.0637, 0.0503, -0.0930, 1.0000;
309 means_ = beta * conditional_means;
313 (variance.array().sqrt()).matrix());
318 "MultivariateNormal", std::move(seed_value_));
319 sample_generator_->generate(parameter_realizations_, means_, covariance_,
321 parameter_realizations_.transposeInPlace();
324 model_parameters_[0] =
326 "LognormalDist", std::move(-1.735), std::move(0.523));
327 model_parameters_[1] =
329 "LognormalDist", std::move(1.009), std::move(0.422));
330 model_parameters_[2] =
332 "NormalDist", std::move(0.249), std::move(1.759));
333 model_parameters_[3] =
335 "NormalDist", std::move(0.768), std::move(1.958));
336 model_parameters_[4] =
338 "LognormalDist", std::move(2.568), std::move(0.557));
339 model_parameters_[5] =
341 "NormalDist", std::move(0.034), std::move(1.471));
342 model_parameters_[6] =
344 "NormalDist", std::move(0.441), std::move(1.733));
345 model_parameters_[7] =
347 "LognormalDist", std::move(3.356), std::move(0.473));
348 model_parameters_[8] =
350 "BetaDist", std::move(2.516), std::move(9.714));
351 model_parameters_[9] =
353 "BetaDist", std::move(3.582), std::move(15.209));
354 model_parameters_[10] =
356 "LognormalDist", std::move(0.746), std::move(0.404));
357 model_parameters_[11] =
359 ->
create(
"StudentstDist", std::move(0.205), std::move(0.232),
361 model_parameters_[12] =
363 "InverseGaussianDist", std::move(0.499), std::move(0.213));
364 model_parameters_[13] =
366 "LognormalDist", std::move(0.702), std::move(0.435));
367 model_parameters_[14] =
369 ->
create(
"StudentstDist", std::move(0.792), std::move(0.157),
371 model_parameters_[15] =
373 "InverseGaussianDist", std::move(0.350), std::move(0.170));
374 model_parameters_[16] =
376 "LognormalDist", std::move(9.470), std::move(1.317));
377 model_parameters_[17] =
379 "LognormalDist", std::move(3.658), std::move(0.375));
382 auto std_normal_dist =
384 "NormalDist", std::move(0.0), std::move(1.0));
386 physical_parameters_.resize(parameter_realizations_.rows(),
387 parameter_realizations_.cols());
390 for (
unsigned int i = 0; i < parameter_realizations_.rows(); ++i) {
391 for (
unsigned int j = 0; j < model_parameters_.size(); ++j) {
392 physical_parameters_(i, j) =
393 (model_parameters_[j]->inv_cumulative_dist_func(
394 std_normal_dist->cumulative_dist_func(
395 std::vector<double>{parameter_realizations_(i, j)})))[0];
401 const std::string& event_name,
bool g_units) {
405 std::vector<std::vector<std::vector<double>>> acceleration_pool(
407 std::vector<std::vector<double>>(num_sims_, std::vector<double>()));
412 for (
unsigned int i = 0; i < num_spectra_; ++i) {
413 time_history_family(acceleration_pool[i], physical_parameters_.row(i));
415 }
catch (
const std::exception& e) {
416 std::cerr << e.what();
422 std::vector<utilities::JsonObject> events_array(num_spectra_ * num_sims_);
427 pattern_x.add_value(
"type",
"UniformAcceleration");
428 pattern_x.add_value(
"timeSeries",
"accel_x");
429 pattern_x.add_value(
"dof", 1);
430 pattern_y.add_value(
"type",
"UniformAcceleration");
431 pattern_y.add_value(
"timeSeries",
"accel_y");
432 pattern_y.add_value(
"dof", 2);
437 for (
unsigned int i = 0; i < num_spectra_; ++i) {
439 for (
unsigned int j = 0; j < num_sims_; ++j) {
440 event_data.add_value(
"name", event_name +
"_Spectra" + std::to_string(i) +
441 "_Sim" + std::to_string(j));
442 event_data.add_value(
"type",
"Seismic");
443 event_data.add_value(
"dT", time_step_);
444 event_data.add_value(
"numSteps", acceleration_pool[i][j].size());
445 event_data.add_value(
446 "pattern", std::vector<utilities::JsonObject>{pattern_x, pattern_y});
449 std::vector<double> x_accels(acceleration_pool[i][j].size());
450 std::vector<double> y_accels(acceleration_pool[i][j].size());
451 rotate_acceleration(acceleration_pool[i][j], x_accels, y_accels, g_units);
456 time_history_x.add_value(
"name",
"accel_x");
457 time_history_x.add_value(
"type",
"Value");
458 time_history_x.add_value(
"dT", time_step_);
459 time_history_x.add_value(
"data", x_accels);
460 time_history_y.add_value(
"name",
"accel_y");
461 time_history_y.add_value(
"type",
"Value");
462 time_history_y.add_value(
"dT", time_step_);
463 time_history_y.add_value(
"data", y_accels);
464 event_data.add_value(
"timeSeries", std::vector<utilities::JsonObject>{
465 time_history_x, time_history_y});
466 events_array[i * num_sims_ + j] = event_data;
471 events.add_value(
"Events", events_array);
477 const std::string& output_location,
483 auto json_output = generate(event_name, g_units);
484 json_output.write_to_file(output_location);
485 }
catch (
const std::exception& e) {
486 std::cerr << e.what();
495 std::vector<std::vector<double>>& time_histories,
496 const Eigen::VectorXd& parameters)
const {
498 auto identified_parameters = identify_parameters(parameters);
500 unsigned int num_times =
501 static_cast<unsigned int>(std::ceil(identified_parameters[17] / time_step_)) + 1;
502 unsigned int num_freqs =
503 static_cast<unsigned int>(std::ceil(cutoff_freq_ / freq_step_)) + 1;
505 std::vector<double> times(num_times);
506 std::vector<double> frequencies(num_freqs);
507 double total_time = (num_times - 1) * time_step_;
509 for (
unsigned int i = 0; i < times.size(); ++i) {
510 times[i] = i * time_step_ / total_time;
514 for (
unsigned int i = 0; i < frequencies.size(); ++i) {
515 frequencies[i] = i * freq_step_;
519 auto energy = energy_accumulation(
520 std::vector<double>{identified_parameters[0], identified_parameters[1]},
524 auto mode_1_freqs = modal_frequencies(
525 std::vector<double>{identified_parameters[2], identified_parameters[3],
526 identified_parameters[4]},
528 auto mode_2_freqs = modal_frequencies(
529 std::vector<double>{identified_parameters[5], identified_parameters[6],
530 identified_parameters[7]},
534 auto mode_2_participation = modal_participation_factor(
535 std::vector<double>{identified_parameters[10], identified_parameters[11],
536 identified_parameters[12], identified_parameters[13],
537 identified_parameters[14], identified_parameters[15]},
541 auto amplitude_modulation = amplitude_modulating_function(
542 identified_parameters[17], identified_parameters[16],
543 std::vector<double>{identified_parameters[0], identified_parameters[1]},
547 int filter_order = 4;
548 double norm_cutoff_freq = 0.20;
551 std::vector<double> highpass_butter_energy(frequencies.size());
552 double freq_ratio_sq;
553 for (
unsigned int i = 0; i < frequencies.size(); ++i) {
554 freq_ratio_sq = std::pow(frequencies[i] / (2.0 * M_PI * norm_cutoff_freq),
556 highpass_butter_energy[i] = freq_ratio_sq / (1.0 + freq_ratio_sq);
561 Eigen::MatrixXd power_spectrum(times.size(), frequencies.size());
563 for (
unsigned int i = 0; i < times.size(); ++i) {
564 power_spectrum.row(i) =
565 kt_2(std::vector<double>{mode_1_freqs[i], identified_parameters[8], 1.0,
566 mode_2_freqs[i], identified_parameters[9],
567 mode_2_participation[i]},
568 frequencies, highpass_butter_energy);
570 double freq_domain_integral =
573 power_spectrum.row(i) =
574 power_spectrum.row(i) * amplitude_modulation[i] / freq_domain_integral;
580 static_cast<int>(std::round(1.5 * static_cast<double>(filter_order) /
581 (2.0 * norm_cutoff_freq)) /
587 ->
dispatch(
"HighPassButter", filter_order,
588 norm_cutoff_freq / (1.0 / time_step_ / 2.0));
591 auto impulse_response =
593 int,
int>::instance()
594 ->
dispatch(
"ImpulseResponse", hp_butter[0], hp_butter[1],
595 filter_order, num_samples);
599 for (
unsigned int i = 0; i < num_sims_; ++i) {
600 simulate_time_history(time_histories[i], power_spectrum);
601 post_process(time_histories[i], impulse_response);
603 }
catch (
const std::exception& e) {
604 std::cerr << e.what();
613 std::vector<double>& time_history,
614 const Eigen::MatrixXd& power_spectrum)
const {
615 unsigned int num_times = power_spectrum.rows(),
616 num_freqs = power_spectrum.cols();
618 time_history.resize(num_times, 0.0);
620 std::vector<double> times(num_times);
621 std::vector<double> frequencies(num_freqs);
623 for (
unsigned int i = 0; i < times.size(); ++i) {
624 times[i] = i * time_step_;
627 for (
unsigned int i = 0; i < frequencies.size(); ++i) {
628 frequencies[i] = i * freq_step_;
631 static unsigned int history_seed =
static_cast<unsigned int>(std::time(
nullptr));
632 history_seed = history_seed + 10;
635 seed_value_ != std::numeric_limits<int>::infinity()
636 ? boost::random::mt19937(static_cast<unsigned int>(seed_value_ + 10))
637 : boost::random::mt19937(history_seed);
639 boost::random::uniform_real_distribution<> distribution(0.0, 2.0 * M_PI);
640 boost::random::variate_generator<boost::random::mt19937&,
641 boost::random::uniform_real_distribution<>>
642 angle_gen(generator, distribution);
644 std::vector<double> phase_angle(num_freqs, 0.0);
646 for (
auto & angle : phase_angle) {
651 for (
unsigned int i = 0; i < num_times; ++i) {
652 for (
unsigned int j = 0; j < num_freqs; ++j) {
655 std::sqrt(power_spectrum(i, j)) *
656 std::cos(frequencies[j] * times[i] + phase_angle[j]);
658 time_history[i] = 2.0 * std::sqrt(freq_step_) * time_history[i];
663 std::vector<double>& time_history,
664 const std::vector<double>& filter_imp_resp)
const {
667 double time_hann_2 = 1.0;
669 Eigen::VectorXd window = Eigen::VectorXd::Ones(time_history.size());
670 unsigned int window1_size =
671 static_cast<unsigned int>(time_hann_2 / time_step_ + 1);
672 unsigned int window2_size =
static_cast<unsigned int>((window1_size - 1) / 2);
675 if (time_history.size() < window1_size) {
676 throw std::runtime_error(
677 "\nERROR: in stochastic::VlachosEtAl::post_process: Input time history " 678 "too short for Hanning Window size\n");
684 "HannWindow", window1_size);
686 window.head(window2_size) = hann_window.head(window2_size);
687 window.tail(window2_size) = hann_window.head(window2_size).reverse();
690 double mean = std::accumulate(time_history.begin(), time_history.end(), 0.0) /
691 static_cast<double>(time_history.size());
694 for (
unsigned int i = 0; i < time_history.size(); ++i) {
695 time_history[i] = window[i] * (time_history[i] - mean);
699 std::vector<double> filtered_history(filter_imp_resp.size() +
700 time_history.size() - 1);
703 }
catch (
const std::exception& e) {
704 std::cerr << e.what();
710 time_history = filtered_history;
716 const Eigen::VectorXd& initial_params)
const {
718 std::vector<double> energy(static_cast<unsigned int>(1.0 / 0.05) + 1, 0.0);
720 for (
unsigned int i = 1; i < energy.size(); ++i) {
721 energy[i] = energy[i - 1] + 0.05;
725 std::vector<double> mode_1_params = {initial_params(2),
728 auto mode_1_freqs = modal_frequencies(mode_1_params, energy);
731 std::vector<double> mode_2_params = {initial_params(5),
734 auto mode_2_freqs = modal_frequencies(mode_2_params, energy);
736 double mode_1_mean = initial_params(11), mode_2_mean = initial_params(14);
739 auto std_normal_dist =
741 "NormalDist", std::move(0.0), std::move(1.0));
743 Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic> realizations(
744 initial_params.size(), 1);
745 Eigen::VectorXd transformed_realizations = initial_params;
749 bool freq_comparison =
false;
750 for (
unsigned int i = 0; i < mode_1_freqs.size(); ++i) {
751 if (mode_1_freqs[i] > mode_2_freqs[i]) {
752 freq_comparison =
true;
758 while (freq_comparison || (mode_1_mean > mode_2_mean)) {
761 sample_generator_->generate(realizations, means_, covariance_, 1);
764 for (
unsigned int i = 0; i < initial_params.size(); ++i) {
765 transformed_realizations(i) =
766 (model_parameters_[i]->inv_cumulative_dist_func(
767 std_normal_dist->cumulative_dist_func(
768 std::vector<double>{realizations(i, 0)})))[0];
773 modal_frequencies(std::vector<double>{transformed_realizations(2),
774 transformed_realizations(3),
775 transformed_realizations(4)},
778 mode_2_params = {transformed_realizations(5), transformed_realizations(6),
779 transformed_realizations(7)};
781 modal_frequencies(std::vector<double>{transformed_realizations(5),
782 transformed_realizations(6),
783 transformed_realizations(7)},
786 mode_1_mean = transformed_realizations(11);
787 mode_2_mean = transformed_realizations(14);
791 freq_comparison =
false;
792 for (
unsigned int i = 0; i < mode_1_freqs.size(); ++i) {
793 if (mode_1_freqs[i] > mode_2_freqs[i]) {
794 freq_comparison =
true;
800 return transformed_realizations;
804 const std::vector<double>& parameters,
805 const std::vector<double>& energy)
const {
806 std::vector<double> frequencies(energy.size());
808 for (
unsigned int i = 0; i < energy.size(); ++i) {
809 frequencies[i] = parameters[2] * std::pow(0.5 + energy[i], parameters[0]) *
810 std::pow(1.5 - energy[i], parameters[1]);
817 const std::vector<double>& parameters,
818 const std::vector<double>& times)
const {
819 std::vector<double> accumulated_energy(times.size());
821 for (
unsigned int i = 0; i < times.size(); ++i) {
822 accumulated_energy[i] =
823 std::exp(-std::pow(times[i] / parameters[0], -parameters[1])) /
824 std::exp(-std::pow(1.0 / parameters[0], -parameters[1]));
827 return accumulated_energy;
831 const std::vector<double>& parameters,
832 const std::vector<double>& energy)
const {
833 std::vector<double> participation_factor(energy.size());
835 for (
unsigned int i = 0; i < energy.size(); ++i) {
836 participation_factor[i] = std::pow(
838 parameters[0] * std::exp(-std::pow(
839 (energy[i] - parameters[1]) / parameters[2], 2)) +
842 -std::pow((energy[i] - parameters[4]) / parameters[5], 2)) -
846 return participation_factor;
850 double duration,
double total_energy,
const std::vector<double>& parameters,
851 const std::vector<double>& times)
const {
852 std::vector<double> func_vals(times.size());
854 double mult_term = total_energy * parameters[1] / (parameters[0] * duration);
855 double exponent_1 = std::pow(1.0 / parameters[0], -parameters[1]);
857 for (
unsigned int i = 0; i < times.size(); ++i) {
858 func_vals[i] = mult_term *
859 std::exp(exponent_1 - std::pow(times[i] / parameters[0], -parameters[1])) *
860 std::pow(times[i] / parameters[0], -1.0 - parameters[1]);
867 const std::vector<double>& parameters,
868 const std::vector<double>& frequencies,
869 const std::vector<double>& highpass_butter)
const {
870 Eigen::VectorXd power_spectrum(frequencies.size());
871 double mode1 = 0, mode2 = 0;
873 for (
unsigned int i = 0; i < frequencies.size(); ++i) {
874 mode1 = parameters[2] *
875 (1.0 + 4.0 * parameters[1] * parameters[1] *
876 std::pow(frequencies[i] / parameters[0], 2)) /
877 (std::pow(1 - std::pow(frequencies[i] / parameters[0], 2), 2) +
878 4.0 * parameters[1] * parameters[1] *
879 std::pow(frequencies[i] / parameters[0], 2));
880 mode2 = parameters[5] *
881 (1.0 + 4.0 * parameters[4] * parameters[4] *
882 std::pow(frequencies[i] / parameters[3], 2)) /
883 (std::pow(1 - std::pow(frequencies[i] / parameters[3], 2), 2) +
884 4.0 * parameters[4] * parameters[4] *
885 std::pow(frequencies[i] / parameters[3], 2));
887 power_spectrum[i] = highpass_butter[i] * (mode1 + mode2);
890 return power_spectrum;
894 const std::vector<double>& acceleration, std::vector<double>& x_accels,
895 std::vector<double>& y_accels,
bool g_units)
const {
897 x_accels.resize(acceleration.size());
898 y_accels.resize(acceleration.size());
900 double conversion_factor = g_units ? 100.0 * 9.81 : 100.0;
903 if (std::abs(orientation_) < 1E-6) {
904 for (
unsigned int i = 0; i < acceleration.size(); ++i) {
906 x_accels[i] = acceleration[i] / conversion_factor;
908 y_accels.assign(acceleration.size(), 0.0);
911 for (
unsigned int i = 0; i < acceleration.size(); ++i) {
914 acceleration[i] * std::cos(orientation_ * M_PI / 180.0) / conversion_factor;
916 acceleration[i] * std::sin(orientation_ * M_PI / 180.0) / conversion_factor;
bool convolve_1d(const std::vector< double > &input_x, const std::vector< double > &input_y, std::vector< double > &response)
bool post_process(std::vector< double > &time_history, const std::vector< double > &filter_imp_resp) const
std::vector< double > energy_accumulation(const std::vector< double > ¶meters, const std::vector< double > ×) const
Eigen::VectorXd kt_2(const std::vector< double > ¶meters, const std::vector< double > &frequencies, const std::vector< double > &highpass_butter) const
std::shared_ptr< Tbaseclass > create(const std::string &key, Targs &&...args)
Treturntype dispatch(const std::string &key, Targs...args)
static Factory * instance()
static Dispatcher * instance()
std::vector< double > modal_frequencies(const std::vector< double > ¶meters, const std::vector< double > &energy) const
std::vector< double > amplitude_modulating_function(double duration, double total_energy, const std::vector< double > ¶meters, const std::vector< double > ×) const
bool time_history_family(std::vector< std::vector< double >> &time_histories, const Eigen::VectorXd ¶meters) const
void rotate_acceleration(const std::vector< double > &acceleration, std::vector< double > &x_accels, std::vector< double > &y_accels, bool g_units) const
Eigen::VectorXd identify_parameters(const Eigen::VectorXd &initial_params) const
utilities::JsonObject generate(const std::string &event_name, bool g_units=false) override
double trapazoid_rule(const std::vector< double > &input_vector, double spacing)
Eigen::MatrixXd corr_to_cov(const Eigen::MatrixXd &corr, const Eigen::VectorXd &std_dev)
void simulate_time_history(std::vector< double > &time_history, const Eigen::MatrixXd &power_spectrum) const
std::vector< double > modal_participation_factor(const std::vector< double > ¶meters, const std::vector< double > &energy) const