LCOV - code coverage report
Current view: top level - src/userobjects - HazardCurve.C (source / functions) Hit Total Coverage
Test: idaholab/mastodon: 55510a Lines: 66 77 85.7 %
Date: 2025-08-26 23:09:31 Functions: 9 10 90.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : // MOOSE includes
       2             : #include "DelimitedFileReader.h"
       3             : #include "LinearInterpolation.h"
       4             : 
       5             : // MASTODON includes
       6             : #include "HazardCurve.h"
       7             : #include "MastodonUtils.h"
       8             : 
       9             : registerMooseObject("MastodonApp", HazardCurve);
      10             : 
      11             : InputParameters
      12          25 : HazardCurve::validParams()
      13             : {
      14          25 :   InputParameters params = GeneralUserObject::validParams();
      15          25 :   params.addClassDescription(
      16             :       "Reads the hazard curve file and creates ground motion bins for time-based assessment.");
      17          25 :   params.set<ExecFlagEnum>("execute_on") = EXEC_NONE;
      18          25 :   params.suppressParameter<ExecFlagEnum>("execute_on");
      19          50 :   params.addRequiredParam<UserObjectName>("ground_motions",
      20             :                                           "The GroundMotionReader object to extract ground motion "
      21             :                                           "data from to build the hazard curve.");
      22          50 :   params.addRequiredParam<std::string>("filename", "The hazard curve csv filename.");
      23          50 :   params.addParam<unsigned int>(
      24          50 :       "number_of_bins", 10, "The number of bins to create from the hazard curve data.");
      25          50 :   params.addRequiredParam<std::vector<Real>>("reference_acceleration",
      26             :                                              "Ground motion reference acceleration(s).");
      27          25 :   return params;
      28           0 : }
      29             : 
      30          13 : HazardCurve::HazardCurve(const InputParameters & parameters)
      31             :   : GeneralUserObject(parameters),
      32          13 :     _hazard_reader(getParam<std::string>("filename")),
      33          26 :     _ground_motion_reader(getUserObject<GroundMotionReader>("ground_motions"))
      34             : {
      35          13 :   const unsigned int & n_bins = getParam<unsigned int>("number_of_bins");
      36          26 :   const std::vector<Real> & ref = getParam<std::vector<Real>>("reference_acceleration");
      37          13 :   if (ref.size() == 1)
      38          12 :     _reference.resize(n_bins, ref[0]);
      39           1 :   else if (ref.size() == n_bins)
      40           0 :     _reference = ref;
      41             :   else
      42           1 :     mooseError("The 'reference_acceleration' input must (size: ",
      43           1 :                ref.size(),
      44             :                ") in the '",
      45             :                name(),
      46             :                "' block should be a scalar or a vector equal to the length of the "
      47             :                "prescribed number of bins (",
      48             :                n_bins,
      49             :                ").");
      50             : 
      51          12 :   execute();
      52          12 : }
      53             : 
      54             : void
      55          12 : HazardCurve::execute()
      56             : {
      57          12 :   _hazard_reader.read();
      58          24 :   _ground_motion_data = HazardCurve::execute(
      59          12 :       name(), _reference, _hazard_reader, _ground_motion_reader.readers(), _hazard_sample);
      60          12 : }
      61             : 
      62             : const std::vector<Real> &
      63         336 : HazardCurve::getData(const std::size_t & bin,
      64             :                      const std::size_t & index,
      65             :                      const GroundMotionReader::Component & comp) const
      66             : {
      67         336 :   if (bin >= _ground_motion_data.size())
      68           0 :     mooseError("The supplied bin number (",
      69             :                bin,
      70             :                ") is out of range of the available number of bins (",
      71           0 :                _ground_motion_data.size(),
      72             :                ").");
      73         336 :   if (index >= _ground_motion_data[bin].size())
      74           0 :     mooseError("The supplied index number (",
      75             :                index,
      76             :                ") is out of range of the available number of ground motions (",
      77           0 :                _ground_motion_data[bin].size(),
      78             :                ").");
      79         336 :   return _ground_motion_data[bin][index].at(comp);
      80             : }
      81             : 
      82             : const std::vector<std::pair<Real, Real>> &
      83           0 : HazardCurve::getSamples() const
      84             : {
      85           0 :   return _hazard_sample;
      86             : }
      87             : 
      88             : std::vector<GroundMotionReader::Data>
      89          13 : HazardCurve::execute(
      90             :     const std::string & name,
      91             :     const std::vector<Real> & reference,
      92             :     const MooseUtils::DelimitedFileReader & hazard_reader,
      93             :     const std::vector<std::unique_ptr<MooseUtils::DelimitedFileReader>> & ground_motion_readers,
      94             :     std::vector<std::pair<Real, Real>> & sample_data)
      95             : {
      96             :   // Read hazard curve data
      97          13 :   const std::vector<std::vector<double>> & data = hazard_reader.getData();
      98             :   mooseAssert(!data.empty(), "The supplied hazard data is empty.");
      99             : 
     100             :   // Number of bins
     101          13 :   const unsigned int n_bins = reference.size();
     102             : 
     103             :   // Adjust the data for linear interpolation
     104          13 :   std::vector<Real> pga = data[1];                        // x-axis: Peak ground acceleration
     105          13 :   std::vector<Real> mafe = MastodonUtils::log10(data[0]); // y-axis: fannual frequency of exceedence
     106          13 :   if (pga.front() > pga.back())
     107             :   {
     108           0 :     std::reverse(pga.begin(), pga.end());
     109           0 :     std::reverse(mafe.begin(), mafe.end());
     110             :   }
     111             : 
     112             :   // Build linear interpolation object
     113          13 :   LinearInterpolation linear_interp(pga, mafe);
     114             : 
     115             :   // Determine bin spacing
     116             :   std::vector<double>::const_iterator x_min = std::min_element(pga.begin(), pga.end());
     117             :   std::vector<double>::const_iterator x_max = std::max_element(pga.begin(), pga.end());
     118          13 :   double dx = (*x_max - *x_min) / n_bins;
     119             : 
     120             :   // Clear sample data
     121          13 :   sample_data.clear();
     122          13 :   sample_data.reserve(n_bins);
     123             : 
     124             :   // Populate ground motion data
     125          13 :   std::vector<GroundMotionReader::Data> ground_motion_data(n_bins);
     126          13 :   double x = (*x_min) + dx / 2.;
     127          51 :   for (unsigned int i = 0; i < n_bins; ++i)
     128             :   {
     129          38 :     Real scale = x / reference[i];
     130          76 :     ground_motion_data[i] = GroundMotionReader::getData(name, ground_motion_readers, scale);
     131             : 
     132          38 :     Real y = linear_interp.sample(x);
     133          38 :     sample_data.emplace_back(x, std::pow(10, y));
     134             : 
     135          38 :     x += dx;
     136             :   }
     137          13 :   return ground_motion_data;
     138          13 : }
     139             : 
     140             : unsigned int
     141           9 : HazardCurve::count() const
     142             : {
     143           9 :   check();
     144             :   unsigned int num = 0;
     145          27 :   for (std::size_t i = 0; i < bins(); ++i)
     146          18 :     num += count(i);
     147           9 :   return num;
     148             : }
     149             : 
     150             : std::size_t
     151         348 : HazardCurve::count(const std::size_t & /*bin*/) const
     152             : {
     153             :   // TODO: In the future it may be possible to have a different number of ground motions per
     154             :   // bin, this method will allow that to work without changing the API.
     155         348 :   check();
     156         348 :   return _ground_motion_reader.count();
     157             : }
     158             : 
     159             : std::size_t
     160         144 : HazardCurve::bins() const
     161             : {
     162         144 :   check();
     163         144 :   return _reference.size();
     164             : }
     165             : 
     166             : void
     167         501 : HazardCurve::check() const
     168             : {
     169         501 :   if (_ground_motion_data.empty())
     170           0 :     mooseError("The HazardCurve '",
     171             :                name(),
     172             :                "' does not contain data, please check the 'execute_on' settings to make sure the "
     173             :                "object was executed.");
     174         501 : }

Generated by: LCOV version 1.14