LCOV - code coverage report
Current view: top level - src/dirackernels - DiracKernelInfo.C (source / functions) Hit Total Coverage
Test: idaholab/moose framework: #32971 (54bef8) with base c6cf66 Lines: 59 63 93.7 %
Date: 2026-05-29 20:35:17 Functions: 8 9 88.9 %
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 "DiracKernelInfo.h"
      11             : #include "MooseMesh.h"
      12             : #include "MooseEnum.h"
      13             : #include "DiracKernelBase.h"
      14             : #include "MooseBase.h"
      15             : 
      16             : // LibMesh
      17             : #include "libmesh/point_locator_base.h"
      18             : #include "libmesh/elem.h"
      19             : #include "libmesh/enum_point_locator_type.h"
      20             : #include "libmesh/point.h"
      21             : 
      22             : using namespace libMesh;
      23             : 
      24       64619 : DiracKernelInfo::DiracKernelInfo()
      25       64619 :   : _point_locator(), _point_equal_distance_sq(libMesh::TOLERANCE * libMesh::TOLERANCE)
      26             : {
      27       64619 : }
      28             : 
      29       61479 : DiracKernelInfo::~DiracKernelInfo() {}
      30             : 
      31             : void
      32      711980 : DiracKernelInfo::addPoint(const Elem * elem, const Point & p, const Real & value)
      33             : {
      34      711980 :   _elements.insert(elem);
      35             : 
      36      711980 :   std::pair<std::vector<Point>, std::vector<Real>> & multi_point_list = _points[elem];
      37             : 
      38      711980 :   const unsigned int npoint = multi_point_list.first.size();
      39             :   mooseAssert(npoint == multi_point_list.second.size(),
      40             :               "Different sizes for location and point value data");
      41             : 
      42      731540 :   for (unsigned int i = 0; i < npoint; ++i)
      43       63828 :     if (pointsFuzzyEqual(multi_point_list.first[i], p))
      44             :     {
      45             :       // A point at the same (within a tolerance) location as p exists, accumulate its value.
      46       44268 :       multi_point_list.second[i] += value;
      47       44268 :       return;
      48             :     }
      49             : 
      50             :   // No prior point found at this location, add it with its initial value.
      51      667712 :   multi_point_list.first.push_back(p);
      52      667712 :   multi_point_list.second.push_back(value);
      53             : }
      54             : 
      55             : void
      56     3703355 : DiracKernelInfo::clearPoints()
      57             : {
      58     3703355 :   _elements.clear();
      59     3703355 :   _points.clear();
      60     3703355 : }
      61             : 
      62             : bool
      63      315876 : DiracKernelInfo::hasPoint(const Elem * elem, const Point & p)
      64             : {
      65      315876 :   std::vector<Point> & point_list = _points[elem].first;
      66             : 
      67      324576 :   for (const auto & pt : point_list)
      68      324576 :     if (pointsFuzzyEqual(pt, p))
      69      315876 :       return true;
      70             : 
      71             :   // If we haven't found it, we don't have it.
      72           0 :   return false;
      73             : }
      74             : 
      75             : void
      76      155211 : DiracKernelInfo::updatePointLocator(const MooseMesh & mesh)
      77             : {
      78             :   // Note: we could update the PointLocator *every* time we call this
      79             :   // function, but that may introduce an unacceptable overhead in
      80             :   // problems which don't need a PointLocator at all.  This issue will
      81             :   // most likely become a moot point when we eventually add a shared
      82             :   // "CachingPointLocator" to MOOSE.
      83             :   // _point_locator = PointLocatorBase::build(TREE_LOCAL_ELEMENTS, mesh);
      84             : 
      85             :   // Construct the PointLocator object if *any* processors have Dirac
      86             :   // points.  Note: building a PointLocator object is a parallel_only()
      87             :   // function, so this is an all-or-nothing thing.
      88      155211 :   unsigned pl_needs_rebuild = _elements.size();
      89      155211 :   mesh.comm().max(pl_needs_rebuild);
      90             : 
      91      155211 :   if (pl_needs_rebuild)
      92             :   {
      93             :     // PointLocatorBase::build() is a parallel_only function!  So we
      94             :     // can't skip building it just becuase our local _elements is
      95             :     // empty, it might be non-empty on some other processor!
      96        2423 :     _point_locator = PointLocatorBase::build(TREE_LOCAL_ELEMENTS, mesh);
      97             : 
      98             :     // We may be querying for points which are not in the semilocal
      99             :     // part of a distributed mesh.
     100        2423 :     _point_locator->enable_out_of_mesh_mode();
     101             :   }
     102             :   else
     103             :   {
     104             :     // There are no elements with Dirac points, but we have been
     105             :     // requested to update the PointLocator so we have to assume the
     106             :     // old one is invalid.  Therefore we reset it to NULL... however
     107             :     // adding this line causes the code to hang because it triggers
     108             :     // the PointLocator to be rebuilt in a non-parallel-only segment
     109             :     // of the code later... so it's commented out for now even though
     110             :     // it's probably the right behavior.
     111             :     // _point_locator.reset(NULL);
     112             :   }
     113      155211 : }
     114             : 
     115             : const Elem *
     116       39344 : DiracKernelInfo::findPoint(const Point & p,
     117             :                            const MooseMesh & mesh,
     118             :                            const std::set<SubdomainID> & blocks,
     119             :                            const PointNotFoundBehavior point_not_found_behavior,
     120             :                            const MooseBase & consumer)
     121             : {
     122             :   // If the PointLocator has never been created, do so now.  NOTE - WE
     123             :   // CAN'T DO THIS if findPoint() is only called on some processors,
     124             :   // PointLocatorBase::build() is a 'parallel_only' method!
     125       39344 :   if (_point_locator.get() == NULL)
     126             :   {
     127         567 :     _point_locator = PointLocatorBase::build(TREE_LOCAL_ELEMENTS, mesh);
     128         567 :     _point_locator->enable_out_of_mesh_mode();
     129             :   }
     130             : 
     131             :   // Check that the PointLocator is ready to start locating points.
     132             :   // So far I do not have any tests that trip this...
     133       39344 :   if (_point_locator->initialized() == false)
     134           0 :     consumer.mooseError("PointLocator is not initialized!");
     135             : 
     136             :   // Note: The PointLocator object returns NULL when the Point is not
     137             :   // found within the Mesh.  This is not considered to be an error as
     138             :   // far as the DiracKernels are concerned: sometimes the Mesh moves
     139             :   // out from the Dirac point entirely and in that case the Point just
     140             :   // gets "deactivated".
     141       39344 :   const Elem * elem = (*_point_locator)(p, &blocks);
     142             : 
     143             :   // The processors may not agree on which Elem the point is in.  This
     144             :   // can happen if a Dirac point lies on the processor boundary, and
     145             :   // two or more neighboring processors think the point is in the Elem
     146             :   // on *their* side.
     147       39344 :   dof_id_type elem_id = elem ? elem->id() : DofObject::invalid_id;
     148             : 
     149             :   // We are going to let the element with the smallest ID "win", all other
     150             :   // procs will return NULL.
     151       39344 :   dof_id_type min_elem_id = elem_id;
     152       39344 :   mesh.comm().min(min_elem_id);
     153             : 
     154       39344 :   if (min_elem_id == DofObject::invalid_id)
     155             :   {
     156        3169 :     std::stringstream msg;
     157       12676 :     msg << "Point " << p << " not found in block(s) " << Moose::stringify(blocks, ", ") << ".\n";
     158        3169 :     switch (point_not_found_behavior)
     159             :     {
     160           3 :       case PointNotFoundBehavior::ERROR:
     161           3 :         consumer.mooseError(msg.str());
     162             :         break;
     163         298 :       case PointNotFoundBehavior::WARNING:
     164         298 :         mooseDoOnce(consumer.mooseWarning(msg.str() + "This message will not be repeated."));
     165         298 :         break;
     166        2868 :       case PointNotFoundBehavior::IGNORE:
     167        2868 :         break;
     168           0 :       default:
     169           0 :         consumer.mooseError("Internal enum error.");
     170             :     }
     171        3166 :   }
     172             : 
     173             :   // But we notably need the processor which owns elem_id to return it!
     174       39341 :   if (min_elem_id != DofObject::invalid_id)
     175       36175 :     if (const auto min_elem = mesh.queryElemPtr(min_elem_id);
     176       36175 :         min_elem && min_elem->processor_id() == mesh.processor_id())
     177       26406 :       return min_elem;
     178       12935 :   return nullptr;
     179             : }
     180             : 
     181             : bool
     182      388404 : DiracKernelInfo::pointsFuzzyEqual(const Point & a, const Point & b)
     183             : {
     184      388404 :   const Real dist_sq = (a - b).norm_sq();
     185      388404 :   return dist_sq < _point_equal_distance_sq;
     186             : }

Generated by: LCOV version 1.14