Program Listing for File mfem.hpp
↰ Return to documentation for file (src/pcms/field/function_space/mfem.hpp)
#ifndef PCMS_MFEM_FIELD_FACTORY_HPP
#define PCMS_MFEM_FIELD_FACTORY_HPP
#include "pcms/field/coordinate_system.hpp"
#include "pcms/field/data/mfem.hpp"
#include "pcms/field/field_factory.h"
#include "pcms/field/layout/mfem.hpp"
#include "pcms/utility/assert.h"
#include "pcms/utility/common.h"
#include <mfem.hpp>
#include <memory>
#include <string>
#include <variant>
namespace pcms
{
// Communication-only field factory for an MFEM order-1 H1 (vertex) scalar
// field. The produced field's data is bound to the live mfem::ParGridFunction,
// so coupled get/set operate on the solver's state. Point evaluation is not
// supported (mirrors XGCFieldFactory).
// Lifetime: the factory and any Field it produces must not outlive
// pmesh / pfes / gf.
class MFEMFieldFactory : public FieldFactory
{
public:
MFEMFieldFactory(mfem::ParMesh& pmesh, mfem::ParFiniteElementSpace& pfes,
mfem::ParGridFunction& gf,
std::shared_ptr<const CoordinateSystem> coordinate_system,
std::string layout_name = "")
: layout_(std::make_shared<MFEMLayout>(pmesh, pfes,
std::move(coordinate_system))),
pfes_(pfes),
gf_(gf)
{
layout_->SetName(std::move(layout_name));
}
void SetLayoutName(std::string name) const
{
layout_->SetName(std::move(name));
}
[[nodiscard]] std::shared_ptr<const FieldLayout> GetLayout()
const noexcept override
{
return layout_;
}
[[nodiscard]] std::shared_ptr<const MFEMLayout> GetMFEMLayout() const noexcept
{
return layout_;
}
protected:
[[nodiscard]] FieldVariant CreateFieldImpl(Type storage_type,
ValueBasis basis) const override
{
if (storage_type != Type::Real) {
throw pcms_error("MFEM adapter only supports Real (double) fields");
}
return WrapField<Real>(layout_, std::make_unique<MFEMVertexFieldData>(
pfes_, gf_, std::move(basis)));
}
[[nodiscard]] FieldVariant CreateFieldImpl(
FieldDataVariant data) const override
{
auto* real = std::get_if<std::unique_ptr<FieldData<Real>>>(&data);
if (real == nullptr || *real == nullptr ||
dynamic_cast<const MFEMVertexFieldData*>(real->get()) == nullptr) {
throw pcms_error(
"MFEMFieldFactory::CreateField: requires MFEMVertexFieldData");
}
if ((*real)->GetDOFAccess()->GetOwnedValues().size() !=
detail::ExpectedFlatFieldDataSize(*layout_)) {
throw pcms_error("MFEMFieldFactory::CreateField: field data size does "
"not match layout");
}
return WrapField<Real>(layout_, std::move(*real));
}
private:
std::shared_ptr<MFEMLayout> layout_;
mfem::ParFiniteElementSpace& pfes_;
mfem::ParGridFunction& gf_;
};
} // namespace pcms
#endif // PCMS_MFEM_FIELD_FACTORY_HPP