684 lines
20 KiB
C++
684 lines
20 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 domain_int
|
|
{
|
|
|
|
static double a_ = 5.0;
|
|
static double b_ = 3.0;
|
|
static double c_ = 2.0;
|
|
|
|
double integral(int dim)
|
|
{
|
|
if (dim == 1)
|
|
{
|
|
return a_;
|
|
}
|
|
else if (dim == 2)
|
|
{
|
|
return a_ * b_;
|
|
}
|
|
else
|
|
{
|
|
return a_ * b_ * c_;
|
|
}
|
|
}
|
|
|
|
enum FEType
|
|
{
|
|
H1_FEC = 0,
|
|
ND_FEC,
|
|
RT_FEC,
|
|
L2V_FEC,
|
|
L2I_FEC,
|
|
};
|
|
|
|
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,
|
|
PYRAMID = 17
|
|
};
|
|
|
|
Mesh * GetMesh(MeshType type);
|
|
|
|
TEST_CASE("Domain Integration (Scalar Field)",
|
|
"[H1_FECollection]"
|
|
"[L2_FECollection]"
|
|
"[GridFunction]"
|
|
"[LinearForm]")
|
|
{
|
|
int order = 2;
|
|
|
|
for (int mt = (int)MeshType::SEGMENT;
|
|
mt <= (int)MeshType::PYRAMID; mt++)
|
|
{
|
|
Mesh *mesh = GetMesh((MeshType)mt);
|
|
int dim = mesh->Dimension();
|
|
mesh->UniformRefinement();
|
|
|
|
ConstantCoefficient oneCoef(1.0);
|
|
|
|
for (int ft = (int)FEType::H1_FEC; ft <= (int)FEType::L2I_FEC; ft++)
|
|
{
|
|
if (ft == (int)FEType::ND_FEC || ft == (int)FEType::RT_FEC)
|
|
{ continue; }
|
|
|
|
SECTION("Integral of field " + std::to_string(ft) +
|
|
" on mesh type " + std::to_string(mt) )
|
|
{
|
|
|
|
FiniteElementCollection *fec = NULL;
|
|
switch ((FEType)ft)
|
|
{
|
|
case FEType::H1_FEC:
|
|
fec = new H1_FECollection(order, dim);
|
|
break;
|
|
case FEType::L2V_FEC:
|
|
fec = new L2_FECollection(order-1, dim);
|
|
break;
|
|
case FEType::L2I_FEC:
|
|
fec = new L2_FECollection(order-1, dim,
|
|
BasisType::GaussLegendre,
|
|
FiniteElement::INTEGRAL);
|
|
break;
|
|
default:
|
|
MFEM_ABORT("Invalid vector FE type");
|
|
}
|
|
FiniteElementSpace fespace(mesh, fec);
|
|
|
|
GridFunction u(&fespace);
|
|
u.ProjectCoefficient(oneCoef);
|
|
|
|
LinearForm b(&fespace);
|
|
b.AddDomainIntegrator(new DomainLFIntegrator(oneCoef));
|
|
b.Assemble();
|
|
|
|
double id = b(u);
|
|
|
|
if (dim == 1)
|
|
{
|
|
REQUIRE(id == MFEM_Approx( 5.0));
|
|
}
|
|
else if (dim == 2)
|
|
{
|
|
REQUIRE(id == MFEM_Approx(15.0));
|
|
}
|
|
else
|
|
{
|
|
REQUIRE(id == MFEM_Approx(30.0));
|
|
}
|
|
|
|
delete fec;
|
|
}
|
|
}
|
|
|
|
delete mesh;
|
|
}
|
|
}
|
|
|
|
TEST_CASE("Domain Integration (Vector Field)",
|
|
"[ND_FECollection]"
|
|
"[RT_FECollection]"
|
|
"[GridFunction]"
|
|
"[LinearForm]")
|
|
{
|
|
int order = 1;
|
|
|
|
for (int mt = (int)MeshType::SEGMENT;
|
|
mt <= (int)MeshType::MIXED3D8; mt++)
|
|
{
|
|
Mesh *mesh = GetMesh((MeshType)mt);
|
|
int dim = mesh->Dimension();
|
|
int sdim = mesh->SpaceDimension();
|
|
mesh->UniformRefinement();
|
|
|
|
Vector f1(sdim); f1 = 1.0;
|
|
Vector fx(sdim); fx = 0.0; fx[0] = 1.0;
|
|
Vector fy(sdim); fy = 0.0;
|
|
if (sdim > 1) { fy[1] = 1.0; }
|
|
Vector fz(sdim); fz = 0.0;
|
|
if (sdim > 2) { fz[2] = 1.0; }
|
|
|
|
VectorConstantCoefficient f1Coef(f1);
|
|
VectorConstantCoefficient fxCoef(fx);
|
|
VectorConstantCoefficient fyCoef(fy);
|
|
VectorConstantCoefficient fzCoef(fz);
|
|
|
|
for (int ft = (int)FEType::ND_FEC; ft <= (int)FEType::RT_FEC; ft++)
|
|
{
|
|
if (dim == 1 && ft == (int)FEType::RT_FEC) { continue; }
|
|
if (mt == (int)MeshType::WEDGE2 || mt == (int)MeshType::WEDGE4 ||
|
|
mt == (int)MeshType::MIXED3D6 || mt == (int)MeshType::MIXED3D8)
|
|
{ continue; }
|
|
|
|
SECTION("Integral of field " + std::to_string(ft) +
|
|
" on mesh type " + std::to_string(mt) )
|
|
{
|
|
|
|
FiniteElementCollection *fec = NULL;
|
|
switch ((FEType)ft)
|
|
{
|
|
case FEType::ND_FEC:
|
|
fec = new ND_FECollection(order, dim);
|
|
break;
|
|
case FEType::RT_FEC:
|
|
fec = new RT_FECollection(order-1, dim);
|
|
break;
|
|
default:
|
|
MFEM_ABORT("Invalid vector FE type");
|
|
}
|
|
FiniteElementSpace fespace(mesh, fec);
|
|
|
|
GridFunction u(&fespace);
|
|
u.ProjectCoefficient(f1Coef);
|
|
|
|
LinearForm bx(&fespace);
|
|
LinearForm by(&fespace);
|
|
LinearForm bz(&fespace);
|
|
bx.AddDomainIntegrator(new VectorFEDomainLFIntegrator(fxCoef));
|
|
by.AddDomainIntegrator(new VectorFEDomainLFIntegrator(fyCoef));
|
|
bz.AddDomainIntegrator(new VectorFEDomainLFIntegrator(fzCoef));
|
|
bx.Assemble();
|
|
by.Assemble();
|
|
bz.Assemble();
|
|
|
|
double ix = bx(u);
|
|
double iy = by(u);
|
|
double iz = bz(u);
|
|
|
|
if (dim == 1)
|
|
{
|
|
REQUIRE(ix == MFEM_Approx( 5.0));
|
|
}
|
|
else if (dim == 2)
|
|
{
|
|
REQUIRE(ix == MFEM_Approx(15.0));
|
|
REQUIRE(iy == MFEM_Approx(15.0));
|
|
}
|
|
else
|
|
{
|
|
REQUIRE(ix == MFEM_Approx(30.0));
|
|
REQUIRE(iy == MFEM_Approx(30.0));
|
|
REQUIRE(iz == MFEM_Approx(30.0));
|
|
}
|
|
|
|
delete fec;
|
|
}
|
|
}
|
|
|
|
delete mesh;
|
|
}
|
|
}
|
|
|
|
#ifdef MFEM_USE_MPI
|
|
|
|
TEST_CASE("Domain Integration in Parallel (Scalar Field)",
|
|
"[H1_FECollection]"
|
|
"[L2_FECollection]"
|
|
"[ParGridFunction]"
|
|
"[ParLinearForm]"
|
|
"[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;
|
|
|
|
for (int mt = (int)MeshType::SEGMENT;
|
|
mt <= (int)MeshType::MIXED3D8; mt++)
|
|
{
|
|
Mesh *mesh = GetMesh((MeshType)mt);
|
|
int dim = mesh->Dimension();
|
|
while (mesh->GetNE() < num_procs)
|
|
{
|
|
mesh->UniformRefinement();
|
|
}
|
|
ParMesh pmesh(MPI_COMM_WORLD, *mesh);
|
|
delete mesh;
|
|
|
|
ConstantCoefficient oneCoef(1.0);
|
|
|
|
for (int ft = (int)FEType::H1_FEC; ft <= (int)FEType::L2I_FEC; ft++)
|
|
{
|
|
if (ft == (int)FEType::ND_FEC || ft == (int)FEType::RT_FEC)
|
|
{ continue; }
|
|
|
|
SECTION("Integral of field " + std::to_string(ft) +
|
|
" on mesh type " + std::to_string(mt) )
|
|
{
|
|
FiniteElementCollection *fec = NULL;
|
|
switch ((FEType)ft)
|
|
{
|
|
case FEType::H1_FEC:
|
|
fec = new H1_FECollection(order, dim);
|
|
break;
|
|
case FEType::L2V_FEC:
|
|
fec = new L2_FECollection(order-1, dim);
|
|
break;
|
|
case FEType::L2I_FEC:
|
|
fec = new L2_FECollection(order-1, dim,
|
|
BasisType::GaussLegendre,
|
|
FiniteElement::INTEGRAL);
|
|
break;
|
|
default:
|
|
MFEM_ABORT("Invalid vector FE type");
|
|
}
|
|
ParFiniteElementSpace fespace(&pmesh, fec);
|
|
|
|
ParGridFunction u(&fespace);
|
|
u.ProjectCoefficient(oneCoef);
|
|
|
|
ParLinearForm b(&fespace);
|
|
b.AddDomainIntegrator(new DomainLFIntegrator(oneCoef));
|
|
b.Assemble();
|
|
|
|
double id = b(u);
|
|
|
|
if (dim == 1)
|
|
{
|
|
REQUIRE(id == MFEM_Approx( 5.0));
|
|
}
|
|
else if (dim == 2)
|
|
{
|
|
REQUIRE(id == MFEM_Approx(15.0));
|
|
}
|
|
else
|
|
{
|
|
REQUIRE(id == MFEM_Approx(30.0));
|
|
}
|
|
|
|
delete fec;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
TEST_CASE("Domain Integration in Parallel (Vector Field)",
|
|
"[ParGridFunction]"
|
|
"[ParLinearForm]"
|
|
"[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;
|
|
|
|
for (int mt = (int)MeshType::SEGMENT;
|
|
mt <= (int)MeshType::MIXED3D8; mt++)
|
|
{
|
|
Mesh *mesh = GetMesh((MeshType)mt);
|
|
int dim = mesh->Dimension();
|
|
int sdim = mesh->SpaceDimension();
|
|
while (mesh->GetNE() < num_procs)
|
|
{
|
|
mesh->UniformRefinement();
|
|
}
|
|
ParMesh pmesh(MPI_COMM_WORLD, *mesh);
|
|
delete mesh;
|
|
|
|
Vector f1(sdim); f1 = 1.0;
|
|
Vector fx(sdim); fx = 0.0; fx[0] = 1.0;
|
|
Vector fy(sdim); fy = 0.0;
|
|
if (sdim > 1) { fy[1] = 1.0; }
|
|
Vector fz(sdim); fz = 0.0;
|
|
if (sdim > 2) { fz[2] = 1.0; }
|
|
|
|
VectorConstantCoefficient f1Coef(f1);
|
|
VectorConstantCoefficient fxCoef(fx);
|
|
VectorConstantCoefficient fyCoef(fy);
|
|
VectorConstantCoefficient fzCoef(fz);
|
|
|
|
for (int ft = (int)FEType::ND_FEC; ft <= (int)FEType::RT_FEC; ft++)
|
|
{
|
|
if (dim == 1 && ft == (int)FEType::RT_FEC) { continue; }
|
|
if (mt == (int)MeshType::WEDGE2 || mt == (int)MeshType::WEDGE4 ||
|
|
mt == (int)MeshType::MIXED3D6 || mt == (int)MeshType::MIXED3D8)
|
|
{ continue; }
|
|
|
|
SECTION("Integral of field " + std::to_string(ft) +
|
|
" on mesh type " + std::to_string(mt) )
|
|
{
|
|
FiniteElementCollection *fec = NULL;
|
|
switch ((FEType)ft)
|
|
{
|
|
case FEType::ND_FEC:
|
|
fec = new ND_FECollection(order, dim);
|
|
break;
|
|
case FEType::RT_FEC:
|
|
fec = new RT_FECollection(order-1, dim);
|
|
break;
|
|
default:
|
|
MFEM_ABORT("Invalid vector FE type");
|
|
}
|
|
ParFiniteElementSpace fespace(&pmesh, fec);
|
|
|
|
ParGridFunction u(&fespace);
|
|
u.ProjectCoefficient(f1Coef);
|
|
|
|
ParLinearForm bx(&fespace);
|
|
ParLinearForm by(&fespace);
|
|
ParLinearForm bz(&fespace);
|
|
bx.AddDomainIntegrator(new VectorFEDomainLFIntegrator(fxCoef));
|
|
by.AddDomainIntegrator(new VectorFEDomainLFIntegrator(fyCoef));
|
|
bz.AddDomainIntegrator(new VectorFEDomainLFIntegrator(fzCoef));
|
|
bx.Assemble();
|
|
by.Assemble();
|
|
bz.Assemble();
|
|
|
|
double ix = bx(u);
|
|
double iy = by(u);
|
|
double iz = bz(u);
|
|
|
|
if (dim == 1)
|
|
{
|
|
REQUIRE(ix == MFEM_Approx( 5.0));
|
|
}
|
|
else if (dim == 2)
|
|
{
|
|
REQUIRE(ix == MFEM_Approx(15.0));
|
|
REQUIRE(iy == MFEM_Approx(15.0));
|
|
}
|
|
else
|
|
{
|
|
REQUIRE(ix == MFEM_Approx(30.0));
|
|
REQUIRE(iy == MFEM_Approx(30.0));
|
|
REQUIRE(iz == MFEM_Approx(30.0));
|
|
}
|
|
|
|
delete fec;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
#endif // MFEM_USE_MPI
|
|
|
|
Mesh * GetMesh(MeshType type)
|
|
{
|
|
Mesh * mesh = NULL;
|
|
|
|
switch (type)
|
|
{
|
|
case SEGMENT:
|
|
mesh = new Mesh(1, 2, 1);
|
|
mesh->AddVertex(0.0);
|
|
mesh->AddVertex(a_);
|
|
|
|
mesh->AddSegment(0, 1);
|
|
|
|
mesh->AddBdrPoint(0);
|
|
mesh->AddBdrPoint(1);
|
|
break;
|
|
case QUADRILATERAL:
|
|
mesh = new Mesh(2, 4, 1);
|
|
mesh->AddVertex(0.0, 0.0);
|
|
mesh->AddVertex(a_, 0.0);
|
|
mesh->AddVertex(a_, b_);
|
|
mesh->AddVertex(0.0, b_);
|
|
|
|
mesh->AddQuad(0, 1, 2, 3);
|
|
break;
|
|
case TRIANGLE2A:
|
|
mesh = new Mesh(2, 4, 2);
|
|
mesh->AddVertex(0.0, 0.0);
|
|
mesh->AddVertex(a_, 0.0);
|
|
mesh->AddVertex(a_, b_);
|
|
mesh->AddVertex(0.0, b_);
|
|
|
|
mesh->AddTriangle(0, 1, 2);
|
|
mesh->AddTriangle(2, 3, 0);
|
|
break;
|
|
case TRIANGLE2B:
|
|
mesh = new Mesh(2, 4, 2);
|
|
mesh->AddVertex(0.0, 0.0);
|
|
mesh->AddVertex(a_, 0.0);
|
|
mesh->AddVertex(a_, b_);
|
|
mesh->AddVertex(0.0, b_);
|
|
|
|
mesh->AddTriangle(1, 2, 0);
|
|
mesh->AddTriangle(3, 0, 2);
|
|
break;
|
|
case TRIANGLE2C:
|
|
mesh = new Mesh(2, 4, 2);
|
|
mesh->AddVertex(0.0, 0.0);
|
|
mesh->AddVertex(a_, 0.0);
|
|
mesh->AddVertex(a_, b_);
|
|
mesh->AddVertex(0.0, b_);
|
|
|
|
mesh->AddTriangle(2, 0, 1);
|
|
mesh->AddTriangle(0, 2, 3);
|
|
break;
|
|
case TRIANGLE4:
|
|
mesh = new Mesh(2, 5, 4);
|
|
mesh->AddVertex(0.0, 0.0);
|
|
mesh->AddVertex(a_, 0.0);
|
|
mesh->AddVertex(a_, b_);
|
|
mesh->AddVertex(0.0, b_);
|
|
mesh->AddVertex(0.5 * a_, 0.5 * b_);
|
|
|
|
mesh->AddTriangle(0, 1, 4);
|
|
mesh->AddTriangle(1, 2, 4);
|
|
mesh->AddTriangle(2, 3, 4);
|
|
mesh->AddTriangle(3, 0, 4);
|
|
break;
|
|
case MIXED2D:
|
|
mesh = new Mesh(2, 6, 4);
|
|
mesh->AddVertex(0.0, 0.0);
|
|
mesh->AddVertex(a_, 0.0);
|
|
mesh->AddVertex(a_, b_);
|
|
mesh->AddVertex(0.0, b_);
|
|
mesh->AddVertex(0.5 * b_, 0.5 * b_);
|
|
mesh->AddVertex(a_ - 0.5 * b_, 0.5 * b_);
|
|
|
|
mesh->AddQuad(0, 1, 5, 4);
|
|
mesh->AddTriangle(1, 2, 5);
|
|
mesh->AddQuad(2, 3, 4, 5);
|
|
mesh->AddTriangle(3, 0, 4);
|
|
break;
|
|
case HEXAHEDRON:
|
|
mesh = new Mesh(3, 8, 1);
|
|
mesh->AddVertex(0.0, 0.0, 0.0);
|
|
mesh->AddVertex(a_, 0.0, 0.0);
|
|
mesh->AddVertex(a_, b_, 0.0);
|
|
mesh->AddVertex(0.0, b_, 0.0);
|
|
mesh->AddVertex(0.0, 0.0, c_);
|
|
mesh->AddVertex(a_, 0.0, c_);
|
|
mesh->AddVertex(a_, b_, c_);
|
|
mesh->AddVertex(0.0, b_, c_);
|
|
|
|
mesh->AddHex(0, 1, 2, 3, 4, 5, 6, 7);
|
|
break;
|
|
case HEXAHEDRON2A:
|
|
case HEXAHEDRON2B:
|
|
case HEXAHEDRON2C:
|
|
case HEXAHEDRON2D:
|
|
mesh = new Mesh(3, 12, 2);
|
|
mesh->AddVertex(0.0, 0.0, 0.0);
|
|
mesh->AddVertex(0.5 * a_, 0.0, 0.0);
|
|
mesh->AddVertex(a_, 0.0, 0.0);
|
|
mesh->AddVertex(a_, b_, 0.0);
|
|
mesh->AddVertex(0.5 * a_, b_, 0.0);
|
|
mesh->AddVertex(0.0, b_, 0.0);
|
|
mesh->AddVertex(0.0, 0.0, c_);
|
|
mesh->AddVertex(0.5 * a_, 0.0, c_);
|
|
mesh->AddVertex(a_, 0.0, c_);
|
|
mesh->AddVertex(a_, b_, c_);
|
|
mesh->AddVertex(0.5 * a_, b_, c_);
|
|
mesh->AddVertex(0.0,b_, c_);
|
|
|
|
mesh->AddHex(0, 5, 11, 6, 1, 4, 10, 7);
|
|
|
|
switch (type)
|
|
{
|
|
case HEXAHEDRON2A: // Face Orientation 1
|
|
mesh->AddHex(4, 10, 7, 1, 3, 9, 8, 2);
|
|
break;
|
|
case HEXAHEDRON2B: // Face Orientation 3
|
|
mesh->AddHex(10, 7, 1, 4, 9, 8, 2, 3);
|
|
break;
|
|
case HEXAHEDRON2C: // Face Orientation 5
|
|
mesh->AddHex(7, 1, 4, 10, 8, 2, 3, 9);
|
|
break;
|
|
case HEXAHEDRON2D: // Face Orientation 7
|
|
mesh->AddHex(1, 4, 10, 7, 2, 3, 9, 8);
|
|
break;
|
|
default:
|
|
// Cannot happen
|
|
break;
|
|
}
|
|
break;
|
|
case WEDGE2:
|
|
mesh = new Mesh(3, 8, 2);
|
|
mesh->AddVertex(0.0, 0.0, 0.0);
|
|
mesh->AddVertex(a_, 0.0, 0.0);
|
|
mesh->AddVertex(a_, b_, 0.0);
|
|
mesh->AddVertex(0.0, b_, 0.0);
|
|
mesh->AddVertex(0.0, 0.0, c_);
|
|
mesh->AddVertex(a_, 0.0, c_);
|
|
mesh->AddVertex(a_, b_, c_);
|
|
mesh->AddVertex(0.0, b_, c_);
|
|
|
|
mesh->AddWedge(0, 1, 2, 4, 5, 6);
|
|
mesh->AddWedge(0, 2, 3, 4, 6, 7);
|
|
break;
|
|
case TETRAHEDRA:
|
|
mesh = new Mesh(3, 8, 5);
|
|
mesh->AddVertex(0.0, 0.0, 0.0);
|
|
mesh->AddVertex(a_, 0.0, 0.0);
|
|
mesh->AddVertex(a_, b_, 0.0);
|
|
mesh->AddVertex(0.0, b_, 0.0);
|
|
mesh->AddVertex(0.0, 0.0, c_);
|
|
mesh->AddVertex(a_, 0.0, c_);
|
|
mesh->AddVertex(a_, b_, c_);
|
|
mesh->AddVertex(0.0, b_, c_);
|
|
|
|
mesh->AddTet(0, 2, 7, 5);
|
|
mesh->AddTet(6, 7, 2, 5);
|
|
mesh->AddTet(4, 7, 5, 0);
|
|
mesh->AddTet(1, 0, 5, 2);
|
|
mesh->AddTet(3, 7, 0, 2);
|
|
break;
|
|
case WEDGE4:
|
|
mesh = new Mesh(3, 10, 4);
|
|
mesh->AddVertex(0.0, 0.0, 0.0);
|
|
mesh->AddVertex(a_, 0.0, 0.0);
|
|
mesh->AddVertex(a_, b_, 0.0);
|
|
mesh->AddVertex(0.0, b_, 0.0);
|
|
mesh->AddVertex(0.5 * a_, 0.5 * b_, 0.0);
|
|
mesh->AddVertex(0.0, 0.0, c_);
|
|
mesh->AddVertex(a_, 0.0, c_);
|
|
mesh->AddVertex(a_, b_, c_);
|
|
mesh->AddVertex(0.0, b_, c_);
|
|
mesh->AddVertex(0.5 * a_, 0.5 * b_, c_);
|
|
|
|
mesh->AddWedge(0, 1, 4, 5, 6, 9);
|
|
mesh->AddWedge(1, 2, 4, 6, 7, 9);
|
|
mesh->AddWedge(2, 3, 4, 7, 8, 9);
|
|
mesh->AddWedge(3, 0, 4, 8, 5, 9);
|
|
break;
|
|
case MIXED3D6:
|
|
mesh = new Mesh(3, 12, 6);
|
|
mesh->AddVertex(0.0, 0.0, 0.0);
|
|
mesh->AddVertex(a_, 0.0, 0.0);
|
|
mesh->AddVertex(a_, b_, 0.0);
|
|
mesh->AddVertex(0.0, b_, 0.0);
|
|
mesh->AddVertex(0.5 * c_, 0.5 * c_, 0.5 * c_);
|
|
mesh->AddVertex(a_ - 0.5 * c_, 0.5 * c_, 0.5 * c_);
|
|
mesh->AddVertex(a_ - 0.5 * c_, b_ - 0.5 * c_, 0.5 * c_);
|
|
mesh->AddVertex(0.5 * c_, b_ - 0.5 * c_, 0.5 * c_);
|
|
mesh->AddVertex(0.0, 0.0, c_);
|
|
mesh->AddVertex(a_, 0.0, c_);
|
|
mesh->AddVertex(a_, b_, c_);
|
|
mesh->AddVertex(0.0, b_, c_);
|
|
|
|
mesh->AddHex(0, 1, 2, 3, 4, 5, 6, 7);
|
|
mesh->AddWedge(0, 4, 8, 1, 5, 9);
|
|
mesh->AddWedge(1, 5, 9, 2, 6, 10);
|
|
mesh->AddWedge(2, 6, 10, 3, 7, 11);
|
|
mesh->AddWedge(3, 7, 11, 0, 4, 8);
|
|
mesh->AddHex(4, 5, 6, 7, 8, 9, 10, 11);
|
|
break;
|
|
case MIXED3D8:
|
|
mesh = new Mesh(3, 10, 8);
|
|
mesh->AddVertex(0.0, 0.0, 0.0);
|
|
mesh->AddVertex(a_, 0.0, 0.0);
|
|
mesh->AddVertex(a_, b_, 0.0);
|
|
mesh->AddVertex(0.0, b_, 0.0);
|
|
mesh->AddVertex(0.25 * a_, 0.5 * b_, 0.5 * c_);
|
|
mesh->AddVertex(0.75 * a_, 0.5 * b_, 0.5 * c_);
|
|
mesh->AddVertex(0.0, 0.0, c_);
|
|
mesh->AddVertex(a_, 0.0, c_);
|
|
mesh->AddVertex(a_, b_, c_);
|
|
mesh->AddVertex(0.0, b_, c_);
|
|
|
|
mesh->AddWedge(0, 3, 4, 1, 2, 5);
|
|
mesh->AddWedge(3, 9, 4, 2, 8, 5);
|
|
mesh->AddWedge(9, 6, 4, 8, 7, 5);
|
|
mesh->AddWedge(6, 0, 4, 7, 1, 5);
|
|
mesh->AddTet(0, 3, 9, 4);
|
|
mesh->AddTet(0, 9, 6, 4);
|
|
mesh->AddTet(1, 7, 2, 5);
|
|
mesh->AddTet(8, 2, 7, 5);
|
|
break;
|
|
case PYRAMID:
|
|
mesh = new Mesh(3, 9, 6);
|
|
mesh->AddVertex(0.0, 0.0, 0.0);
|
|
mesh->AddVertex(a_, 0.0, 0.0);
|
|
mesh->AddVertex(a_, b_, 0.0);
|
|
mesh->AddVertex(0.0, b_, 0.0);
|
|
mesh->AddVertex(0.5 * a_, 0.5 * b_, 0.5 * c_);
|
|
mesh->AddVertex(0.0, 0.0, c_);
|
|
mesh->AddVertex(a_, 0.0, c_);
|
|
mesh->AddVertex(a_, b_, c_);
|
|
mesh->AddVertex(0.0, b_, c_);
|
|
|
|
mesh->AddPyramid(0, 1, 2, 3, 4);
|
|
mesh->AddPyramid(0, 5, 6, 1, 4);
|
|
mesh->AddPyramid(1, 6, 7, 2, 4);
|
|
mesh->AddPyramid(2, 7, 8, 3, 4);
|
|
mesh->AddPyramid(3, 8, 5, 0, 4);
|
|
mesh->AddPyramid(8, 7, 6, 5, 4);
|
|
break;
|
|
}
|
|
mesh->FinalizeTopology();
|
|
|
|
return mesh;
|
|
}
|
|
|
|
} // namespace domain_int
|