232 lines
6.4 KiB
C++
232 lines
6.4 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 "unit_tests.hpp"
|
|
#include "mfem.hpp"
|
|
#include <fstream>
|
|
#include <iostream>
|
|
|
|
using namespace mfem;
|
|
|
|
namespace pa_kernels
|
|
{
|
|
|
|
TEST_CASE("H1 SumIntegrator", "[SumIntegrator][PartialAssembly]")
|
|
{
|
|
Mesh mesh = Mesh::MakeCartesian3D(1, 1, 1, Element::HEXAHEDRON);
|
|
H1_FECollection fec(2, mesh.Dimension());
|
|
FiniteElementSpace fes(&mesh, &fec);
|
|
|
|
MassIntegrator integ1;
|
|
DiffusionIntegrator integ2;
|
|
|
|
SumIntegrator integ_sum(true);
|
|
integ_sum.AddIntegrator(new MassIntegrator);
|
|
integ_sum.AddIntegrator(new DiffusionIntegrator);
|
|
|
|
const FiniteElement &el = *fes.GetTypicalFE();
|
|
ElementTransformation &T = *mesh.GetTypicalElementTransformation();
|
|
DenseMatrix m1, m_tmp, m2;
|
|
|
|
// AssembleElementMatrix
|
|
integ1.AssembleElementMatrix(el, T, m1);
|
|
integ2.AssembleElementMatrix(el, T, m_tmp);
|
|
m1 += m_tmp;
|
|
integ_sum.AssembleElementMatrix(el, T, m2);
|
|
m1 -= m2;
|
|
REQUIRE(m1.MaxMaxNorm() == MFEM_Approx(0.0));
|
|
|
|
// AssembleElementMatrix2
|
|
integ1.AssembleElementMatrix2(el, el, T, m1);
|
|
integ2.AssembleElementMatrix2(el, el, T, m_tmp);
|
|
m1 += m_tmp;
|
|
integ_sum.AssembleElementMatrix2(el, el, T, m2);
|
|
m1 -= m2;
|
|
REQUIRE(m1.MaxMaxNorm() == MFEM_Approx(0.0));
|
|
|
|
// PA
|
|
integ1.AssemblePA(fes);
|
|
integ2.AssemblePA(fes);
|
|
integ_sum.AssemblePA(fes);
|
|
|
|
int n = fes.GetTrueVSize();
|
|
Vector x(n), y1(n), y2(n);
|
|
Vector diag1(n), diag_tmp(n), diag2(n);
|
|
x.Randomize(1);
|
|
|
|
// AddMultPA
|
|
y1 = 0.0;
|
|
y2 = 0.0;
|
|
integ1.AddMultPA(x, y1);
|
|
integ2.AddMultPA(x, y1);
|
|
integ_sum.AddMultPA(x, y2);
|
|
y1 -= y2;
|
|
REQUIRE(y1.Normlinf() == MFEM_Approx(0.0));
|
|
|
|
// AddMultTransposePA
|
|
y1 = 0.0;
|
|
y2 = 0.0;
|
|
integ1.AddMultTransposePA(x, y1);
|
|
integ2.AddMultTransposePA(x, y1);
|
|
integ_sum.AddMultTransposePA(x, y2);
|
|
y1 -= y2;
|
|
REQUIRE(y1.Normlinf() == MFEM_Approx(0.0));
|
|
|
|
// AssembleDiagonalPA
|
|
diag1 = 0.0;
|
|
diag_tmp = 0.0;
|
|
diag2 = 0.0;
|
|
integ1.AssembleDiagonalPA(diag1);
|
|
integ2.AssembleDiagonalPA(diag_tmp);
|
|
diag1 += diag_tmp;
|
|
integ_sum.AssembleDiagonalPA(diag2);
|
|
diag1 -= diag2;
|
|
REQUIRE(diag1.Normlinf() == MFEM_Approx(0.0));
|
|
|
|
// MF
|
|
#ifdef MFEM_USE_CEED
|
|
if (DeviceCanUseCeed())
|
|
{
|
|
integ1.AssembleMF(fes);
|
|
integ2.AssembleMF(fes);
|
|
integ_sum.AssembleMF(fes);
|
|
|
|
// AddMultMF
|
|
y1 = 0.0;
|
|
y2 = 0.0;
|
|
integ1.AddMultMF(x, y1);
|
|
integ2.AddMultMF(x, y1);
|
|
integ_sum.AddMultMF(x, y2);
|
|
y1 -= y2;
|
|
REQUIRE(y1.Normlinf() == MFEM_Approx(0.0));
|
|
|
|
// AddMultTransposeMF
|
|
y1 = 0.0;
|
|
y2 = 0.0;
|
|
integ1.AddMultTransposeMF(x, y1);
|
|
integ2.AddMultTransposeMF(x, y1);
|
|
integ_sum.AddMultTransposeMF(x, y2);
|
|
y1 -= y2;
|
|
REQUIRE(y1.Normlinf() == MFEM_Approx(0.0));
|
|
|
|
// AssembleDiagonalMF
|
|
integ1.AssembleDiagonalMF(diag1);
|
|
integ2.AssembleDiagonalMF(diag_tmp);
|
|
diag1 += diag_tmp;
|
|
integ_sum.AssembleDiagonalMF(diag2);
|
|
diag1 -= diag2;
|
|
REQUIRE(diag1.Normlinf() == MFEM_Approx(0.0));
|
|
}
|
|
#endif
|
|
}
|
|
|
|
TEST_CASE("DG SumIntegrator", "[SumIntegrator][PartialAssembly]")
|
|
{
|
|
Mesh mesh = Mesh::MakeCartesian3D(2, 1, 1, Element::HEXAHEDRON);
|
|
DG_FECollection fec(2, mesh.Dimension(), BasisType::GaussLobatto);
|
|
FiniteElementSpace fes(&mesh, &fec);
|
|
|
|
Vector v(mesh.Dimension());
|
|
v = 1.0;
|
|
VectorConstantCoefficient v_coeff(v);
|
|
|
|
DGTraceIntegrator integ1(v_coeff, 1.0, 2.0);
|
|
DGTraceIntegrator integ2(v_coeff, 3.0, 4.0);
|
|
|
|
SumIntegrator integ_sum(true);
|
|
integ_sum.AddIntegrator(new DGTraceIntegrator(v_coeff, 1.0, 2.0));
|
|
integ_sum.AddIntegrator(new DGTraceIntegrator(v_coeff, 3.0, 4.0));
|
|
|
|
DenseMatrix m1, m_tmp, m2;
|
|
|
|
// AssembleFaceMatrix
|
|
int nfaces = mesh.GetNumFaces();
|
|
for (int i = 0; i < nfaces; i++)
|
|
{
|
|
FaceElementTransformations *tr = mesh.GetFaceElementTransformations(i);
|
|
const FiniteElement &el0 = *fes.GetFE(tr->Elem1No);
|
|
const FiniteElement &el1 = (tr->Elem2No >= 0) ? *fes.GetFE(tr->Elem2No) : el0;
|
|
integ1.AssembleFaceMatrix(el0, el1, *tr, m1);
|
|
integ2.AssembleFaceMatrix(el0, el1, *tr, m_tmp);
|
|
m1 += m_tmp;
|
|
integ_sum.AssembleFaceMatrix(el0, el1, *tr, m2);
|
|
m1 -= m2;
|
|
REQUIRE(m1.MaxMaxNorm() == MFEM_Approx(0.0));
|
|
}
|
|
|
|
// PA interior
|
|
integ1.AssemblePAInteriorFaces(fes);
|
|
integ2.AssemblePAInteriorFaces(fes);
|
|
integ_sum.AssemblePAInteriorFaces(fes);
|
|
|
|
const FaceRestriction *R_int = fes.GetFaceRestriction(
|
|
ElementDofOrdering::LEXICOGRAPHIC,
|
|
FaceType::Interior);
|
|
|
|
int n_int = R_int->Height();
|
|
Vector x(n_int), y1(n_int), y2(n_int);
|
|
x.Randomize(1);
|
|
|
|
// AddMultPA
|
|
y1 = 0.0;
|
|
y2 = 0.0;
|
|
integ1.AddMultPA(x, y1);
|
|
integ2.AddMultPA(x, y1);
|
|
integ_sum.AddMultPA(x, y2);
|
|
y1 -= y2;
|
|
REQUIRE(y1.Normlinf() == MFEM_Approx(0.0));
|
|
|
|
// AddMultTransposePA
|
|
y1 = 0.0;
|
|
y2 = 0.0;
|
|
integ1.AddMultTransposePA(x, y1);
|
|
integ2.AddMultTransposePA(x, y1);
|
|
integ_sum.AddMultTransposePA(x, y2);
|
|
y1 -= y2;
|
|
REQUIRE(y1.Normlinf() == MFEM_Approx(0.0));
|
|
|
|
// PA boundary
|
|
integ1.AssemblePABoundaryFaces(fes);
|
|
integ2.AssemblePABoundaryFaces(fes);
|
|
integ_sum.AssemblePABoundaryFaces(fes);
|
|
|
|
const FaceRestriction *R_bdr = fes.GetFaceRestriction(
|
|
ElementDofOrdering::LEXICOGRAPHIC,
|
|
FaceType::Boundary,
|
|
L2FaceValues::DoubleValued);
|
|
|
|
int n_bdr = R_bdr->Height();
|
|
x.SetSize(n_bdr);
|
|
y1.SetSize(n_bdr);
|
|
y2.SetSize(n_bdr);
|
|
x.Randomize(1);
|
|
|
|
// AddMultPA
|
|
y1 = 0.0;
|
|
y2 = 0.0;
|
|
integ1.AddMultPA(x, y1);
|
|
integ2.AddMultPA(x, y1);
|
|
integ_sum.AddMultPA(x, y2);
|
|
y1 -= y2;
|
|
REQUIRE(y1.Normlinf() == MFEM_Approx(0.0));
|
|
|
|
// AddMultTransposePA
|
|
y1 = 0.0;
|
|
y2 = 0.0;
|
|
integ1.AddMultTransposePA(x, y1);
|
|
integ2.AddMultTransposePA(x, y1);
|
|
integ_sum.AddMultTransposePA(x, y2);
|
|
y1 -= y2;
|
|
REQUIRE(y1.Normlinf() == MFEM_Approx(0.0));
|
|
}
|
|
|
|
} // namespace pa_kernels
|