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