https://mooseframework.inl.gov
Loading...
Searching...
No Matches
EigenproblemEquationSystem.C
Go to the documentation of this file.
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
13#include "MFEMEigensolverBase.h"
14#include "libmesh/int_range.h"
15
16namespace Moose::MFEM
17{
18
19void
21{
22 _ess_tdof_lists.resize(1);
23 _ess_markers.resize(1);
24 mfem::ParGridFunction & trial_gf = *(_var_ess_constraints.at(0));
25 trial_gf.Update();
26 trial_gf = _gfuncs->GetRef(_trial_var_names.at(0));
27 _ess_markers.at(0).SetSize(trial_gf.ParFESpace()->GetParMesh()->bdr_attributes.Max(), 0);
28 // Set constrained DoF values on user-declared essential boundaries and collect their markers
29 ApplyEssentialBC(_trial_var_names.at(0), trial_gf, _ess_markers.at(0));
30 trial_gf.FESpace()->GetEssentialTrueDofs(_ess_markers.at(0), _ess_tdof_lists.at(0));
32}
33
34void
36{
37 // Reject nonzero Dirichlet BCs.
38 mfem::ParGridFunction & trial_gf = *(_var_ess_constraints.at(0));
39 mfem::Vector ess_values;
40 trial_gf.GetTrueDofs(ess_values);
41 ess_values.SetSubVectorComplement(_ess_tdof_lists.at(0), 0.0);
42 mfem::real_t max_ess_value =
43 mfem::GlobalLpNorm(mfem::infinity(), ess_values.Normlinf(), trial_gf.ParFESpace()->GetComm());
44 // Roundoff guard. Zero coefficients project to exactly zero.
45 if (max_ess_value > 10 * std::numeric_limits<mfem::real_t>::epsilon())
46 mooseError("Essential boundary conditions on variable '",
47 _trial_var_names.at(0),
48 "' prescribe a nonzero value. "
49 "An eigenproblem is homogeneous so only zero-valued essential boundary conditions "
50 "are meaningful. Set the boundary coefficient to zero.");
51}
52
53void
55{
56 auto & test_var_name = _test_var_names.at(0);
57 auto blf = _blfs.Get(test_var_name);
58
59 blf->EliminateEssentialBCDiag(_ess_markers.at(0), 1.0);
60 blf->Finalize();
61 _jacobian.Reset(blf->ParallelAssemble());
62}
63
64void
66{
67 mfem::ParFiniteElementSpace * fespace = _test_pfespaces.at(0);
68 std::unique_ptr<mfem::ParBilinearForm> m = std::make_unique<mfem::ParBilinearForm>(fespace);
69
70 if (fespace->GetTypicalFE()->GetRangeType() == mfem::FiniteElement::SCALAR)
71 {
72 if (std::holds_alternative<mfem::MatrixCoefficient *>(rhs_coefficient))
73 mooseError("A matrix rhs_coefficient cannot be used with a scalar finite element space.");
74 m->AddDomainIntegrator(
75 new mfem::MassIntegrator(*std::get<mfem::Coefficient *>(rhs_coefficient)));
76 }
77 else
78 m->AddDomainIntegrator(std::visit(
79 [](auto * coef) { return new mfem::VectorFEMassIntegrator(*coef); }, rhs_coefficient));
80
81 m->Assemble();
82 // Shift the eigenvalue corresponding to eliminated dofs to a large value. The BC DoFs on the
83 // stiffness matrix are set to 1 and the mass matrix BC DoFs are set to a small value eps, such
84 // that the eigenvalues associate with these DOFs are ~1/eps.
85 m->EliminateEssentialBCDiag(_ess_markers.at(0), std::numeric_limits<mfem::real_t>::min());
86 m->Finalize();
87 _mass_rhs.Reset(m->ParallelAssemble());
88}
89
90void
92 EigenRHSCoefficient rhs_coefficient)
93{
94 mooseAssert(_test_var_names.size() == 1 && (_test_var_names.size() == _trial_var_names.size()) &&
95 (_test_var_names.at(0) == _trial_var_names.at(0)),
96 "Eigensolve is only supported for single-variable, square systems");
97
98 height = trueX.Size();
99 width = trueX.Size();
102 FormMassMatrix(rhs_coefficient);
103}
104
105void
111
112} // namespace Moose::MFEM
113
114#endif
void mooseError(Args &&... args)
Emit an error message with the given stringified, concatenated args and terminate the application.
Definition MooseError.h:311
virtual void ApplyEssentialBCs() override
Mark external boundaries as essential for eigenproblem BC elimination.
void FormMassMatrix(EigenRHSCoefficient rhs_coefficient)
Form mass matrix for the eigensolver with Dirichlet BC elimination.
virtual void CheckProblemIsHomogeneous()
Verify that the problem is homogeneous (all Dirichlet BCs are zero)
mfem::OperatorHandle _mass_rhs
The mass operator (e.g. the RHS operator for a generalized eigenproblem)
void PrepareEigensolver(EigensolverBase &solver)
Prepare the provided eigensolver.
void BuildEigenproblemJacobian(mfem::BlockVector &trueX, EigenRHSCoefficient rhs_coefficient)
Build eigenproblem system, with essential boundary conditions accounted for.
void FormEigenproblemMatrix()
Form HypreParMatrix matrix operator for the eigensolver with Dirichlet BC elimination.
Base class for eigensolvers.
virtual void SetMassMatrix(mfem::Operator &mass)=0
Sets the mass matrix for the eigensolver in derived classes.
std::vector< mfem::ParFiniteElementSpace * > _test_pfespaces
Pointers to finite element spaces associated with test variables.
virtual void ApplyEssentialBC(const std::string &var_name, mfem::ParGridFunction &trial_gf, mfem::Array< int > &global_ess_markers)
Apply essential BC(s) associated with var_name to set true DoFs of trial_gf and update markers of all...
std::vector< std::string > _test_var_names
Names of all test variables corresponding to linear forms in this equation system.
std::vector< mfem::Array< int > > _ess_tdof_lists
NamedFieldsMap< mfem::ParBilinearForm > _blfs
mfem::OperatorHandle _jacobian
std::vector< std::string > _trial_var_names
Subset of _coupled_var_names of all variables corresponding to gridfunctions with degrees of freedom ...
std::vector< std::unique_ptr< mfem::ParGridFunction > > _var_ess_constraints
Gridfunctions holding essential constraints from Dirichlet BCs.
std::vector< mfem::Array< int > > _ess_markers
Moose::MFEM::GridFunctions * _gfuncs
T * Get(const std::string &field_name) const
Returns a non-owning pointer to the field. This is guaranteed to return a non-null pointer.
T & GetRef(const std::string &field_name) const
Returns a reference to a field.
void SetOperator(mfem::Operator &op)
Updates the solver and any associated weak form context at the operator level.
Utilities for converting between vector(s) of libMesh Points and MFEM Vector(s).
std::variant< mfem::Coefficient *, mfem::MatrixCoefficient * > EigenRHSCoefficient
Scalar or matrix coefficient scaling the eigenproblem right-hand side.