32#ifndef RESPONSE_SPECTRUM_H
33#define RESPONSE_SPECTRUM_H
41 const T alpha = omega * zeta;
42 const T beta = omega * std::sqrt(1. - zeta * zeta);
45 T a{0.}, b{0.}, c{0.};
47 T amplitude(
const Col<T>& data) {
return std::max(std::abs(data.max()), std::abs(data.min())); }
49 void compute_parameter(
const T interval) {
50 const auto exp_term = std::exp(-alpha * interval);
52 a = exp_term * std::sin(beta * interval) / beta;
53 b = 2. * exp_term * std::cos(beta * interval);
54 c = exp_term * exp_term;
56 gamma = (1. - b + c) / a / interval / omega / omega;
59 std::tuple<Col<T>, Col<T>, Col<T>> populate_response(
const T interval,
const Col<T>& motion) {
60 this->compute_parameter(interval);
62 Col<T> displacement(motion.n_elem, fill::none);
63 displacement(0) =
T(0);
64 displacement(1) = b * displacement(0) - motion(0);
66 for(
auto I = 2llu, J = 1llu,
K = 0llu; I < motion.n_elem; ++I, ++J, ++
K) displacement(I) = b * displacement(J) - c * displacement(
K) - motion(J);
68 const auto n_elem = motion.n_elem - 1llu;
70 Col<T> velocity(motion.n_elem, fill::none);
72 velocity.tail(n_elem) = arma::diff(displacement);
74 Col<T> acceleration(motion.n_elem, fill::none);
75 acceleration(0) =
T(0);
76 acceleration.tail(n_elem) = arma::diff(velocity);
78 return std::make_tuple(displacement, velocity, acceleration);
87 Col<T> displacement, velocity, acceleration;
88 std::tie(displacement, velocity, acceleration) = this->populate_response(interval, motion);
90 const auto factor = gamma * a;
92 displacement *= factor * interval;
94 acceleration *= factor / interval;
96 return arma::join_rows(displacement, velocity, acceleration);
100 Col<T> displacement, velocity, acceleration;
101 std::tie(displacement, velocity, acceleration) = this->populate_response(interval, motion);
103 const auto factor = gamma * a;
105 const auto max_u = this->amplitude(displacement) * factor * interval;
106 const auto max_v = this->amplitude(velocity) * factor;
107 const auto max_a = this->amplitude(acceleration * factor / interval + motion);
109 return {max_u, max_v, max_a};
121template<sp_d T> Mat<T>
response_spectrum(
const T damping_ratio,
const T interval,
const Col<T>& motion,
const Col<T>& period) {
122 Mat<T> spectrum(3, period.n_elem, fill::none);
125 if(!suanpan::approx_equal(period(I), T(0), 10000)) [[likely]] spectrum.col(I) = Oscillator(datum::tau / period(I), damping_ratio).compute_maximum_response(interval, motion);
127 spectrum.col(I)(0) = spectrum.col(I)(1) = T(0);
128 spectrum.col(I)(2) = std::max(std::abs(motion.max()), std::abs(motion.min()));
132 arma::inplace_trans(spectrum);
134 return arma::join_rows(period, spectrum);
145template<sp_d T> Mat<T>
sdof_response(
const T damping_ratio,
const T interval,
const T freq,
const Col<T>& motion) {
146 Oscillator system(freq * datum::tau, damping_ratio);
148 return arma::join_rows(interval * arma::regspace<Col<T>>(
T(0),
static_cast<double>(motion.n_elem) -
T(1)), system.
compute_response(interval, motion));
Definition: response_spectrum.h:37
Mat< T > sdof_response(const T damping_ratio, const T interval, const T freq, const Col< T > &motion)
compute response of a linear SDOF system
Definition: response_spectrum.h:145
Oscillator(const T O, const T Z)
Definition: response_spectrum.h:82
Mat< T > response_spectrum(const T damping_ratio, const T interval, const Col< T > &motion, const Col< T > &period)
compute response spectrum of the given ground motion
Definition: response_spectrum.h:121
Mat< T > compute_response(const T interval, const Col< T > &motion)
Definition: response_spectrum.h:86
Col< T > compute_maximum_response(const T interval, const Col< T > &motion)
Definition: response_spectrum.h:99
void for_each(const IT start, const IT end, F &&FN)
Definition: utility.h:28