LCOV - code coverage report
Current view: top level - src/mfem/markers - MFEMRefinementMarker.C (source / functions) Hit Total Coverage
Test: idaholab/moose framework: #32971 (54bef8) with base c6cf66 Lines: 52 60 86.7 %
Date: 2026-05-29 20:35:17 Functions: 5 5 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 "MFEMRefinementMarker.h"
      13             : #include "MFEMProblem.h"
      14             : 
      15             : registerMooseObject("MooseApp", MFEMRefinementMarker);
      16             : 
      17             : InputParameters
      18        2150 : MFEMRefinementMarker::validParams()
      19             : {
      20        2150 :   InputParameters params = MFEMObject::validParams();
      21        4300 :   params.registerBase("Marker");
      22        4300 :   params.registerSystemAttributeName("Marker");
      23             : 
      24        8600 :   params.addRequiredParam<std::string>("indicator", "Estimator to use");
      25       12900 :   params.addRangeCheckedParam<Real>("threshold",
      26             :                                     0,
      27             :                                     "threshold>=0 & threshold<=1",
      28             :                                     "Elements above this percentage of the max error will "
      29             :                                     "be refined. Must be between 0 and 1!");
      30        8600 :   params.addParam<bool>("rebalance", false, "Whether to rebalance the mesh after h-refinement");
      31       10750 :   params.addRangeCheckedParam<unsigned>(
      32        4300 :       "max_h_level", 0, "max_h_level>=0 & max_h_level<=10", "Max number of h-refinement steps");
      33        8600 :   params.addRangeCheckedParam<unsigned>(
      34        4300 :       "max_p_level", 0, "max_p_level>=0 & max_p_level<=10", "Max number of p-refinement steps");
      35        2150 :   return params;
      36           0 : }
      37             : 
      38          26 : MFEMRefinementMarker::MFEMRefinementMarker(const InputParameters & params)
      39             :   : MFEMObject(params),
      40          52 :     _estimator_name(getParam<std::string>("indicator")),
      41          52 :     _error_threshold(getParam<Real>("threshold")),
      42          52 :     _rebalance(getParam<bool>("rebalance")),
      43          52 :     _max_h_level(getParam<unsigned>("max_h_level")),
      44          78 :     _max_p_level(getParam<unsigned>("max_p_level"))
      45             : {
      46          26 : }
      47             : 
      48             : void
      49          26 : MFEMRefinementMarker::initialSetup()
      50             : {
      51             :   // fetch const ref to the estimator
      52          52 :   _estimator = &getMFEMProblem().getMFEMObject<MFEMIndicator>("Indicator", _estimator_name);
      53             : 
      54             :   // Check if p-refinement is supported by the fespace supplied with the variable
      55          26 :   if (_max_p_level and !_estimator->getFESpace().PRefinementSupported())
      56             :   {
      57           0 :     mooseWarning("Specified p-refinement on an unsupported FESpace or geometry. Only H1 and L2 "
      58             :                  "spaces on quad/hex meshes are supported by mfem. Disabling p-refinement.");
      59           0 :     _p_ref_counter = _max_p_level;
      60             :   }
      61             : 
      62             :   // For now, we only allow one level of p-refinement exclusively.
      63          26 :   if ((_max_h_level and _max_p_level) or _max_p_level > 1)
      64             :   {
      65           0 :     mooseWarning("At present, only either a) h-refinement or b) one level of p-refinement is "
      66             :                  "supported. Disabling p-refinement.");
      67           0 :     _p_ref_counter = _max_p_level;
      68             :   }
      69             : 
      70             :   // We do not want to allow rebalancing if p-refinement is enabled, because that mesh-only
      71             :   // operation has no notion of p-refinement and the computational imbalance that may result.
      72          26 :   if (_max_p_level and _rebalance)
      73             :   {
      74           0 :     mooseWarning("Asked for rebalancing as well as p-refinement, which is not supported.");
      75           0 :     _rebalance = false;
      76             :   }
      77             : 
      78          26 :   _threshold_refiner = std::make_unique<mfem::ThresholdRefiner>(*(_estimator->getEstimator()));
      79          26 :   _threshold_refiner->SetTotalErrorFraction(_error_threshold);
      80          26 : }
      81             : 
      82             : bool
      83          52 : MFEMRefinementMarker::pRefine()
      84             : {
      85             :   // Nothing to do if we've reached the max level of refinement
      86          52 :   if (_p_ref_counter >= _max_p_level)
      87          39 :     return false;
      88             : 
      89          13 :   mfem::Array<mfem::Refinement> refinements;
      90          13 :   _threshold_refiner->MarkWithoutRefining(_estimator->getParMesh(), refinements);
      91             : 
      92          13 :   const bool refined = _estimator->getParMesh().ReduceInt(refinements.Size()) != 0LL;
      93             : 
      94          13 :   if (refined)
      95             :   {
      96          13 :     mfem::Array<mfem::pRefinement> prefinements(refinements.Size());
      97         103 :     for (const auto i : make_range(refinements.Size()))
      98          90 :       prefinements[i] = mfem::pRefinement(refinements[i].index, 1);
      99             : 
     100             :     // Perform p-refinement
     101          13 :     _estimator->getFESpace().PRefineAndUpdate(prefinements);
     102             :     // Update all gridfunctions since the same fespace can be shared by multiple gridfunctions
     103          13 :     getMFEMProblem().updateGridFunctions();
     104          13 :   }
     105             : 
     106             :   // Return whether we actually refined and increase the counter if we did
     107          13 :   return refined && ++_p_ref_counter;
     108          13 : }
     109             : 
     110             : bool
     111          39 : MFEMRefinementMarker::hRefine()
     112             : {
     113             :   // Nothing to do if we've reached the max level of refinement
     114          39 :   if (_h_ref_counter >= _max_h_level)
     115          26 :     return false;
     116             : 
     117             :   // Perform h-refinement
     118          13 :   _threshold_refiner->Apply(_estimator->getParMesh());
     119             : 
     120          13 :   const bool refined = !_threshold_refiner->Stop();
     121             : 
     122          13 :   if (refined)
     123             :   {
     124             :     // Update all fespaces since the same mesh can be shared by multiple fespaces
     125          13 :     getMFEMProblem().updateFESpaces();
     126             :     // Update all gridfunctions now we have updated all fespaces
     127          13 :     getMFEMProblem().updateGridFunctions();
     128          13 :     if (_rebalance)
     129           0 :       getMFEMProblem().rebalanceMesh(_estimator->getParMesh());
     130             :   }
     131             : 
     132             :   // Return whether we actually refined and increase the counter if we did
     133          13 :   return refined && ++_h_ref_counter;
     134             : }
     135             : 
     136             : #endif

Generated by: LCOV version 1.14