LCOV - code coverage report
Current view: top level - src/mfem/vectorpostprocessors - MFEMValueSamplerBase.C (source / functions) Hit Total Coverage
Test: idaholab/moose framework: #33416 (b10b36) with base 9fbd27 Lines: 81 83 97.6 %
Date: 2026-07-23 16:15:30 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             : #ifdef MOOSE_MFEM_ENABLED
      11             : 
      12             : #include "MFEMValueSamplerBase.h"
      13             : 
      14             : #include "MFEMProblem.h"
      15             : #include "MFEMVectorUtils.h"
      16             : #include "MooseError.h"
      17             : 
      18             : #include "mfem/fem/fespace.hpp"
      19             : 
      20             : namespace
      21             : {
      22             : /** Enum for values returned by gslib for point location relative to mesh
      23             :  */
      24             : enum class GSLibLocationCode : unsigned int
      25             : {
      26             :   INTERNAL = 0,
      27             :   BORDER = 1,
      28             :   NOT_FOUND = 2,
      29             : };
      30             : 
      31             : void
      32         972 : MFEMVectorToPostprocessorPoints(
      33             :     const mfem::Vector & mfem_points,
      34             :     std::vector<std::reference_wrapper<VectorPostprocessorValue>> & points,
      35             :     const unsigned int num_dims,
      36             :     const mfem::Ordering::Type ordering)
      37             : {
      38         972 :   const unsigned int num_points = mfem_points.Size() / num_dims;
      39        5116 :   for (unsigned int i_point = 0; i_point < num_points; i_point++)
      40             :   {
      41       12930 :     for (unsigned int i_dim = 0; i_dim < num_dims; i_dim++)
      42             :     {
      43        8786 :       const size_t idx = Moose::MFEM::MFEMIndex(i_dim, i_point, num_dims, num_points, ordering);
      44             : 
      45        8786 :       points[i_dim].get()[i_point] = mfem_points(idx);
      46             :     }
      47             :   }
      48         972 : }
      49             : 
      50             : mfem::FindPointsGSLIB::AvgType
      51         366 : getAvgType(const MooseEnum & avg_type)
      52             : {
      53         366 :   if (avg_type == "NONE")
      54          13 :     return mfem::FindPointsGSLIB::AvgType::NONE;
      55         353 :   else if (avg_type == "ARITHMETIC")
      56         340 :     return mfem::FindPointsGSLIB::AvgType::ARITHMETIC;
      57          13 :   else if (avg_type == "HARMONIC")
      58          13 :     return mfem::FindPointsGSLIB::AvgType::HARMONIC;
      59             :   else
      60           0 :     mooseError(
      61             :         "Unknown average type: ",
      62             :         avg_type,
      63             :         ", this is an internal MOOSE error, new enum variants must be handled by this function.");
      64             : }
      65             : }
      66             : 
      67             : InputParameters
      68        4978 : MFEMValueSamplerBase::validParams()
      69             : {
      70        4978 :   InputParameters params = MFEMVectorPostprocessor::validParams();
      71             : 
      72       19912 :   MFEMExecutedObject::addRequiredDependencyParam<VariableName>(
      73             :       params, "variable", "The names of the variables that this VectorPostprocessor operates on");
      74       19912 :   MooseEnum ordering("NODES VDIM", "VDIM", false);
      75       19912 :   params.addParam<MooseEnum>(
      76             :       "point_ordering", ordering, "Ordering style to use for point vector DoFs.");
      77       19912 :   MooseEnum avg_type("NONE ARITHMETIC HARMONIC", "ARITHMETIC", false);
      78       19912 :   params.addParam<MooseEnum>("average_type",
      79             :                              avg_type,
      80             :                              "Average type used when sampling L2 functions at element boundaries.");
      81        9956 :   params.addParam<double>("mesh_boundary_tolerance",
      82        9956 :                           1e-8,
      83             :                           "Distance from point to mesh boundary below which the point is "
      84             :                           "considered to be on the boundary rather than outside the mesh.");
      85             : 
      86        9956 :   return params;
      87        4978 : }
      88             : 
      89         366 : MFEMValueSamplerBase::MFEMValueSamplerBase(const InputParameters & parameters,
      90         366 :                                            const std::vector<Point> & points)
      91             :   : MFEMVectorPostprocessor(parameters),
      92         366 :     _var_name(getParam<VariableName>("variable")),
      93         366 :     _var(*getMFEMProblem().getGridFunction(_var_name)),
      94         366 :     _mesh(const_cast<mfem::ParMesh &>(getMFEMProblem().getMFEMVariableMesh(_var_name))),
      95         366 :     _finder(this->comm().get()),
      96         732 :     _points_ordering(getParam<MooseEnum>("point_ordering") == "NODES" ? mfem::Ordering::byNODES
      97             :                                                                       : mfem::Ordering::byVDIM),
      98         366 :     _points(
      99         366 :         Moose::MFEM::libMeshPointsToMFEMVector(points, _mesh.SpaceDimension(), _points_ordering)),
     100         732 :     _interp_vals(points.size())
     101             : {
     102         366 :   if (getMFEMProblem().mesh().shouldDisplace())
     103           0 :     mooseError("MFEMValueSamplerBase does not yet support problems with displacement.");
     104             : 
     105         732 :   _finder.SetL2AvgType(getAvgType(getParam<MooseEnum>("average_type")));
     106         732 :   _finder.SetDistanceToleranceForPointsFoundOnBoundary(getParam<double>("mesh_boundary_tolerance"));
     107             : 
     108             :   // set up points vector
     109         366 :   _mesh.EnsureNodes();
     110         366 :   _finder.Setup(_mesh);
     111         366 :   _finder.FindPoints(_points, _points_ordering);
     112             : 
     113             :   bool fe_boundary_discontinuous =
     114         366 :       _var.FESpace()->FEColl()->GetContType() == mfem::FiniteElementCollection::DISCONTINUOUS;
     115             : 
     116             :   // check all points were found
     117         366 :   mfem::Array<unsigned int> point_codes = _finder.GetCode();
     118        3850 :   for (size_t i = 0; i < points.size(); i++)
     119             :   {
     120        3490 :     switch (GSLibLocationCode(point_codes[i]))
     121             :     {
     122        2711 :       case GSLibLocationCode::INTERNAL:
     123        2711 :         break;
     124         775 :       case GSLibLocationCode::BORDER:
     125         775 :         if (fe_boundary_discontinuous)
     126         233 :           mooseWarning("MFEMValueSamplerBase found a point on an element boundary but "
     127             :                        "the FE space is discontinuous at boundaries: ",
     128         233 :                        points[i],
     129             :                        ".");
     130         773 :         break;
     131           4 :       default:
     132           4 :         mooseError("MFEMValueSamplerBase could not find point at ", points[i], ".");
     133             :         break;
     134             :     }
     135             :   }
     136             : 
     137             :   // declare points vectors for outputting
     138         360 :   const auto mesh_dim = _mesh.SpaceDimension();
     139        1196 :   for (int i = 0; i < mesh_dim; i++)
     140             :   {
     141             :     std::reference_wrapper<VectorPostprocessorValue> declared_dim =
     142         836 :         this->declareVector("x_" + std::to_string(i));
     143         836 :     declared_dim.get().resize(points.size());
     144         836 :     _declared_points.push_back(declared_dim);
     145             :   }
     146             : 
     147             :   // declare value vectors for outputting
     148         360 :   const auto val_dim = _var.VectorDim();
     149         784 :   for (int i = 0; i < val_dim; i++)
     150             :   {
     151             :     std::reference_wrapper<VectorPostprocessorValue> declared_dim =
     152         424 :         this->declareVector(_var_name + "_" + std::to_string(i));
     153         424 :     declared_dim.get().resize(points.size());
     154         424 :     _declared_vals.push_back(declared_dim);
     155             :   }
     156         360 : }
     157             : 
     158             : void
     159         972 : MFEMValueSamplerBase::execute()
     160             : {
     161         972 :   _finder.Interpolate(_var, _interp_vals);
     162         972 : }
     163             : 
     164             : void
     165         972 : MFEMValueSamplerBase::finalize()
     166             : {
     167         972 :   _interp_vals.HostReadWrite();
     168         972 :   _points.HostReadWrite();
     169             : 
     170         972 :   const auto mesh_dim = _mesh.SpaceDimension();
     171         972 :   MFEMVectorToPostprocessorPoints(_points, _declared_points, mesh_dim, _points_ordering);
     172         972 :   const auto val_dims = _var.VectorDim();
     173         972 :   const auto num_points = _declared_points[0].get().size();
     174         972 :   const auto val_fespace_ordering = _var.FESpace()->GetOrdering();
     175        2008 :   for (int i_dim = 0; i_dim < val_dims; i_dim++)
     176             :   {
     177        5638 :     for (size_t i_point = 0; i_point < num_points; i_point++)
     178             :     {
     179             :       const auto mfem_idx =
     180        4602 :           Moose::MFEM::MFEMIndex(i_dim, i_point, val_dims, num_points, val_fespace_ordering);
     181        4602 :       _declared_vals[i_dim].get()[i_point] = _interp_vals[mfem_idx];
     182             :     }
     183             :   }
     184         972 : }
     185             : 
     186             : #endif // MOOSE_MFEM_ENABLED

Generated by: LCOV version 1.14