Skip to content

Commit aa31cee

Browse files
committed
Create a function to perform baseline correction on acceleration time histories
(closes idaholab#296)
1 parent 8f71dbe commit aa31cee

File tree

4 files changed

+568
-0
lines changed

4 files changed

+568
-0
lines changed
+70
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
/*************************************************/
2+
/* DO NOT MODIFY THIS HEADER */
3+
/* */
4+
/* MASTODON */
5+
/* */
6+
/* (c) 2015 Battelle Energy Alliance, LLC */
7+
/* ALL RIGHTS RESERVED */
8+
/* */
9+
/* Prepared by Battelle Energy Alliance, LLC */
10+
/* With the U. S. Department of Energy */
11+
/* */
12+
/* See COPYRIGHT for full restrictions */
13+
/*************************************************/
14+
15+
// This code was implemented in collaboration with Christopher J. Wong
16+
// ([email protected]) from the University of Utah.
17+
18+
#pragma once
19+
20+
// MOOSE includes
21+
#include "Function.h"
22+
#include "LinearInterpolation.h"
23+
24+
// Forward Declarations
25+
class BaselineCorrection;
26+
27+
/**
28+
* Applies a baseline correction to an accceleration time history using least squares polynomial
29+
* fits and outputs the adjusted acceleration with linear interpolation.
30+
*/
31+
class BaselineCorrection : public Function
32+
{
33+
public:
34+
static InputParameters validParams();
35+
36+
BaselineCorrection(const InputParameters & parameters);
37+
38+
virtual Real value(Real t, const Point & /*P*/) const override;
39+
40+
protected:
41+
/// Newmark integration parameters
42+
const Real & _gamma;
43+
const Real & _beta;
44+
45+
/// order used for the least squares polynomial fit
46+
unsigned int _order;
47+
48+
/// acceleration time history variables from input
49+
std::vector<Real> _time;
50+
std::vector<Real> _accel;
51+
52+
/// adjusted (corrected) acceleration ordinates
53+
std::vector<Real> _adj_accel;
54+
55+
/// object to output linearly interpolated corrected acceleration ordinates
56+
std::unique_ptr<LinearInterpolation> _linear_interp;
57+
58+
/// function value scale factor
59+
const Real & _scale_factor;
60+
61+
private:
62+
/// Applies baseline correction to raw acceleration time history
63+
void applyCorrection();
64+
65+
/// Reads and builds data from supplied CSV file
66+
void buildFromFile();
67+
68+
/// Builds data from pairs of `time_values` and `acceleration_values'
69+
void buildFromXandY();
70+
};
+71
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
/*************************************************/
2+
/* DO NOT MODIFY THIS HEADER */
3+
/* */
4+
/* MASTODON */
5+
/* */
6+
/* (c) 2015 Battelle Energy Alliance, LLC */
7+
/* ALL RIGHTS RESERVED */
8+
/* */
9+
/* Prepared by Battelle Energy Alliance, LLC */
10+
/* With the U. S. Department of Energy */
11+
/* */
12+
/* See COPYRIGHT for full restrictions */
13+
/*************************************************/
14+
15+
// This code was implemented in collaboration with Christopher J. Wong
16+
// ([email protected]) from the University of Utah.
17+
18+
#pragma once
19+
20+
// LIBMESH includes
21+
#include "DenseMatrix.h"
22+
#include "libmesh/dense_vector.h"
23+
24+
/**
25+
* This namespace contains the functions used for the calculations corresponding
26+
* to the time history adjustment procedure in BaselineCorrection
27+
**/
28+
namespace BaselineCorrectionUtils
29+
{
30+
/// Evaluates an integral over a single time step with Newmark-beta method
31+
/// Also is used as simple trapezoidal rule when gamma = 0.5.
32+
Real newmarkGammaIntegrate(const Real & u_ddot_old,
33+
const Real & u_ddot,
34+
const Real & u_dot_old,
35+
const Real & gamma,
36+
const Real & dt);
37+
38+
/// Evaluates a double integral over a single time step with Newmark-beta method
39+
Real newmarkBetaIntegrate(const Real & u_ddot_old,
40+
const Real & u_ddot,
41+
const Real & u_dot_old,
42+
const Real & u_old,
43+
const Real & beta,
44+
const Real & dt);
45+
46+
/// Solves linear normal equation for minimum acceleration square error
47+
DenseVector<Real> getAccelerationFitCoeffs(unsigned int order,
48+
const std::vector<Real> & accel,
49+
const std::vector<Real> & t,
50+
const unsigned int & num_steps,
51+
const Real & gamma);
52+
53+
/// Solves linear normal equation for minimum velocity square error
54+
DenseVector<Real> getVelocityFitCoeffs(unsigned int order,
55+
const std::vector<Real> & accel,
56+
const std::vector<Real> & vel,
57+
const std::vector<Real> & t,
58+
const unsigned int & num_steps,
59+
const Real & beta);
60+
61+
/// Solves linear normal equation for minimum displacement square error
62+
DenseVector<Real> getDisplacementFitCoeffs(unsigned int order,
63+
const std::vector<Real> & disp,
64+
const std::vector<Real> & t,
65+
const unsigned int & num_steps);
66+
67+
/// Evaluates the least squares polynomials over at a single time step
68+
std::vector<Real>
69+
computePolynomials(unsigned int order, const DenseVector<Real> & coeffs, const Real & t);
70+
71+
} // namespace BaselineCorrectionUtils

src/functions/BaselineCorrection.C

+247
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,247 @@
1+
/*************************************************/
2+
/* DO NOT MODIFY THIS HEADER */
3+
/* */
4+
/* MASTODON */
5+
/* */
6+
/* (c) 2015 Battelle Energy Alliance, LLC */
7+
/* ALL RIGHTS RESERVED */
8+
/* */
9+
/* Prepared by Battelle Energy Alliance, LLC */
10+
/* With the U. S. Department of Energy */
11+
/* */
12+
/* See COPYRIGHT for full restrictions */
13+
/*************************************************/
14+
15+
// This code was implemented in collaboration with Christopher J. Wong
16+
// ([email protected]) from the University of Utah.
17+
18+
// MASTODON includes
19+
#include "BaselineCorrection.h"
20+
#include "BaselineCorrectionUtils.h"
21+
22+
// MOOSE includes
23+
#include "DelimitedFileReader.h"
24+
25+
registerMooseObject("MastodonApp", BaselineCorrection);
26+
27+
InputParameters
28+
BaselineCorrection::validParams()
29+
{
30+
InputParameters params = Function::validParams();
31+
params.addClassDescription("Applies a baseline correction to an accceleration time history "
32+
"using least squares polynomial fits and outputs the adjusted "
33+
"acceleration with linear interpolation.");
34+
35+
params.addParam<FileName>(
36+
"data_file", "The name of a CSV file containing raw acceleration time history data.");
37+
params.addParam<std::string>(
38+
"time_name",
39+
"The header name of the column which contains the time values in the data file. If not "
40+
"specified, they are assumed to be in the first column index.");
41+
params.addParam<std::string>(
42+
"acceleration_name",
43+
"The header name for the column which contains the acceleration values in the data file. If "
44+
"not specified, they are assumed to be in the second column index.");
45+
46+
params.addParam<std::vector<Real>>("time_values", "The time abscissa values.");
47+
params.addParam<std::vector<Real>>("acceleration_values", "The acceleration ordinate values.");
48+
49+
params.addRequiredParam<Real>("gamma", "The gamma parameter for Newmark time integration.");
50+
params.addRequiredParam<Real>("beta", "The beta parameter for Newmark time integration.");
51+
52+
params.addRangeCheckedParam<unsigned int>(
53+
"accel_fit_order",
54+
"(0 <= accel_fit_order) & (accel_fit_order < 10)",
55+
"If this is provided, the acceleration time history will be adjusted using an nth-order "
56+
"polynomial fit of the nominal acceleration data, where n = accel_fit_order (only integer "
57+
"values from 0 to 9 are supported).");
58+
params.addRangeCheckedParam<unsigned int>(
59+
"vel_fit_order",
60+
"(0 <= vel_fit_order) & (vel_fit_order < 10)",
61+
"If this is provided, the acceleration time history will be adjusted using an nth-order "
62+
"polynomial fit of the nominal velocity data, where n = vel_fit_order (only integer values "
63+
"from 0 to 9 are supported).");
64+
params.addRangeCheckedParam<unsigned int>(
65+
"disp_fit_order",
66+
"(0 <= disp_fit_order) & (disp_fit_order < 10)",
67+
"If this is provided, the acceleration time history will be adjusted using an nth-order "
68+
"polynomial fit of the nominal displacement data, where n = disp_fit_order (only integer "
69+
"values from 0 to 9 are supported).");
70+
71+
params.addParam<Real>("scale_factor",
72+
1.0,
73+
"A scale factor to be applied to the adjusted acceleration time history.");
74+
params.declareControllable("scale_factor");
75+
76+
return params;
77+
}
78+
79+
BaselineCorrection::BaselineCorrection(const InputParameters & parameters)
80+
: Function(parameters),
81+
_gamma(getParam<Real>("gamma")),
82+
_beta(getParam<Real>("beta")),
83+
_scale_factor(getParam<Real>("scale_factor"))
84+
{
85+
// determine data source and check parameter consistency
86+
if (isParamValid("data_file") && !isParamValid("time_values") &&
87+
!isParamValid("acceleration_values"))
88+
buildFromFile();
89+
else if (!isParamValid("data_file") && isParamValid("time_values") &&
90+
isParamValid("acceleration_values"))
91+
buildFromXandY();
92+
else
93+
mooseError("In BaselineCorrection ",
94+
_name,
95+
": Either `data_file` or `time_values` and `acceleration_values` must be specified "
96+
"exclusively.");
97+
98+
// size checks
99+
if (_time.size() != _accel.size())
100+
mooseError("In BaselineCorrection ",
101+
_name,
102+
": The length of time and acceleration data must be equal.");
103+
if (_time.size() == 0 || _accel.size() == 0)
104+
mooseError(
105+
"In BaselineCorrection ", _name, ": The length of time and acceleration data must be > 0.");
106+
107+
// check that at lease one least squares fit will be applied
108+
if (!isParamValid("accel_fit_order") && !isParamValid("vel_fit_order") &&
109+
!isParamValid("disp_fit_order"))
110+
mooseError("In BaselineCorrection ",
111+
_name,
112+
": No values were input for parameters 'accel_fit_order', 'vel_fit_order', or "
113+
"'disp_fit_order'. Please specify an integer value from 0 to 9 for at least one "
114+
"of these parameters.");
115+
116+
// apply baseline correction to raw acceleration time history
117+
applyCorrection();
118+
119+
// try building a linear interpolation object
120+
try
121+
{
122+
_linear_interp = libmesh_make_unique<LinearInterpolation>(_time, _adj_accel);
123+
}
124+
catch (std::domain_error & e)
125+
{
126+
mooseError("In BaselineCorrection ", _name, ": ", e.what());
127+
}
128+
}
129+
130+
Real
131+
BaselineCorrection::value(Real t, const Point & /*P*/) const
132+
{
133+
return _scale_factor * _linear_interp->sample(t);
134+
}
135+
136+
void
137+
BaselineCorrection::applyCorrection()
138+
{
139+
// store a reference to final array index
140+
unsigned int index_end = _accel.size() - 1;
141+
142+
// Compute unadjusted velocity and displacment time histories
143+
Real dt;
144+
std::vector<Real> vel, disp;
145+
vel.push_back(0);
146+
disp.push_back(0);
147+
for (unsigned int i = 0; i < index_end; ++i)
148+
{
149+
dt = _time[i + 1] - _time[i];
150+
151+
vel.push_back(BaselineCorrectionUtils::newmarkGammaIntegrate(
152+
_accel[i], _accel[i + 1], vel[i], _gamma, dt));
153+
disp.push_back(BaselineCorrectionUtils::newmarkBetaIntegrate(
154+
_accel[i], _accel[i + 1], vel[i], disp[i], _beta, dt));
155+
}
156+
157+
// initialize polyfits and adjusted time history arrays as the nominal ones
158+
DenseVector<Real> coeffs;
159+
_adj_accel = _accel;
160+
std::vector<Real> p_fit, adj_vel = vel, adj_disp = disp;
161+
162+
// adjust time histories with acceleration fit if desired
163+
if (isParamValid("accel_fit_order"))
164+
{
165+
_order = getParam<unsigned int>("accel_fit_order");
166+
coeffs = BaselineCorrectionUtils::getAccelerationFitCoeffs(
167+
_order, _adj_accel, _time, index_end, _gamma);
168+
169+
for (unsigned int i = 0; i <= index_end; ++i)
170+
{
171+
p_fit = BaselineCorrectionUtils::computePolynomials(_order, coeffs, _time[i]);
172+
_adj_accel[i] -= p_fit[0];
173+
adj_vel[i] -= p_fit[1];
174+
adj_disp[i] -= p_fit[2];
175+
}
176+
}
177+
178+
// adjust with velocity fit
179+
if (isParamValid("vel_fit_order"))
180+
{
181+
_order = getParam<unsigned int>("vel_fit_order");
182+
coeffs = BaselineCorrectionUtils::getVelocityFitCoeffs(
183+
_order, _adj_accel, adj_vel, _time, index_end, _beta);
184+
185+
for (unsigned int i = 0; i <= index_end; ++i)
186+
{
187+
p_fit = BaselineCorrectionUtils::computePolynomials(_order, coeffs, _time[i]);
188+
_adj_accel[i] -= p_fit[0];
189+
adj_disp[i] -= p_fit[2];
190+
}
191+
}
192+
193+
// adjust with displacement fit
194+
if (isParamValid("disp_fit_order"))
195+
{
196+
_order = getParam<unsigned int>("disp_fit_order");
197+
coeffs = BaselineCorrectionUtils::getDisplacementFitCoeffs(_order, adj_disp, _time, index_end);
198+
199+
for (unsigned int i = 0; i <= index_end; ++i)
200+
{
201+
p_fit = BaselineCorrectionUtils::computePolynomials(_order, coeffs, _time[i]);
202+
_adj_accel[i] -= p_fit[0];
203+
}
204+
}
205+
}
206+
207+
void
208+
BaselineCorrection::buildFromFile()
209+
{
210+
// Read data from CSV file
211+
MooseUtils::DelimitedFileReader reader(getParam<FileName>("data_file"), &_communicator);
212+
reader.read();
213+
214+
// Check if specific column headers were input
215+
const bool time_header = isParamValid("time_name"),
216+
accel_header = isParamValid("acceleration_name");
217+
218+
if (time_header && !accel_header)
219+
mooseError("In BaselineCorrection ",
220+
_name,
221+
": A column header name was specified for the for the time data. Please specify a ",
222+
"header for the acceleration data using the 'acceleration_name' parameter.");
223+
else if (!time_header && accel_header)
224+
mooseError("In BaselineCorrection ",
225+
_name,
226+
": A column header name was specified for the for the acceleration data. Please "
227+
"specify a header for the time data using the 'time_name' parameter.");
228+
229+
// Obtain acceleration time history from file data
230+
if (time_header && accel_header)
231+
{
232+
_time = reader.getData(getParam<std::string>("time_name"));
233+
_accel = reader.getData(getParam<std::string>("acceleration_name"));
234+
}
235+
else
236+
{
237+
_time = reader.getData(0);
238+
_accel = reader.getData(1);
239+
}
240+
}
241+
242+
void
243+
BaselineCorrection::buildFromXandY()
244+
{
245+
_time = getParam<std::vector<Real>>("time_values");
246+
_accel = getParam<std::vector<Real>>("acceleration_values");
247+
}

0 commit comments

Comments
 (0)