Files
mfem/tests/unit/fem/test_nonlinearform.cpp
T

99 lines
3.1 KiB
C++

// Copyright (c) 2010-2025, Lawrence Livermore National Security, LLC. Produced
// at the Lawrence Livermore National Laboratory. All Rights reserved. See files
// LICENSE and NOTICE for details. LLNL-CODE-806117.
//
// This file is part of the MFEM library. For more information and source code
// availability visit https://mfem.org.
//
// MFEM is free software; you can redistribute it and/or modify it under the
// terms of the BSD-3 license. We welcome feedback and contributions, see file
// CONTRIBUTING.md for details.
#include "mfem.hpp"
#include "unit_tests.hpp"
using namespace mfem;
TEST_CASE("NonlinearForm Boundary Integrator", "[NonlinearForm]")
{
// See problem description in ex27.
Mesh mesh("./data/holes.mesh", 1, 1);
H1_FECollection fec(1, mesh.Dimension());
FiniteElementSpace fespace(&mesh, &fec);
Array<int> nbc_bdr(mesh.bdr_attributes.Max());
Array<int> rbc_bdr(mesh.bdr_attributes.Max());
Array<int> dbc_bdr(mesh.bdr_attributes.Max());
nbc_bdr = 0; nbc_bdr[0] = 1;
rbc_bdr = 0; rbc_bdr[1] = 1;
dbc_bdr = 0; dbc_bdr[2] = 1;
Array<int> ess_tdof_list(0);
fespace.GetEssentialTrueDofs(dbc_bdr, ess_tdof_list);
// See defaults in ex27.
ConstantCoefficient matCoef(1.0);
ConstantCoefficient dbcCoef(0.0);
ConstantCoefficient nbcCoef(1.0);
ConstantCoefficient rbcACoef(1.0);
ConstantCoefficient rbcBCoef(1.0);
ProductCoefficient m_nbcCoef(matCoef, nbcCoef);
ProductCoefficient m_rbcACoef(matCoef, rbcACoef);
ProductCoefficient m_rbcBCoef(matCoef, rbcBCoef);
GridFunction u1(&fespace), u2(&fespace);
u1 = 0.0;
u2 = 0.0;
u1.ProjectBdrCoefficient(dbcCoef, dbc_bdr);
u2.ProjectBdrCoefficient(dbcCoef, dbc_bdr);
LinearForm b(&fespace);
b.AddBoundaryIntegrator(new BoundaryLFIntegrator(m_nbcCoef), nbc_bdr);
b.AddBoundaryIntegrator(new BoundaryLFIntegrator(m_rbcBCoef), rbc_bdr);
b.Assemble();
// Solve as a linear problem.
{
BilinearForm a(&fespace);
a.AddDomainIntegrator(new DiffusionIntegrator(matCoef));
a.AddBoundaryIntegrator(new MassIntegrator(m_rbcACoef), rbc_bdr);
a.Assemble();
OperatorPtr A;
Vector B, X;
a.FormLinearSystem(ess_tdof_list, u1, b, A, X, B);
GSSmoother M((SparseMatrix&)(*A));
PCG(*A, M, B, X, 1, 500, 1e-12, 0.0);
a.RecoverFEMSolution(X, b, u1);
}
// Solve as a nonlinear problem.
{
NonlinearForm a_nf(&fespace);
a_nf.AddDomainIntegrator(new DiffusionIntegrator(matCoef));
a_nf.AddBoundaryIntegrator(new MassIntegrator(m_rbcACoef), rbc_bdr);
a_nf.SetEssentialTrueDofs(ess_tdof_list);
IterativeSolver::PrintLevel print;
print.Iterations();
CGSolver cg;
cg.SetPrintLevel(print);
cg.SetMaxIter(100);
cg.SetRelTol(1e-12); cg.SetAbsTol(0.0);
NewtonSolver newton;
newton.iterative_mode = false;
newton.SetSolver(cg);
newton.SetOperator(a_nf);
newton.SetPrintLevel(print);
newton.SetRelTol(1e-14); newton.SetAbsTol(0.0);
newton.SetMaxIter(1);
newton.Mult(b, u2);
}
u2 -= u1;
REQUIRE(u2.Norml2() == MFEM_Approx(0.0, 1e-5));
}