LCOV - code coverage report
Current view: top level - src/vectorpostprocessors - SamplerBase.C (source / functions) Hit Total Coverage
Test: idaholab/moose framework: 2bf808 Lines: 74 74 100.0 %
Date: 2025-07-17 01:28:37 Functions: 9 9 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : //* This file is part of the MOOSE framework
       2             : //* https://mooseframework.inl.gov
       3             : //*
       4             : //* All rights reserved, see COPYRIGHT for full restrictions
       5             : //* https://github.com/idaholab/moose/blob/master/COPYRIGHT
       6             : //*
       7             : //* Licensed under LGPL 2.1, please see LICENSE for details
       8             : //* https://www.gnu.org/licenses/lgpl-2.1.html
       9             : 
      10             : #include "SamplerBase.h"
      11             : 
      12             : // MOOSE includes
      13             : #include "IndirectSort.h"
      14             : #include "InputParameters.h"
      15             : #include "MooseEnum.h"
      16             : #include "MooseError.h"
      17             : #include "VectorPostprocessor.h"
      18             : #include "MooseVariableFieldBase.h"
      19             : #include "MooseBaseParameterInterface.h"
      20             : 
      21             : #include "libmesh/point.h"
      22             : 
      23             : InputParameters
      24      131636 : SamplerBase::validParams()
      25             : {
      26      131636 :   InputParameters params = emptyInputParameters();
      27             : 
      28      131636 :   MooseEnum sort_options("x y z id");
      29      131636 :   params.addRequiredParam<MooseEnum>("sort_by", sort_options, "What to sort the samples by");
      30             : 
      31             :   // The value from this VPP is naturally already on every processor
      32             :   // TODO: Make this not the case!  See #11415
      33      131636 :   params.set<bool>("_auto_broadcast") = false;
      34             : 
      35      263272 :   return params;
      36      131636 : }
      37             : 
      38        1650 : SamplerBase::SamplerBase(const InputParameters & parameters,
      39             :                          VectorPostprocessor * vpp,
      40        1650 :                          const libMesh::Parallel::Communicator & comm)
      41        1650 :   : _sampler_params(parameters),
      42        1650 :     _vpp(vpp),
      43        1650 :     _comm(comm),
      44        1650 :     _sort_by(parameters.get<MooseEnum>("sort_by")),
      45        1650 :     _x(vpp->declareVector("x")),
      46        1650 :     _y(vpp->declareVector("y")),
      47        1650 :     _z(vpp->declareVector("z")),
      48        3300 :     _id(vpp->declareVector("id"))
      49             : {
      50        1650 : }
      51             : 
      52             : void
      53        1626 : SamplerBase::setupVariables(const std::vector<std::string> & variable_names)
      54             : {
      55        1626 :   _variable_names = variable_names;
      56        1626 :   _values.reserve(variable_names.size());
      57             : 
      58        3835 :   for (const auto & variable_name : variable_names)
      59        2209 :     _values.push_back(&_vpp->declareVector(variable_name));
      60        1626 : }
      61             : 
      62             : void
      63      209508 : SamplerBase::addSample(const Point & p, const Real & id, const std::vector<Real> & values)
      64             : {
      65      209508 :   _x.push_back(p(0));
      66      209508 :   _y.push_back(p(1));
      67      209508 :   _z.push_back(p(2));
      68             : 
      69      209508 :   _id.push_back(id);
      70             : 
      71             :   mooseAssert(values.size() == _variable_names.size(), "Mismatch of variable names to vector size");
      72      424501 :   for (MooseIndex(values) i = 0; i < values.size(); ++i)
      73      214993 :     _values[i]->emplace_back(values[i]);
      74      209508 : }
      75             : 
      76             : void
      77       13009 : SamplerBase::initialize()
      78             : {
      79             :   // Don't reset the vectors if we want to retain history
      80       13009 :   if (_vpp->containsCompleteHistory() && _comm.rank() == 0)
      81         400 :     return;
      82             : 
      83       12609 :   _x.clear();
      84       12609 :   _y.clear();
      85       12609 :   _z.clear();
      86       12609 :   _id.clear();
      87             : 
      88       12609 :   std::for_each(
      89       13934 :       _values.begin(), _values.end(), [](VectorPostprocessorValue * vec) { vec->clear(); });
      90             : }
      91             : 
      92             : void
      93        1819 : SamplerBase::checkForStandardFieldVariableType(const MooseVariableFieldBase * const var_ptr,
      94             :                                                const std::string & var_param_name) const
      95             : {
      96             :   // A pointer to a MooseVariableFieldBase should never be SCALAR
      97             :   mooseAssert(var_ptr->feType().family != SCALAR,
      98             :               "Scalar variable '" + var_ptr->name() + "' cannot be sampled.");
      99             :   mooseAssert(dynamic_cast<const MooseObject *>(_vpp), "Should have succeeded");
     100        1819 :   if (var_ptr->isVector())
     101          16 :     dynamic_cast<const MooseObject *>(_vpp)->paramError(
     102             :         var_param_name,
     103             :         "The variable '",
     104           8 :         var_ptr->name(),
     105             :         "' is a vector variable. Sampling those is not currently supported in the "
     106             :         "framework. It may be supported using a dedicated object in your application. Use "
     107             :         "'VectorVariableComponentAux' auxkernel to copy those values into a regular field "
     108             :         "variable");
     109        1811 :   if (var_ptr->isArray())
     110          16 :     dynamic_cast<const MooseObject *>(_vpp)->paramError(
     111             :         var_param_name,
     112             :         "The variable '",
     113           8 :         var_ptr->name(),
     114             :         "' is an array variable. Sampling those is not currently supported in the "
     115             :         "framework. It may be supported using a dedicated object in your application. Use "
     116             :         "'ArrayVariableComponent' auxkernel to copy those values into a regular field variable");
     117        1803 : }
     118             : 
     119             : void
     120        8733 : SamplerBase::finalize()
     121             : {
     122             :   /**
     123             :    * We have several vectors that all need to be processed in the same way.
     124             :    * Rather than enumerate them all, let's just create a vector of pointers
     125             :    * and work on them that way.
     126             :    */
     127        8733 :   constexpr auto NUM_ID_VECTORS = 4;
     128             : 
     129        8733 :   std::vector<VectorPostprocessorValue *> vec_ptrs;
     130        8733 :   vec_ptrs.reserve(_values.size() + NUM_ID_VECTORS);
     131             :   // Initialize the pointer vector with the position and ID vectors
     132        8733 :   vec_ptrs = {{&_x, &_y, &_z, &_id}};
     133             :   // Now extend the vector by all the remaining values vector before processing
     134        8733 :   vec_ptrs.insert(vec_ptrs.end(), _values.begin(), _values.end());
     135             : 
     136             :   // Gather up each of the partial vectors
     137       53165 :   for (auto vec_ptr : vec_ptrs)
     138       44432 :     _comm.allgather(*vec_ptr, /* identical buffer lengths = */ false);
     139             : 
     140             :   // Now create an index vector by using an indirect sort
     141        8733 :   std::vector<std::size_t> sorted_indices;
     142        8733 :   Moose::indirectSort(vec_ptrs[_sort_by]->begin(), vec_ptrs[_sort_by]->end(), sorted_indices);
     143             : 
     144             :   /**
     145             :    * We now have one sorted vector. The remaining vectors need to be sorted according to that
     146             :    * vector.
     147             :    * We'll need a temporary vector to hold values as we map them according to the sorted indices.
     148             :    * After that, we'll swap the vector contents with the sorted vector to get the values
     149             :    * back into the original vector.
     150             :    */
     151             :   // This vector is used as temp storage to sort each of the remaining vectors according to the
     152             :   // first
     153        8733 :   auto vector_length = sorted_indices.size();
     154        8733 :   VectorPostprocessorValue tmp_vector(vector_length);
     155             : 
     156             : #ifndef NDEBUG
     157             :   for (const auto vec_ptr : vec_ptrs)
     158             :     if (vec_ptr->size() != vector_length)
     159             :       mooseError("Vector length mismatch");
     160             : #endif
     161             : 
     162             :   // Sort each of the vectors using the same sorted indices
     163       53165 :   for (auto & vec_ptr : vec_ptrs)
     164             :   {
     165     1517888 :     for (MooseIndex(sorted_indices) j = 0; j < sorted_indices.size(); ++j)
     166     1473456 :       tmp_vector[j] = (*vec_ptr)[sorted_indices[j]];
     167             : 
     168             :     // Swap vector storage with sorted vector
     169       44432 :     vec_ptr->swap(tmp_vector);
     170             :   }
     171        8733 : }
     172             : 
     173             : void
     174         417 : SamplerBase::threadJoin(const SamplerBase & y)
     175             : {
     176         417 :   _x.insert(_x.end(), y._x.begin(), y._x.end());
     177         417 :   _y.insert(_y.end(), y._y.begin(), y._y.end());
     178         417 :   _z.insert(_z.end(), y._z.begin(), y._z.end());
     179             : 
     180         417 :   _id.insert(_id.end(), y._id.begin(), y._id.end());
     181             : 
     182         840 :   for (MooseIndex(_variable_names) i = 0; i < _variable_names.size(); i++)
     183         423 :     _values[i]->insert(_values[i]->end(), y._values[i]->begin(), y._values[i]->end());
     184         417 : }

Generated by: LCOV version 1.14