LCOV - code coverage report
Current view: top level - src/vectorpostprocessors - PointSamplerBase.C (source / functions) Hit Total Coverage
Test: idaholab/moose framework: 2bf808 Lines: 64 66 97.0 %
Date: 2025-07-17 01:28:37 Functions: 6 6 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 "PointSamplerBase.h"
      11             : 
      12             : // MOOSE includes
      13             : #include "MooseMesh.h"
      14             : #include "Assembly.h"
      15             : 
      16             : #include "libmesh/mesh_tools.h"
      17             : 
      18             : InputParameters
      19       14289 : PointSamplerBase::validParams()
      20             : {
      21       14289 :   InputParameters params = GeneralVectorPostprocessor::validParams();
      22             : 
      23       14289 :   params += SamplerBase::validParams();
      24             : 
      25       42867 :   params.addParam<PostprocessorName>(
      26       28578 :       "scaling", 1.0, "The postprocessor that the variables are multiplied with");
      27       42867 :   params.addParam<bool>(
      28             :       "warn_discontinuous_face_values",
      29       28578 :       true,
      30             :       "Whether to return a warning if a discontinuous variable is sampled on a face");
      31             : 
      32       14289 :   return params;
      33           0 : }
      34             : 
      35         731 : PointSamplerBase::PointSamplerBase(const InputParameters & parameters)
      36             :   : GeneralVectorPostprocessor(parameters),
      37             :     SamplerBase(parameters, this, _communicator),
      38        1462 :     _mesh(_subproblem.mesh()),
      39         731 :     _pp_value(getPostprocessorValue("scaling")),
      40         731 :     _warn_discontinuous_face_values(getParam<bool>("warn_discontinuous_face_values")),
      41         731 :     _discontinuous_at_faces(false)
      42             : {
      43         731 : }
      44             : 
      45             : void
      46        3866 : PointSamplerBase::initialize()
      47             : {
      48             :   // Generate new Ids if the point vector has grown (non-negative counting numbers)
      49        3866 :   if (_points.size() > _ids.size())
      50             :   {
      51          11 :     auto old_size = _ids.size();
      52          11 :     _ids.resize(_points.size());
      53          11 :     std::iota(_ids.begin() + old_size, _ids.end(), old_size);
      54             :   }
      55             :   // Otherwise sync the ids array to be smaller if the point vector has been shrunk
      56        3855 :   else if (_points.size() < _ids.size())
      57           0 :     _ids.resize(_points.size());
      58             : 
      59        3866 :   SamplerBase::initialize();
      60             : 
      61             :   // We do this here just in case it's been destroyed and recreated because of mesh adaptivity.
      62        3866 :   _pl = _mesh.getPointLocator();
      63             : 
      64             :   // We may not find a requested point on a distributed mesh, and
      65             :   // that's okay.
      66        3866 :   _pl->enable_out_of_mesh_mode();
      67             : 
      68             :   // Reset the point arrays
      69        3866 :   _found_points.assign(_points.size(), false);
      70             : 
      71        3866 :   _point_values.resize(_points.size());
      72        3866 :   std::for_each(
      73       57666 :       _point_values.begin(), _point_values.end(), [](std::vector<Real> & vec) { vec.clear(); });
      74        3866 : }
      75             : 
      76             : void
      77        3866 : PointSamplerBase::finalize()
      78             : {
      79             :   // Save off for speed
      80        3866 :   const auto pid = processor_id();
      81             : 
      82             :   // Consolidate _found_points across processes to know which points were found
      83        3866 :   auto _global_found_points = _found_points;
      84        3866 :   _comm.sum(_global_found_points);
      85             : 
      86             :   // Keep track of maximum process ids for each point to only add it once
      87        3866 :   std::vector<unsigned int> max_pid(_found_points.size());
      88        3866 :   _comm.maxloc(_found_points, max_pid);
      89             : 
      90       61528 :   for (MooseIndex(_found_points) i = 0; i < _found_points.size(); ++i)
      91             :   {
      92             :     // _global_found_points should contain all 1's at this point (ie every point was found by a
      93             :     // proc)
      94       57666 :     if (pid == 0 && !_global_found_points[i])
      95           4 :       mooseError("In ", name(), ", sample point not found: ", _points[i]);
      96             : 
      97             :     // only process that found the point has the value, and only process with max id should add
      98       57662 :     if (pid == max_pid[i] && _found_points[i])
      99       40345 :       SamplerBase::addSample(_points[i], _ids[i], _point_values[i]);
     100             :   }
     101             : 
     102        3862 :   SamplerBase::finalize();
     103        3862 : }
     104             : 
     105             : const Elem *
     106       42895 : PointSamplerBase::getLocalElemContainingPoint(const Point & p)
     107             : {
     108       42895 :   const Elem * elem = nullptr;
     109       42895 :   if (_discontinuous_at_faces)
     110             :   {
     111             :     libmesh_parallel_only(comm());
     112             : 
     113             :     // Get all possible elements the point may be in
     114        4770 :     std::set<const Elem *> candidate_elements;
     115        4770 :     (*_pl)(p, candidate_elements);
     116             : 
     117             :     // Look at all the element IDs
     118        4770 :     std::set<dof_id_type> candidate_ids;
     119        9477 :     for (auto candidate : candidate_elements)
     120        4707 :       candidate_ids.insert(candidate->id());
     121             : 
     122        4770 :     comm().set_union(candidate_ids);
     123             : 
     124             :     // Domains without candidate elements will not own the lowest ID one
     125        4770 :     if (candidate_elements.size())
     126             :     {
     127             :       // If we know of the minimum, this will be valid. Otherwise, it'll be
     128             :       // nullptr which is fine
     129        4533 :       elem = _mesh.queryElemPtr(*(candidate_ids.begin()));
     130             : 
     131             :       // Print a warning if it's on a face and a variable is discontinuous
     132        4533 :       if (_warn_discontinuous_face_values && candidate_ids.size() > 1)
     133          18 :         mooseDoOnce(mooseWarning("A discontinuous variable is sampled on a face, at ", p));
     134             :     }
     135        4770 :   }
     136             :   else // continuous variables
     137             :   {
     138             :     // Get all possible elements the point may be in
     139             :     // We cant just locate in one element because at the edge between two process domains, it could
     140             :     // be that both domains find the element that is not within their domain
     141       38125 :     std::set<const Elem *> candidate_elements;
     142       38125 :     (*_pl)(p, candidate_elements);
     143             : 
     144             :     // Only keep the one that may be local
     145      103253 :     for (auto candidate : candidate_elements)
     146       65128 :       if (candidate->processor_id() == processor_id())
     147       61630 :         elem = candidate;
     148       38125 :   }
     149             : 
     150       42895 :   if (elem && elem->processor_id() == processor_id())
     151       40836 :     return elem;
     152             : 
     153        2059 :   return nullptr;
     154             : }

Generated by: LCOV version 1.14