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

121 lines
4.5 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"
#include <fstream>
#include <sstream>
using namespace mfem;
// Tests the use of refined/LOR grid function coefficients.
//
// Given a space fes, and a refined space fes_refined (either vector or scalar
// spaces), projects coeff_1 onto a grid function in fes, and then creates the
// corresponding grid function coefficient (could be scalar, vector, grad, div,
// or curl grid function coefficients). Then, this grid function coefficient is
// projected onto fes_refined, and compared with the result of projecting
// coeff_2 onto fes_refined.
//
// If coeff_1 can be represented exactly in fes, then these two projections
// should be identical.
template <typename GridFunctionCoeffType=GridFunctionCoefficient,
typename CoeffType1, typename CoeffType2>
void TestRefinedGridFunctionCoefficient(
FiniteElementSpace &fes, FiniteElementSpace &fes_refined,
CoeffType1 &coeff_1, CoeffType2 &coeff_2)
{
GridFunction gf(&fes);
gf.ProjectCoefficient(coeff_1);
GridFunctionCoeffType gf_coeff(&gf);
GridFunction gf_refined_1(&fes_refined), gf_refined_2(&fes_refined);
gf_refined_1.ProjectCoefficient(coeff_2);
gf_refined_2.ProjectCoefficient(gf_coeff);
gf_refined_2 -= gf_refined_1;
REQUIRE(gf_refined_2.Normlinf() == MFEM_Approx(0.0));
}
// Forward declarations for functions defined in test_lin_interp.cpp
namespace lin_interp
{
double f2(const Vector & x);
void F2(const Vector & x, Vector & v);
void Grad_f2(const Vector & x, Vector & df);
double curlF2(const Vector & x);
double DivF2(const Vector & x);
double f3(const Vector & x);
void F3(const Vector & x, Vector & v);
void Grad_f3(const Vector & x, Vector & df);
void CurlF3(const Vector & x, Vector & df);
double DivF3(const Vector & x);
}
namespace detail
{
Mesh MakeCartesian(int dim, int nx)
{
if (dim == 1) { return Mesh::MakeCartesian1D(nx); }
else if (dim == 2) { return Mesh::MakeCartesian2D(nx, nx, Element::QUADRILATERAL); }
else { return Mesh::MakeCartesian3D(nx, nx, nx, Element::HEXAHEDRON); }
}
}
TEST_CASE("LOR GridFunction Coefficient", "[LOR][GridFunctionCoefficient]")
{
auto dim = GENERATE(2, 3);
Mesh mesh = ::detail::MakeCartesian(dim, 2);
Mesh mesh_refined = Mesh::MakeRefined(mesh, 3, Quadrature1D::GaussLobatto);
int order = 1;
H1_FECollection fec(order, dim);
FiniteElementSpace fes(&mesh, &fec);
FiniteElementSpace fes_refined(&mesh_refined, &fec);
FiniteElementSpace vec_fes(&mesh, &fec, dim);
FiniteElementSpace vec_fes_refined(&mesh_refined, &fec, dim);
auto f = (dim == 2)? lin_interp::f2 : lin_interp::f3;
auto F = (dim == 2)? lin_interp::F2 : lin_interp::F3;
auto grad = (dim == 2)? lin_interp::Grad_f2 : lin_interp::Grad_f3;
auto div = (dim == 2)? lin_interp::DivF2 : lin_interp::DivF3;
FunctionCoefficient f_coeff(f);
VectorFunctionCoefficient vec_coeff(dim, F);
VectorFunctionCoefficient grad_coeff(dim, grad);
FunctionCoefficient div_coeff(div);
TestRefinedGridFunctionCoefficient<GridFunctionCoefficient>(
fes, fes_refined, f_coeff, f_coeff);
TestRefinedGridFunctionCoefficient<VectorGridFunctionCoefficient>(
vec_fes, vec_fes_refined, vec_coeff, vec_coeff);
TestRefinedGridFunctionCoefficient<DivergenceGridFunctionCoefficient>(
vec_fes, fes_refined, vec_coeff, div_coeff);
TestRefinedGridFunctionCoefficient<GradientGridFunctionCoefficient>(
fes, vec_fes_refined, f_coeff, grad_coeff);
// Curl is treated differently for dim = 2 (where it is a scalar quantity)
// and dim = 3 (where it is a vector quantity)
if (dim == 2)
{
FunctionCoefficient curl_coeff(lin_interp::curlF2);
TestRefinedGridFunctionCoefficient<CurlGridFunctionCoefficient>(
vec_fes, fes_refined, vec_coeff, curl_coeff);
}
else if (dim == 3)
{
VectorFunctionCoefficient curl_coeff(dim, lin_interp::CurlF3);
TestRefinedGridFunctionCoefficient<CurlGridFunctionCoefficient>(
vec_fes, vec_fes_refined, vec_coeff, curl_coeff);
}
}