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