LCOV - code coverage report
Current view: top level - src/mfem/fespaces - MFEMFESpaceHierarchy.C (source / functions) Hit Total Coverage
Test: idaholab/moose framework: #33390 (250e9c) with base 846a5c Lines: 40 49 81.6 %
Date: 2026-07-31 18:15:22 Functions: 3 3 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 "MFEMFESpaceHierarchy.h"
      13             : #include "MFEMFESpace.h"
      14             : #include "MFEMProblem.h"
      15             : 
      16             : registerMooseObject("MooseApp", MFEMFESpaceHierarchy);
      17             : 
      18             : InputParameters
      19        2148 : MFEMFESpaceHierarchy::validParams()
      20             : {
      21        2148 :   InputParameters params = MFEMObject::validParams();
      22        4296 :   params.registerBase("MFEMFESpaceHierarchy");
      23        4296 :   params.registerSystemAttributeName("MFEMFESpaceHierarchy");
      24        4296 :   params.addClassDescription(
      25             :       "Builds a mfem::ParFiniteElementSpaceHierarchy from a base FESpace by applying a "
      26             :       "sequence of h-refinements ('h') and/or p-refinements (integer order strings).");
      27        8592 :   params.addRequiredParam<MFEMFESpaceName>("fespace",
      28             :                                            "Name of the base (coarsest-level) FESpace object.");
      29        6444 :   params.addRequiredParam<std::vector<std::string>>(
      30             :       "refinements",
      31             :       "Ordered sequence of refinements. Each entry is 'h' for uniform h-refinement or "
      32             :       "an integer string for p-refinement to that polynomial order (must be strictly "
      33             :       "increasing across p-entries).");
      34        2148 :   return params;
      35           0 : }
      36             : 
      37          11 : MFEMFESpaceHierarchy::MFEMFESpaceHierarchy(const InputParameters & parameters)
      38          11 :   : MFEMObject(parameters)
      39             : {
      40          11 :   buildHierarchy();
      41          11 : }
      42             : 
      43             : void
      44          11 : MFEMFESpaceHierarchy::buildHierarchy()
      45             : {
      46          22 :   const auto & fespace_name = getParam<MFEMFESpaceName>("fespace");
      47          22 :   const auto & refinements = getParam<std::vector<std::string>>("refinements");
      48             : 
      49          11 :   if (refinements.empty())
      50           0 :     paramError("refinements", "must not be empty.");
      51             : 
      52             :   const auto & base_fespace_object =
      53          22 :       getMFEMProblem().getMFEMObject<MFEMFESpace>("MFEMFESpace", fespace_name);
      54          11 :   _is_scalar = base_fespace_object.isScalar();
      55             : 
      56             :   // Retrieve the base (coarsest) ParFiniteElementSpace from ProblemData.
      57          11 :   auto base_fespace = base_fespace_object.getFESpace();
      58          11 :   mfem::ParMesh * base_mesh = base_fespace->GetParMesh();
      59          11 :   const int vdim = base_fespace->GetVDim();
      60          11 :   const int ordering = base_fespace->GetOrdering();
      61             : 
      62             :   // Construct the hierarchy with the coarse level.
      63             :   // MOOSE owns the mesh and fespace, so pass ownM=false, ownFES=false.
      64          11 :   _hierarchy = std::make_shared<mfem::ParFiniteElementSpaceHierarchy>(
      65          11 :       base_mesh, base_fespace.get(), /*ownM=*/false, /*ownFES=*/false);
      66             : 
      67          22 :   for (const auto & entry : refinements)
      68             :   {
      69          11 :     if (entry == "h")
      70           0 :       _hierarchy->AddUniformlyRefinedLevel(vdim, ordering);
      71             :     else
      72             :     {
      73             :       // p-refinement: parse the target polynomial order.
      74          11 :       int new_order = 0;
      75             :       try
      76             :       {
      77          11 :         new_order = std::stoi(entry);
      78             :       }
      79           0 :       catch (const std::exception &)
      80             :       {
      81           0 :         paramError("refinements",
      82             :                    "entry '",
      83             :                    entry,
      84             :                    "' is neither 'h' nor a valid integer polynomial order.");
      85           0 :       }
      86             : 
      87          11 :       if (new_order < 1)
      88           0 :         paramError("refinements", "p-refinement order must be >= 1, got ", new_order, ".");
      89             : 
      90             :       // Derive the new FEC name from the current finest level's FEC.
      91          11 :       const std::string current_fec_name = _hierarchy->GetFinestFESpace().FEColl()->Name();
      92          11 :       const auto pos = current_fec_name.rfind("_P");
      93          11 :       if (pos == std::string::npos)
      94           0 :         paramError("refinements",
      95             :                    "cannot infer polynomial order from FEC name '",
      96             :                    current_fec_name,
      97             :                    "' - expected a '_P<N>' suffix.");
      98             : 
      99          11 :       const int current_order = std::stoi(current_fec_name.substr(pos + 2));
     100          11 :       if (new_order <= current_order)
     101           0 :         paramError("refinements",
     102             :                    "p-refinement orders must be strictly increasing; requested order ",
     103             :                    new_order,
     104             :                    " is not greater than the current finest level's order ",
     105             :                    current_order,
     106             :                    ".");
     107             : 
     108             :       const std::string new_fec_name =
     109          11 :           current_fec_name.substr(0, pos + 2) + std::to_string(new_order);
     110             : 
     111             :       auto new_fec = std::unique_ptr<mfem::FiniteElementCollection>(
     112          11 :           mfem::FiniteElementCollection::New(new_fec_name.c_str()));
     113          11 :       _hierarchy->AddOrderRefinedLevel(new_fec.get(), vdim, ordering);
     114          11 :       _level_fecs.push_back(std::move(new_fec));
     115          11 :     }
     116             :   }
     117          11 : }
     118             : #endif

Generated by: LCOV version 1.14