diff --git a/framework/include/mfem/ics/MFEMScalarIC.h b/framework/include/mfem/ics/MFEMScalarIC.h new file mode 100644 index 000000000000..6a135a175b96 --- /dev/null +++ b/framework/include/mfem/ics/MFEMScalarIC.h @@ -0,0 +1,15 @@ +#ifdef MFEM_ENABLED + +#pragma once + +#include "MFEMGeneralUserObject.h" + +class MFEMScalarIC : public MFEMGeneralUserObject +{ +public: + static InputParameters validParams(); + MFEMScalarIC(const InputParameters & params); + virtual void execute() override; +}; + +#endif diff --git a/framework/include/mfem/materials/MFEMMaterial.h b/framework/include/mfem/materials/MFEMMaterial.h index a579b7bf3799..260d2e1d0a29 100644 --- a/framework/include/mfem/materials/MFEMMaterial.h +++ b/framework/include/mfem/materials/MFEMMaterial.h @@ -12,7 +12,6 @@ class MFEMMaterial : public MFEMGeneralUserObject { public: static InputParameters validParams(); - static std::vector subdomainsToStrings(std::vector blocks); static libMesh::Point pointFromMFEMVector(const mfem::Vector & vec); MFEMMaterial(const InputParameters & parameters); @@ -21,6 +20,8 @@ class MFEMMaterial : public MFEMGeneralUserObject const std::vector & getBlocks() const { return _block_ids; } protected: + std::vector subdomainsToStrings(std::vector blocks); + std::vector _block_ids; platypus::PropertyManager & _properties; }; diff --git a/framework/include/mfem/problem/MFEMProblem.h b/framework/include/mfem/problem/MFEMProblem.h index 875ca587e339..bdacf276530b 100644 --- a/framework/include/mfem/problem/MFEMProblem.h +++ b/framework/include/mfem/problem/MFEMProblem.h @@ -115,6 +115,10 @@ class MFEMProblem : public ExternalProblem const std::string & name, InputParameters & parameters) override; + void addInitialCondition(const std::string & ic_name, + const std::string & name, + InputParameters & parameters) override; + /** * Method called in AddMFEMPreconditionerAction which will create the solver. */ @@ -196,6 +200,11 @@ class MFEMProblem : public ExternalProblem std::optional> getMeshDisplacementGridFunction(); + /** + * @returns a shared pointer to an MFEM parallel grid function + */ + std::shared_ptr getGridFunction(const std::string & name); + protected: /** * Template method for adding kernels. We can only add kernels using equation system problem diff --git a/framework/src/mfem/ics/MFEMScalarIC.C b/framework/src/mfem/ics/MFEMScalarIC.C new file mode 100644 index 000000000000..82ef294bcb64 --- /dev/null +++ b/framework/src/mfem/ics/MFEMScalarIC.C @@ -0,0 +1,36 @@ +#ifdef MFEM_ENABLED + +#include "MFEMScalarIC.h" +#include "MFEMProblem.h" +#include +#include + +registerMooseObject("MooseApp", MFEMScalarIC); + +InputParameters +MFEMScalarIC::validParams() +{ + auto params = MFEMGeneralUserObject::validParams(); + params.addRequiredParam("variable", + "The variable to apply the initial condition for"); + params.addRequiredParam("coefficient", "The scalar coefficient"); + params.registerBase("InitialCondition"); + // We cannot generally execute this at construction time since the coefficient may be based on a + // MOOSE function which is not itself setup until its initialSetup is called. UserObject initial + // execution occurs after function initialSetup + params.set("execute_on") = {EXEC_INITIAL}; + params.suppressParameter("execute_on"); + return params; +} + +MFEMScalarIC::MFEMScalarIC(const InputParameters & params) : MFEMGeneralUserObject(params) {} + +void +MFEMScalarIC::execute() +{ + auto coeff = getMFEMProblem().getScalarFunctionCoefficient(getParam("coefficient")); + auto grid_function = getMFEMProblem().getGridFunction(getParam("variable")); + grid_function->ProjectCoefficient(*coeff); +} + +#endif diff --git a/framework/src/mfem/materials/MFEMMaterial.C b/framework/src/mfem/materials/MFEMMaterial.C index 38a41a0096ea..67420fbdc73e 100644 --- a/framework/src/mfem/materials/MFEMMaterial.C +++ b/framework/src/mfem/materials/MFEMMaterial.C @@ -27,13 +27,31 @@ std::vector MFEMMaterial::subdomainsToStrings(std::vector blocks) { std::vector result(blocks.size()); + auto & mesh = getMFEMProblem().mesh().getMFEMParMesh(); // FIXME: Is there really no better way to do this conversion? It doesn't seem like it should be // necessary to do the various copies etc. for this. - std::transform(blocks.begin(), - blocks.end(), - result.begin(), - // FIXME: How do I pass the string constructor directly? - [](const SubdomainName & x) -> std::string { return std::string(x); }); + std::transform( + blocks.begin(), + blocks.end(), + result.begin(), + // FIXME: How do I pass the string constructor directly? + [this, &mesh](const SubdomainName & x) -> std::string + { + try + { + // Is this a block ID? + std::stoi(x); + return std::string(x); + } + catch (...) + { + // It was not + auto & block_ids = mesh.attribute_sets.GetAttributeSet(x); + if (block_ids.Size() != 1) + this->mooseError("There should be a 1-to-1 correspondence between block name and block ID"); + return std::to_string(block_ids[0]); + } + }); return result; } diff --git a/framework/src/mfem/problem/MFEMProblem.C b/framework/src/mfem/problem/MFEMProblem.C index 090ca40c0825..0b69074f3c19 100644 --- a/framework/src/mfem/problem/MFEMProblem.C +++ b/framework/src/mfem/problem/MFEMProblem.C @@ -1,6 +1,7 @@ #ifdef MFEM_ENABLED #include "MFEMProblem.h" +#include "MFEMScalarIC.h" #include #include @@ -383,4 +384,19 @@ MFEMProblem::mesh() return (MFEMMesh &)_mesh; } +std::shared_ptr +MFEMProblem::getGridFunction(const std::string & name) +{ + return getUserObject(name).getGridFunction(); +} + +void +MFEMProblem::addInitialCondition(const std::string & ic_name, + const std::string & name, + InputParameters & parameters) +{ + FEProblemBase::addUserObject(ic_name, name, parameters); + getUserObject(name); // error check +} + #endif diff --git a/test/tests/mfem/kernels/diffusion.i b/test/tests/mfem/kernels/diffusion.i index 607be54273cc..4a07cd30f6c3 100644 --- a/test/tests/mfem/kernels/diffusion.i +++ b/test/tests/mfem/kernels/diffusion.i @@ -23,6 +23,21 @@ [] [] +[ICs] + [diffused_ic] + type = MFEMScalarIC + coefficient = one + variable = diffused + [] +[] + +[Functions] + [one] + type = ParsedFunction + expression = 1.0 + [] +[] + [BCs] [bottom] type = MFEMScalarDirichletBC @@ -43,6 +58,7 @@ type = MFEMGenericConstantMaterial prop_names = diffusivity prop_values = 1.0 + block = 'the_domain' [] [] diff --git a/test/tests/mfem/kernels/gold/mug.e b/test/tests/mfem/kernels/gold/mug.e index 99190251d9ec..af9c3ac30ff0 100644 Binary files a/test/tests/mfem/kernels/gold/mug.e and b/test/tests/mfem/kernels/gold/mug.e differ diff --git a/unit/data/mug.e b/unit/data/mug.e index 99190251d9ec..af9c3ac30ff0 100644 Binary files a/unit/data/mug.e and b/unit/data/mug.e differ