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