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

Generated by: LCOV version 1.14