LCOV - code coverage report
Current view: top level - src/vectorpostprocessors - ResponseHistoryBuilder.C (source / functions) Hit Total Coverage
Test: idaholab/mastodon: 55510a Lines: 69 71 97.2 %
Date: 2025-08-26 23:09:31 Functions: 8 8 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : // MOOSE includes
       2             : #include "PostprocessorInterface.h"
       3             : #include "ResponseHistoryBuilder.h"
       4             : 
       5             : // libMesh includes
       6             : #include "libmesh/parallel_algebra.h"
       7             : 
       8             : // C++ includes
       9             : #include <unistd.h>
      10             : 
      11             : registerMooseObject("MastodonApp", ResponseHistoryBuilder);
      12             : 
      13             : InputParameters
      14         364 : ResponseHistoryBuilder::validParams()
      15             : {
      16         364 :   InputParameters params = NodalVectorPostprocessor::validParams();
      17         728 :   params.addParam<std::vector<dof_id_type>>(
      18             :       "nodes", "Node number(s) at which the response history is needed.");
      19             : 
      20             :   // Force the object to only execute once per node even if it has multiple boundary ids
      21         364 :   params.set<bool>("unique_node_execute") = true;
      22         364 :   params.suppressParameter<bool>("unique_node_execute");
      23             : 
      24        1456 :   params.set<ExecFlagEnum>("execute_on") = {EXEC_INITIAL, EXEC_TIMESTEP_END};
      25         364 :   params.suppressParameter<ExecFlagEnum>("execute_on");
      26             : 
      27         364 :   params.set<bool>("contains_complete_history") = true;
      28         364 :   params.suppressParameter<bool>("contains_complete_history");
      29             : 
      30         728 :   params.addRequiredCoupledVar("variables",
      31             :                                "Variable name for which the response history is requested.");
      32         364 :   params.addClassDescription("Calculates response histories for a given node and variable(s).");
      33         364 :   return params;
      34         364 : }
      35             : 
      36         230 : ResponseHistoryBuilder::ResponseHistoryBuilder(const InputParameters & parameters)
      37             :   : NodalVectorPostprocessor(parameters),
      38         230 :     _var_names(getParam<std::vector<VariableName>>("variables")),
      39         460 :     _history_time(declareVector("time"))
      40             : {
      41             :   // Set that will store the union of node ids from all the boundaries or requested nodes
      42             :   std::set<dof_id_type> history_nodes;
      43             : 
      44         282 :   if (parameters.isParamValid("boundary") && parameters.isParamValid("nodes"))
      45           0 :     mooseError("Error in VectorPostprocessor, '",
      46             :                name(),
      47             :                "'. Please specify either of boundary or node, but not both.");
      48             : 
      49         586 :   if (!parameters.isParamValid("boundary") && !parameters.isParamValid("nodes"))
      50           0 :     mooseError("Error in VectorPostprocessor, '",
      51             :                name(),
      52             :                "'. Please provide either boundary or node for response history output.");
      53             : 
      54         460 :   if (parameters.isParamValid("boundary"))
      55             :   {
      56             :     // Retrieving boundaries and making a set of all the nodes in these boundaries
      57             :     std::set<BoundaryID> bnd_ids =
      58          52 :         boundaryIDs(); // Set containing the boundary IDs input by the user
      59         104 :     for (auto id : boundaryIDs())
      60         104 :       history_nodes.insert(_mesh.getNodeList(id).begin(), _mesh.getNodeList(id).end());
      61             :   }
      62             : 
      63         460 :   if (parameters.isParamValid("nodes"))
      64             :   {
      65             :     // Retrieving vector of nodes from input and storing them in a set, in case
      66             :     // there are repetetions
      67         534 :     std::vector<dof_id_type> vec = getParam<std::vector<dof_id_type>>("nodes");
      68         178 :     history_nodes.insert(vec.begin(), vec.end());
      69         178 :   }
      70             : 
      71             :   // Resizing _history to the number of nodes * number of variables
      72         230 :   _history.resize(_var_names.size() * history_nodes.size());
      73         230 :   _history_names.resize(_history.size());
      74             : 
      75             :   // Declaring _history vectors and creating map from node_id to the location of
      76             :   // the corresponding VPP in _history
      77             :   std::size_t count = 0;
      78         900 :   for (dof_id_type node_id : history_nodes)
      79             :   {
      80        1686 :     for (std::size_t i = 0; i < _var_names.size(); ++i)
      81             :     {
      82        1016 :       _history_names[count * _var_names.size() + i] =
      83        2032 :           "node_" + Moose::stringify(node_id) + "_" + _var_names[i];
      84        1016 :       _history[count * _var_names.size() + i] =
      85        1016 :           &declareVector(_history_names[count * _var_names.size() + i]);
      86             :     }
      87         670 :     _node_map[node_id] = count;
      88         670 :     count++;
      89             :   }
      90             : 
      91             :   // Coupling variables
      92         624 :   for (std::size_t i = 0; i < _var_names.size(); ++i)
      93         788 :     _variables.push_back(&coupledValue("variables", i));
      94         230 : }
      95             : 
      96             : void
      97       12783 : ResponseHistoryBuilder::initialize()
      98             : {
      99       12783 :   _current_data.clear();
     100       12783 :   _current_data.resize(_history.size());
     101       12783 : }
     102             : 
     103             : void
     104        6747 : ResponseHistoryBuilder::finalize()
     105             : {
     106             :   // Data to be added to the current vectors
     107        6747 :   std::vector<Real> data(_history.size());
     108             : 
     109        6747 :   if (n_processors() > 1)
     110             :   {
     111             :     // On each processor _current_data is sized for the number of history vectors (N). The allgather
     112             :     // method puts these vectors together on the root processor in a single vector. Therefore, if
     113             :     // there are two processors (A and B) then the _current_data for each processors are:
     114             :     //    A = [A_0, A_1, ..., A_N]
     115             :     //    B = [B_0, B_1, ..., B_N]
     116             :     // After allgather is executed the _current_data on the root processor becomes:
     117             :     //    _current_data = [A_0, A_1, ..., A_N, B_0, B_1, ..., B_N]
     118        5898 :     _communicator.allgather(_current_data, true);
     119             : 
     120             :     // The values for _current_data are zero everywhere except on the processor on which it was
     121             :     // computed and there should never be repeated values because "unique_node_execute" is true and
     122             :     // the execute method sets the data by index so any repeated calls would overwrite a previous
     123             :     // calculation. Therefore, the data that needs to be added is simply the sum of all the vector
     124             :     // across processors.
     125             :     const std::size_t N = _history.size();
     126       20214 :     for (dof_id_type rank = 0; rank < n_processors(); ++rank)
     127       71268 :       for (std::size_t i = 0; i < _history.size(); ++i)
     128       56952 :         data[i] += _current_data[rank * N + i];
     129             :   }
     130             : 
     131             :   else
     132         849 :     data = _current_data;
     133             : 
     134             :   // Update the history vectors with the new data
     135       33558 :   for (std::size_t i = 0; i < _history.size(); ++i)
     136       26811 :     _history[i]->push_back(data[i]);
     137             : 
     138             :   // Update the time vector
     139        6747 :   _history_time.push_back(_t);
     140        6747 : }
     141             : 
     142             : void
     143        6036 : ResponseHistoryBuilder::threadJoin(const UserObject & uo)
     144             : {
     145             :   // As detailed in the finalize() method the _current_data are zero everywhere except on the
     146             :   // process and thread where it was computed. Thus, adding the values from the other threads
     147             :   // updates the root thread correctly.
     148             :   const ResponseHistoryBuilder & builder = static_cast<const ResponseHistoryBuilder &>(uo);
     149       30096 :   for (std::size_t i = 0; i < _history.size(); ++i)
     150       24060 :     _current_data[i] += builder._current_data[i];
     151        6036 : }
     152             : 
     153             : void
     154       67464 : ResponseHistoryBuilder::execute()
     155             : {
     156             :   // finding the index of the VPP corresponding to _current_node in _history
     157       67464 :   if (_node_map.find(_current_node->id()) != _node_map.end())
     158             :   {
     159             :     // The index of the data within the _history vector for the current node
     160        6786 :     std::size_t loc = _node_map[_current_node->id()];
     161       20196 :     for (std::size_t i = 0; i < _variables.size(); ++i)
     162       13410 :       _current_data[loc * _variables.size() + i] = (*_variables[i])[0];
     163             :   }
     164       67464 : }
     165             : 
     166             : const std::vector<VectorPostprocessorValue *> &
     167         153 : ResponseHistoryBuilder::getHistories() const
     168             : {
     169         153 :   return _history;
     170             : }
     171             : 
     172             : const std::vector<std::string> &
     173          41 : ResponseHistoryBuilder::getHistoryNames() const
     174             : {
     175          41 :   return _history_names;
     176             : }

Generated by: LCOV version 1.14