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

666 lines
19 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;
namespace eigs
{
static real_t a_ = M_PI;
static real_t b_ = M_PI / sqrt(2.0);
static real_t c_ = M_PI / 2.0;
enum MeshType
{
SEGMENT = 0,
QUADRILATERAL = 1,
TRIANGLE2A = 2,
TRIANGLE2B = 3,
TRIANGLE2C = 4,
TRIANGLE4 = 5,
MIXED2D = 6,
HEXAHEDRON = 7,
HEXAHEDRON2A = 8,
HEXAHEDRON2B = 9,
HEXAHEDRON2C = 10,
HEXAHEDRON2D = 11,
WEDGE2 = 12,
TETRAHEDRA = 13,
WEDGE4 = 14,
MIXED3D6 = 15,
MIXED3D8 = 16
};
Mesh * GetMesh(MeshType type);
int eigs[21] =
{
1,4,9,16,25,36,49,
3,6,9,11,12,17,18,
7,10,13,15,16,19,21
};
#ifdef MFEM_USE_LAPACK
TEST_CASE("Laplacian Eigenvalues",
"[H1_FECollection]"
"[GridFunction]"
"[BilinearForm]")
{
int order = 3;
for (int mt = (int)MeshType::SEGMENT;
mt <= (int)MeshType::MIXED3D8; mt++)
{
Mesh *mesh = GetMesh((MeshType)mt);
int dim = mesh->Dimension();
if (dim < 3 ||
mt == MeshType::HEXAHEDRON ||
mt == MeshType::WEDGE2 ||
mt == MeshType::TETRAHEDRA ||
mt == MeshType::WEDGE4 ||
mt == MeshType::MIXED3D8 )
{
mesh->UniformRefinement();
}
H1_FECollection fec(order, dim);
FiniteElementSpace fespace(mesh, &fec);
int size = fespace.GetTrueVSize();
CAPTURE(mt, size);
Array<int> ess_bdr;
if (mesh->bdr_attributes.Size())
{
ess_bdr.SetSize(mesh->bdr_attributes.Max());
ess_bdr = 1;
}
Array<int> ess_bdr_tdofs;
fespace.GetEssentialTrueDofs(ess_bdr, ess_bdr_tdofs);
int bsize = ess_bdr_tdofs.Size();
BilinearForm a(&fespace);
a.AddDomainIntegrator(new DiffusionIntegrator);
a.Assemble();
a.EliminateEssentialBCDiag(ess_bdr, 1.0);
a.Finalize();
BilinearForm m(&fespace);
m.AddDomainIntegrator(new MassIntegrator);
m.Assemble();
// shift the eigenvalue corresponding to eliminated dofs to a large value
m.EliminateEssentialBCDiag(ess_bdr, std::numeric_limits<real_t>::min());
m.Finalize();
DenseMatrix Ad(size);
DenseMatrix Md(size);
DenseMatrix vd(size);
Ad = 0.0;
Md = 0.0;
Vector one(size);
Vector done(size);
one = 0.0;
for (int i=0; i<size; i++)
{
one[i] = 1.0;
a.Mult(one, done);
for (int j=0; j<size; j++)
{
Ad(j, i) = done[j];
}
m.Mult(one, done);
for (int j=0; j<size; j++)
{
Md(j, i) = done[j];
}
one[i] = 0.0;
}
for (int i=0; i<bsize; i++)
{
int ei = ess_bdr_tdofs[i];
Ad(ei,ei) = 0.0;
Md(ei,ei) = 1.0;
}
int nev = dim;
Vector deigs(size);
Ad.Eigenvalues(Md, deigs, vd);
Array<int> exact_eigs(&eigs[7 * (dim - 1)], 7);
real_t max_err = 0.0;
for (int i=bsize; i<std::min(size,bsize+nev); i++)
{
real_t lc = deigs[i];
real_t le = exact_eigs[i-bsize];
real_t err = 100.0 * fabs(le - lc) / le;
max_err = std::max(max_err, err);
REQUIRE(err < 5.0);
}
CAPTURE(mt, max_err);
delete mesh;
}
}
#endif // MFEM_USE_LAPACK
#ifdef MFEM_USE_MPI
#
TEST_CASE("Laplacian Eigenvalues in Parallel",
"[H1_FECollection]"
"[GridFunction]"
"[BilinearForm]"
"[Parallel]")
{
int num_procs;
MPI_Comm_size(MPI_COMM_WORLD, &num_procs);
int my_rank;
MPI_Comm_rank(MPI_COMM_WORLD, &my_rank);
int order = 3;
int seed = 75;
for (int mt = (int)MeshType::SEGMENT;
mt <= (int)MeshType::MIXED3D8; mt++)
{
Mesh *mesh = GetMesh((MeshType)mt);
int dim = mesh->Dimension();
if (dim < 3 ||
mt == MeshType::HEXAHEDRON ||
mt == MeshType::WEDGE2 ||
mt == MeshType::TETRAHEDRA ||
mt == MeshType::WEDGE4 ||
mt == MeshType::MIXED3D8 )
{
mesh->UniformRefinement();
}
while (mesh->GetNE() < num_procs)
{
mesh->UniformRefinement();
}
ParMesh pmesh(MPI_COMM_WORLD, *mesh);
delete mesh;
H1_FECollection fec(order, dim);
ParFiniteElementSpace fespace(&pmesh, &fec);
HYPRE_BigInt size = fespace.GlobalTrueVSize();
CAPTURE(mt, size);
Array<int> ess_bdr;
if (pmesh.bdr_attributes.Size())
{
ess_bdr.SetSize(pmesh.bdr_attributes.Max());
ess_bdr = 1;
}
Array<int> ess_bdr_tdofs;
fespace.GetEssentialTrueDofs(ess_bdr, ess_bdr_tdofs);
ParBilinearForm a(&fespace);
a.AddDomainIntegrator(new DiffusionIntegrator);
a.Assemble();
a.EliminateEssentialBCDiag(ess_bdr, 1.0);
a.Finalize();
ParBilinearForm m(&fespace);
m.AddDomainIntegrator(new MassIntegrator);
m.Assemble();
// shift the eigenvalue corresponding to eliminated dofs to a large value
m.EliminateEssentialBCDiag(ess_bdr, std::numeric_limits<real_t>::min());
m.Finalize();
HypreParMatrix *A = a.ParallelAssemble();
HypreParMatrix *M = m.ParallelAssemble();
HypreBoomerAMG amg(*A);
amg.SetPrintLevel(0);
int nev = dim;
HypreLOBPCG lobpcg(MPI_COMM_WORLD);
lobpcg.SetNumModes(nev);
lobpcg.SetRandomSeed(seed);
lobpcg.SetPreconditioner(amg);
lobpcg.SetMaxIter(200);
lobpcg.SetTol(1e-8);
lobpcg.SetPrecondUsageMode(1);
lobpcg.SetPrintLevel(0);
lobpcg.SetMassMatrix(*M);
lobpcg.SetOperator(*A);
Array<real_t> eigenvalues;
lobpcg.Solve();
lobpcg.GetEigenvalues(eigenvalues);
Array<int> exact_eigs(&eigs[7 * (dim - 1)], 7);
real_t max_err = 0.0;
for (int i=0; i<nev; i++)
{
real_t lc = eigenvalues[i];
real_t le = exact_eigs[i];
real_t err = 100.0 * fabs(le - lc) / le;
max_err = std::max(max_err, err);
REQUIRE(err < 5.0);
}
CAPTURE(mt, max_err);
delete A;
delete M;
}
}
#endif // MFEM_USE_MPI
Mesh * GetMesh(MeshType type)
{
Mesh * mesh = NULL;
real_t c[3];
int v[8];
switch (type)
{
case SEGMENT:
mesh = new Mesh(1, 2, 1);
c[0] = 0.0;
mesh->AddVertex(c);
c[0] = a_;
mesh->AddVertex(c);
v[0] = 0; v[1] = 1;
mesh->AddSegment(v);
{
Element * el = mesh->NewElement(Geometry::POINT);
el->SetAttribute(1);
el->SetVertices(&v[0]);
mesh->AddBdrElement(el);
}
{
Element * el = mesh->NewElement(Geometry::POINT);
el->SetAttribute(2);
el->SetVertices(&v[1]);
mesh->AddBdrElement(el);
}
break;
case QUADRILATERAL:
mesh = new Mesh(2, 4, 1);
c[0] = 0.0; c[1] = 0.0;
mesh->AddVertex(c);
c[0] = a_; c[1] = 0.0;
mesh->AddVertex(c);
c[0] = a_; c[1] = b_;
mesh->AddVertex(c);
c[0] = 0.0; c[1] = b_;
mesh->AddVertex(c);
v[0] = 0; v[1] = 1; v[2] = 2; v[3] = 3;
mesh->AddQuad(v);
break;
case TRIANGLE2A:
mesh = new Mesh(2, 4, 2);
c[0] = 0.0; c[1] = 0.0;
mesh->AddVertex(c);
c[0] = a_; c[1] = 0.0;
mesh->AddVertex(c);
c[0] = a_; c[1] = b_;
mesh->AddVertex(c);
c[0] = 0.0; c[1] = b_;
mesh->AddVertex(c);
v[0] = 0; v[1] = 1; v[2] = 2;
mesh->AddTri(v);
v[0] = 2; v[1] = 3; v[2] = 0;
mesh->AddTri(v);
break;
case TRIANGLE2B:
mesh = new Mesh(2, 4, 2);
c[0] = 0.0; c[1] = 0.0;
mesh->AddVertex(c);
c[0] = a_; c[1] = 0.0;
mesh->AddVertex(c);
c[0] = a_; c[1] = b_;
mesh->AddVertex(c);
c[0] = 0.0; c[1] = b_;
mesh->AddVertex(c);
v[0] = 1; v[1] = 2; v[2] = 0;
mesh->AddTri(v);
v[0] = 3; v[1] = 0; v[2] = 2;
mesh->AddTri(v);
break;
case TRIANGLE2C:
mesh = new Mesh(2, 4, 2);
c[0] = 0.0; c[1] = 0.0;
mesh->AddVertex(c);
c[0] = a_; c[1] = 0.0;
mesh->AddVertex(c);
c[0] = a_; c[1] = b_;
mesh->AddVertex(c);
c[0] = 0.0; c[1] = b_;
mesh->AddVertex(c);
v[0] = 2; v[1] = 0; v[2] = 1;
mesh->AddTri(v);
v[0] = 0; v[1] = 2; v[2] = 3;
mesh->AddTri(v);
break;
case TRIANGLE4:
mesh = new Mesh(2, 5, 4);
c[0] = 0.0; c[1] = 0.0;
mesh->AddVertex(c);
c[0] = a_; c[1] = 0.0;
mesh->AddVertex(c);
c[0] = a_; c[1] = b_;
mesh->AddVertex(c);
c[0] = 0.0; c[1] = b_;
mesh->AddVertex(c);
c[0] = 0.5 * a_; c[1] = 0.5 * b_;
mesh->AddVertex(c);
v[0] = 0; v[1] = 1; v[2] = 4;
mesh->AddTri(v);
v[0] = 1; v[1] = 2; v[2] = 4;
mesh->AddTri(v);
v[0] = 2; v[1] = 3; v[2] = 4;
mesh->AddTri(v);
v[0] = 3; v[1] = 0; v[2] = 4;
mesh->AddTri(v);
break;
case MIXED2D:
mesh = new Mesh(2, 6, 4);
c[0] = 0.0; c[1] = 0.0;
mesh->AddVertex(c);
c[0] = a_; c[1] = 0.0;
mesh->AddVertex(c);
c[0] = a_; c[1] = b_;
mesh->AddVertex(c);
c[0] = 0.0; c[1] = b_;
mesh->AddVertex(c);
c[0] = 0.5 * b_; c[1] = 0.5 * b_;
mesh->AddVertex(c);
c[0] = a_ - 0.5 * b_; c[1] = 0.5 * b_;
mesh->AddVertex(c);
v[0] = 0; v[1] = 1; v[2] = 5; v[3] = 4;
mesh->AddQuad(v);
v[0] = 1; v[1] = 2; v[2] = 5;
mesh->AddTri(v);
v[0] = 2; v[1] = 3; v[2] = 4; v[3] = 5;
mesh->AddQuad(v);
v[0] = 3; v[1] = 0; v[2] = 4;
mesh->AddTri(v);
break;
case HEXAHEDRON:
mesh = new Mesh(3, 8, 1);
c[0] = 0.0; c[1] = 0.0; c[2] = 0.0;
mesh->AddVertex(c);
c[0] = a_; c[1] = 0.0; c[2] = 0.0;
mesh->AddVertex(c);
c[0] = a_; c[1] = b_; c[2] = 0.0;
mesh->AddVertex(c);
c[0] = 0.0; c[1] = b_; c[2] = 0.0;
mesh->AddVertex(c);
c[0] = 0.0; c[1] = 0.0; c[2] = c_;
mesh->AddVertex(c);
c[0] = a_; c[1] = 0.0; c[2] = c_;
mesh->AddVertex(c);
c[0] = a_; c[1] = b_; c[2] = c_;
mesh->AddVertex(c);
c[0] = 0.0; c[1] = b_; c[2] = c_;
mesh->AddVertex(c);
v[0] = 0; v[1] = 1; v[2] = 2; v[3] = 3;
v[4] = 4; v[5] = 5; v[6] = 6; v[7] = 7;
mesh->AddHex(v);
break;
case HEXAHEDRON2A:
case HEXAHEDRON2B:
case HEXAHEDRON2C:
case HEXAHEDRON2D:
mesh = new Mesh(3, 12, 2);
c[0] = 0.0; c[1] = 0.0; c[2] = 0.0;
mesh->AddVertex(c);
c[0] = 0.5 * a_; c[1] = 0.0; c[2] = 0.0;
mesh->AddVertex(c);
c[0] = a_; c[1] = 0.0; c[2] = 0.0;
mesh->AddVertex(c);
c[0] = a_; c[1] = b_; c[2] = 0.0;
mesh->AddVertex(c);
c[0] = 0.5 * a_; c[1] = b_; c[2] = 0.0;
mesh->AddVertex(c);
c[0] = 0.0; c[1] = b_; c[2] = 0.0;
mesh->AddVertex(c);
c[0] = 0.0; c[1] = 0.0; c[2] = c_;
mesh->AddVertex(c);
c[0] = 0.5 * a_; c[1] = 0.0; c[2] = c_;
mesh->AddVertex(c);
c[0] = a_; c[1] = 0.0; c[2] = c_;
mesh->AddVertex(c);
c[0] = a_; c[1] = b_; c[2] = c_;
mesh->AddVertex(c);
c[0] = 0.5 * a_; c[1] = b_; c[2] = c_;
mesh->AddVertex(c);
c[0] = 0.0; c[1] = b_; c[2] = c_;
mesh->AddVertex(c);
v[0] = 0; v[1] = 5; v[2] = 11; v[3] = 6;
v[4] = 1; v[5] = 4; v[6] = 10; v[7] = 7;
mesh->AddHex(v);
switch (type)
{
case HEXAHEDRON2A: // Face Orientation 1
v[0] = 4; v[1] = 10; v[2] = 7; v[3] = 1;
v[4] = 3; v[5] = 9; v[6] = 8; v[7] = 2;
mesh->AddHex(v);
break;
case HEXAHEDRON2B: // Face Orientation 3
v[0] = 10; v[1] = 7; v[2] = 1; v[3] = 4;
v[4] = 9; v[5] = 8; v[6] = 2; v[7] = 3;
mesh->AddHex(v);
break;
case HEXAHEDRON2C: // Face Orientation 5
v[0] = 7; v[1] = 1; v[2] = 4; v[3] = 10;
v[4] = 8; v[5] = 2; v[6] = 3; v[7] = 9;
mesh->AddHex(v);
break;
case HEXAHEDRON2D: // Face Orientation 7
v[0] = 1; v[1] = 4; v[2] = 10; v[3] = 7;
v[4] = 2; v[5] = 3; v[6] = 9; v[7] = 8;
mesh->AddHex(v);
break;
default:
// Cannot happen
break;
}
break;
case WEDGE2:
mesh = new Mesh(3, 8, 2);
c[0] = 0.0; c[1] = 0.0; c[2] = 0.0;
mesh->AddVertex(c);
c[0] = a_; c[1] = 0.0; c[2] = 0.0;
mesh->AddVertex(c);
c[0] = a_; c[1] = b_; c[2] = 0.0;
mesh->AddVertex(c);
c[0] = 0.0; c[1] = b_; c[2] = 0.0;
mesh->AddVertex(c);
c[0] = 0.0; c[1] = 0.0; c[2] = c_;
mesh->AddVertex(c);
c[0] = a_; c[1] = 0.0; c[2] = c_;
mesh->AddVertex(c);
c[0] = a_; c[1] = b_; c[2] = c_;
mesh->AddVertex(c);
c[0] = 0.0; c[1] = b_; c[2] = c_;
mesh->AddVertex(c);
v[0] = 0; v[1] = 1; v[2] = 2; v[3] = 4; v[4] = 5; v[5] = 6;
mesh->AddWedge(v);
v[0] = 0; v[1] = 2; v[2] = 3; v[3] = 4; v[4] = 6; v[5] = 7;
mesh->AddWedge(v);
break;
case TETRAHEDRA:
mesh = new Mesh(3, 8, 5);
c[0] = 0.0; c[1] = 0.0; c[2] = 0.0;
mesh->AddVertex(c);
c[0] = a_; c[1] = 0.0; c[2] = 0.0;
mesh->AddVertex(c);
c[0] = a_; c[1] = b_; c[2] = 0.0;
mesh->AddVertex(c);
c[0] = 0.0; c[1] = b_; c[2] = 0.0;
mesh->AddVertex(c);
c[0] = 0.0; c[1] = 0.0; c[2] = c_;
mesh->AddVertex(c);
c[0] = a_; c[1] = 0.0; c[2] = c_;
mesh->AddVertex(c);
c[0] = a_; c[1] = b_; c[2] = c_;
mesh->AddVertex(c);
c[0] = 0.0; c[1] = b_; c[2] = c_;
mesh->AddVertex(c);
v[0] = 0; v[1] = 2; v[2] = 7; v[3] = 5;
mesh->AddTet(v);
v[0] = 6; v[1] = 7; v[2] = 2; v[3] = 5;
mesh->AddTet(v);
v[0] = 4; v[1] = 7; v[2] = 5; v[3] = 0;
mesh->AddTet(v);
v[0] = 1; v[1] = 0; v[2] = 5; v[3] = 2;
mesh->AddTet(v);
v[0] = 3; v[1] = 7; v[2] = 0; v[3] = 2;
mesh->AddTet(v);
break;
case WEDGE4:
mesh = new Mesh(3, 10, 4);
c[0] = 0.0; c[1] = 0.0; c[2] = 0.0;
mesh->AddVertex(c);
c[0] = a_; c[1] = 0.0; c[2] = 0.0;
mesh->AddVertex(c);
c[0] = a_; c[1] = b_; c[2] = 0.0;
mesh->AddVertex(c);
c[0] = 0.0; c[1] = b_; c[2] = 0.0;
mesh->AddVertex(c);
c[0] = 0.5 * a_; c[1] = 0.5 * b_; c[2] = 0.0;
mesh->AddVertex(c);
c[0] = 0.0; c[1] = 0.0; c[2] = c_;
mesh->AddVertex(c);
c[0] = a_; c[1] = 0.0; c[2] = c_;
mesh->AddVertex(c);
c[0] = a_; c[1] = b_; c[2] = c_;
mesh->AddVertex(c);
c[0] = 0.0; c[1] = b_; c[2] = c_;
mesh->AddVertex(c);
c[0] = 0.5 * a_; c[1] = 0.5 * b_; c[2] = c_;
mesh->AddVertex(c);
v[0] = 0; v[1] = 1; v[2] = 4; v[3] = 5; v[4] = 6; v[5] = 9;
mesh->AddWedge(v);
v[0] = 1; v[1] = 2; v[2] = 4; v[3] = 6; v[4] = 7; v[5] = 9;
mesh->AddWedge(v);
v[0] = 2; v[1] = 3; v[2] = 4; v[3] = 7; v[4] = 8; v[5] = 9;
mesh->AddWedge(v);
v[0] = 3; v[1] = 0; v[2] = 4; v[3] = 8; v[4] = 5; v[5] = 9;
mesh->AddWedge(v);
break;
case MIXED3D6:
mesh = new Mesh(3, 12, 6);
c[0] = 0.0; c[1] = 0.0; c[2] = 0.0;
mesh->AddVertex(c);
c[0] = a_; c[1] = 0.0; c[2] = 0.0;
mesh->AddVertex(c);
c[0] = a_; c[1] = b_; c[2] = 0.0;
mesh->AddVertex(c);
c[0] = 0.0; c[1] = b_; c[2] = 0.0;
mesh->AddVertex(c);
c[0] = 0.5 * c_; c[1] = 0.5 * c_; c[2] = 0.5 * c_;
mesh->AddVertex(c);
c[0] = a_ - 0.5 * c_; c[1] = 0.5 * c_; c[2] = 0.5 * c_;
mesh->AddVertex(c);
c[0] = a_ - 0.5 * c_; c[1] = b_ - 0.5 * c_; c[2] = 0.5 * c_;
mesh->AddVertex(c);
c[0] = 0.5 * c_; c[1] = b_ - 0.5 * c_; c[2] = 0.5 * c_;
mesh->AddVertex(c);
c[0] = 0.0; c[1] = 0.0; c[2] = c_;
mesh->AddVertex(c);
c[0] = a_; c[1] = 0.0; c[2] = c_;
mesh->AddVertex(c);
c[0] = a_; c[1] = b_; c[2] = c_;
mesh->AddVertex(c);
c[0] = 0.0; c[1] = b_; c[2] = c_;
mesh->AddVertex(c);
v[0] = 0; v[1] = 1; v[2] = 2; v[3] = 3;
v[4] = 4; v[5] = 5; v[6] = 6; v[7] = 7;
mesh->AddHex(v);
v[0] = 0; v[1] = 4; v[2] = 8; v[3] = 1; v[4] = 5; v[5] = 9;
mesh->AddWedge(v);
v[0] = 1; v[1] = 5; v[2] = 9; v[3] = 2; v[4] = 6; v[5] = 10;
mesh->AddWedge(v);
v[0] = 2; v[1] = 6; v[2] = 10; v[3] = 3; v[4] = 7; v[5] = 11;
mesh->AddWedge(v);
v[0] = 3; v[1] = 7; v[2] = 11; v[3] = 0; v[4] = 4; v[5] = 8;
mesh->AddWedge(v);
v[0] = 4; v[1] = 5; v[2] = 6; v[3] = 7;
v[4] = 8; v[5] = 9; v[6] = 10; v[7] = 11;
mesh->AddHex(v);
break;
case MIXED3D8:
mesh = new Mesh(3, 10, 8);
c[0] = 0.0; c[1] = 0.0; c[2] = 0.0;
mesh->AddVertex(c);
c[0] = a_; c[1] = 0.0; c[2] = 0.0;
mesh->AddVertex(c);
c[0] = a_; c[1] = b_; c[2] = 0.0;
mesh->AddVertex(c);
c[0] = 0.0; c[1] = b_; c[2] = 0.0;
mesh->AddVertex(c);
c[0] = 0.25 * a_; c[1] = 0.5 * b_; c[2] = 0.5 * c_;
mesh->AddVertex(c);
c[0] = 0.75 * a_; c[1] = 0.5 * b_; c[2] = 0.5 * c_;
mesh->AddVertex(c);
c[0] = 0.0; c[1] = 0.0; c[2] = c_;
mesh->AddVertex(c);
c[0] = a_; c[1] = 0.0; c[2] = c_;
mesh->AddVertex(c);
c[0] = a_; c[1] = b_; c[2] = c_;
mesh->AddVertex(c);
c[0] = 0.0; c[1] = b_; c[2] = c_;
mesh->AddVertex(c);
v[0] = 0; v[1] = 3; v[2] = 4; v[3] = 1; v[4] = 2; v[5] = 5;
mesh->AddWedge(v);
v[0] = 3; v[1] = 9; v[2] = 4; v[3] = 2; v[4] = 8; v[5] = 5;
mesh->AddWedge(v);
v[0] = 9; v[1] = 6; v[2] = 4; v[3] = 8; v[4] = 7; v[5] = 5;
mesh->AddWedge(v);
v[0] = 6; v[1] = 0; v[2] = 4; v[3] = 7; v[4] = 1; v[5] = 5;
mesh->AddWedge(v);
v[0] = 0; v[1] = 3; v[2] = 9; v[3] = 4;
mesh->AddTet(v);
v[0] = 0; v[1] = 9; v[2] = 6; v[3] = 4;
mesh->AddTet(v);
v[0] = 1; v[1] = 7; v[2] = 2; v[3] = 5;
mesh->AddTet(v);
v[0] = 8; v[1] = 2; v[2] = 7; v[3] = 5;
mesh->AddTet(v);
break;
}
mesh->FinalizeTopology();
return mesh;
}
} // namespace eigs