Skip to content

Commit

Permalink
Tests
Browse files Browse the repository at this point in the history
  • Loading branch information
cbritopacheco committed Feb 14, 2025
1 parent 92e04d0 commit d2b35d4
Show file tree
Hide file tree
Showing 6 changed files with 453 additions and 14 deletions.
6 changes: 3 additions & 3 deletions src/Rodin/Variational/P1/QuadratureRule.h
Original file line number Diff line number Diff line change
Expand Up @@ -458,7 +458,7 @@ namespace Rodin::Variational
for (size_t i = 0; i < fe.getCount(); i++)
m_sb1[i] = fe.getBasis(i)(rc);
for (size_t i = 0; i < fe.getCount(); i++)
m_matrix(i, i) = Math::conj(csv) * Math::dot(m_sb1[i], m_sb1[i]);
m_matrix(i, i) = Math::conj(csv) * Math::dot(m_sb1[i], m_sb1[i]);
for (size_t i = 0; i < fe.getCount(); i++)
for (size_t j = 0; j < i; j++)
m_matrix(i, j) = Math::conj(csv) * Math::dot(m_sb1[j], m_sb1[i]);
Expand All @@ -470,7 +470,7 @@ namespace Rodin::Variational
for (size_t i = 0; i < fe.getCount(); i++)
fe.getBasis(i)(m_vb1[i], rc);
for (size_t i = 0; i < fe.getCount(); i++)
m_matrix(i, i) = Math::conj(csv) * Math::dot(m_vb1[i], m_vb1[i]);
m_matrix(i, i) = Math::conj(csv) * m_vb1[i].squaredNorm();
for (size_t i = 0; i < fe.getCount(); i++)
for (size_t j = 0; j < i; j++)
m_matrix(i, j) = Math::conj(csv) * Math::dot(m_vb1[j], m_vb1[i]);
Expand All @@ -482,7 +482,7 @@ namespace Rodin::Variational
for (size_t i = 0; i < fe.getCount(); i++)
fe.getBasis(i)(m_mb1[i], rc);
for (size_t i = 0; i < fe.getCount(); i++)
m_matrix(i, i) = Math::conj(csv) * Math::dot(m_mb1[i], m_mb1[i]);
m_matrix(i, i) = Math::conj(csv) * Math::dot(m_mb1[i], m_mb1[i]);
for (size_t i = 0; i < fe.getCount(); i++)
for (size_t j = 0; j < i; j++)
m_matrix(i, j) = Math::conj(csv) * Math::dot(m_mb1[j], m_mb1[i]);
Expand Down
11 changes: 11 additions & 0 deletions tests/manufactured/Rodin/P1/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -19,3 +19,14 @@ target_link_libraries(RodinManufacturedConductivity
Rodin::Solver
)
gtest_discover_tests(RodinManufacturedConductivity)

add_executable(RodinManufacturedReactionDiffusion ReactionDiffusion.cpp)
target_link_libraries(RodinManufacturedReactionDiffusion
PUBLIC
GTest::gtest
GTest::gtest_main
Rodin::Geometry
Rodin::Variational
Rodin::Solver
)
gtest_discover_tests(RodinManufacturedReactionDiffusion)
31 changes: 21 additions & 10 deletions tests/manufactured/Rodin/P1/Conductivity.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,15 +18,26 @@ using namespace Rodin::Solver;
using namespace Rodin::Test::Random;

/**
* Contains manufactured solution tests cases for the conductivity equation.
* @brief Manufactured solutions for the conductivity problem using P1 spaces.
*
* The system is given by:
* @f[
* \left\{
* \begin{aligned}
* - \nabla \cdot (\gamma \nabla u) &= f && \mathrm{in} \ \Omega, \\
* u &= g && \mathrm{on} \ \Gamma.
* \end{aligned}
* \right.
* \begin{aligned}
* -\operatorname{div}( \gamma \nabla u) &= f \quad \text{in } \Omega,\\
* u &= g \quad \text{on } \partial\Omega.
* \end{aligned}
* \right.
* @f]
*
*
* The weak formulation is: Find @f$ u \in V @f$ such that
* @f[
* \int_\Omega \gamma \nabla u \cdot \nabla v \,dx = \int_\Omega f \, v \,dx,
* @f]
* for all @f$ v \in V @f$, with the essential boundary condition
* @f[
* u = g \quad \text{on } \partial\Omega.
* @f]
*/
namespace Rodin::Tests::Manufactured::Conductivity
Expand Down Expand Up @@ -167,7 +178,7 @@ namespace Rodin::Tests::Manufactured::Conductivity
* u(x,y)= e^{\phi(x,y)}-1,
* @f]
*
* so that \(u=0\) on \(\partial\Omega\). With
* so that @f$u=0@f$ on @f$\partial\Omega@f$. With
*
* @f[
* \gamma(x,y)= 1+x^2,
Expand Down Expand Up @@ -246,7 +257,7 @@ namespace Rodin::Tests::Manufactured::Conductivity
* u_y=(1-2y)x(1-x),\quad u_{yy}=-2x(1-x),
* @f]
*
* and with \(\gamma_x=1,\;\gamma_y=1\), we have
* and with @f$\gamma_x=1,\;\gamma_y=1@f$, we have
*
* @f[
* f(x,y)=-\Bigl[\gamma_xu_x+\gamma\,u_{xx}+\gamma_yu_y+\gamma\,u_{yy}\Bigr].
Expand Down Expand Up @@ -316,7 +327,7 @@ namespace Rodin::Tests::Manufactured::Conductivity
* u_{xx}=-\pi^2\sin(\pi x)e^y,\quad u_{yy}=\sin(\pi x)e^y,
* @f]
*
* with \(\gamma_x=1,\;\gamma_y=0\), the forcing function is given by
* with @f$\gamma_x=1,\;\gamma_y=0@f$, the forcing function is given by
*
* @f[
* f(x,y)=-\Bigl[u_x+(1+x)(u_{xx}+u_{yy})\Bigr].
Expand Down Expand Up @@ -390,7 +401,7 @@ namespace Rodin::Tests::Manufactured::Conductivity
* u_y=-\pi\cos(\pi x)\sin(\pi y),\quad u_{yy}=-\pi^2\cos(\pi x)\cos(\pi y).
* @f]
*
* (Note: \(\gamma_x=1,\;\gamma_y=0\).)
* @note @f$ \gamma_x=1,\; \gamma_y=0 @f$
*/
TEST(Rodin_Manufactured_P1, Conductivity_NonhomogeneousDirichlet)
{
Expand Down
154 changes: 154 additions & 0 deletions tests/manufactured/Rodin/P1/Darcy.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
/*
* Copyright Carlos BRITO PACHECO 2021 - 2025.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE or copy at
* https://www.boost.org/LICENSE_1_0.txt)
*/
#include <gtest/gtest.h>

#include "Rodin/Variational.h"
#include "Rodin/Solver/CG.h"

using namespace Rodin;
using namespace Rodin::Geometry;
using namespace Rodin::Variational;
using namespace Rodin::Solver;

/**
*
* @brief Manufactured solution for the Darcy problem using P1 spaces.
*
* Let the pressure and flux satisfy
* @f[
* \mathbf{u} = -\nabla p \quad \text{in } \Omega,
* @f]
* @f[
* \operatorname{div}\,\mathbf{u} = f \quad \text{in } \Omega,
* @f]
* with the Dirichlet boundary condition
* @f[
* p = p_{\mathrm{exact}} \quad \text{on } \partial\Omega.
* @f]
*
* The weak formulation is: Find @f$(\mathbf{u}, p) \in \mathbb{P}_1^2 \times \mathbb{P}_1@f$ such that
* @f[
* (\mathbf{u}, \mathbf{v}) - (p, \operatorname{div}\,\mathbf{v}) -
* (\operatorname{div}\,\mathbf{u}, q) + (f, q) = 0,
* @f]
* for all test functions @f$(\mathbf{v},q)@f$ with the essential boundary condition
* @f[
* p = \sin(\pi x)\sin(\pi y) \quad \text{on } \partial\Omega.
* @f]
*
* @note Although mixed formulations typically use an H(div)–conforming space
* for the flux, here a vector–valued P1 space.
*/
namespace Rodin::Tests::Manufactured::Darcy
{
template <size_t M>
class ManufacturedDarcyTest : public ::testing::TestWithParam<Polytope::Type>
{
protected:
Mesh<Context::Local> getMesh()
{
Mesh mesh;
mesh = mesh.UniformGrid(GetParam(), { M, M });
mesh.scale(1.0 / (M - 1));
mesh.getConnectivity().compute(1, 2);
return mesh;
}
};

using ManufacturedDarcyTest16x16 = ManufacturedDarcyTest<16>;
using ManufacturedDarcyTest32x32 = ManufacturedDarcyTest<32>;
using ManufacturedDarcyTest64x64 = ManufacturedDarcyTest<64>;

/**
* @f[
* \Omega = [0,1]\times[0,1]
* @f]
*
* @f[
* p(x,y)=\sin(\pi x)\sin(\pi y)
* @f]
*
* @f[
* \mathbf{u}(x,y)=-\nabla p(x,y)
* = -\pi \begin{pmatrix}
* \cos(\pi x)\sin(\pi y) \\
* \sin(\pi x)\cos(\pi y)
* \end{pmatrix}
* @f]
*
*
* @f[
* f(x,y)=2\pi^2\sin(\pi x)\sin(\pi y)
* @f]
*
*/
TEST_P(ManufacturedDarcyTest16x16, Darcy_SimpleSine_P1)
{
auto pi = Math::Constants::pi();
Mesh mesh = this->getMesh();

// Flux space (vector-valued)
P1 uh(mesh, mesh.getSpaceDimension());

// Pressure space (scalar)
P1 ph(mesh);

// Manufactured solution:
auto p_exact = sin(pi * F::x) * sin(pi * F::y);
auto u_exact = -pi * VectorFunction{
cos(pi * F::x) * sin(pi * F::y),
sin(pi * F::x) * cos(pi * F::y)
};
auto f = 2 * pi * pi * sin(pi * F::x) * sin(pi * F::y);

// Define trial and test functions.
TrialFunction u(uh); // Flux trial function.
TrialFunction p(ph); // Pressure trial function.
TestFunction v(uh); // Flux test function.
TestFunction q(ph); // Pressure test function.

// Assemble the weak form:
Problem darcy(u, p, v, q);
darcy = Integral(u, v)
- Integral(p, Div(v))
- Integral(Div(u), q)
+ Integral(f, q)
+ DirichletBC(p, p_exact);

// Solve the system.
CG cg(darcy);
cg.setTolerance(1e-12);
cg.setMaxIterations(1000);
cg.solve();
std::cout << cg.success() << std::endl;

// Compute the L^2 error for pressure.
GridFunction diff_p(ph);
p.getSolution().save("p.gf");
mesh.save("mesh.mesh");
std::exit(1);
diff_p = Pow(p.getSolution() - p_exact, 2);
diff_p.setWeights();
Real error_p = Integral(diff_p).compute();

// Compute the L^2 error for flux.
GridFunction diff_u(ph);
diff_u = Pow(Frobenius(u.getSolution() - u_exact), 2);
diff_u.setWeights();
Real error_u = Integral(diff_u).compute();

EXPECT_NEAR(error_p, 0, RODIN_FUZZY_CONSTANT);
EXPECT_NEAR(error_u, 0, RODIN_FUZZY_CONSTANT);
}

INSTANTIATE_TEST_SUITE_P(
MeshParams16x16,
ManufacturedDarcyTest16x16,
::testing::Values(Polytope::Type::Quadrilateral, Polytope::Type::Triangle)
);
}

25 changes: 24 additions & 1 deletion tests/manufactured/Rodin/P1/Poisson.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright Carlos BRITO PACHECO 2021 - 2022.
* Copyright Carlos BRITO PACHECO 2021 - 2025.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE or copy at
* https://www.boost.org/LICENSE_1_0.txt)
Expand All @@ -17,6 +17,29 @@ using namespace Rodin::Variational;
using namespace Rodin::Solver;
using namespace Rodin::Test::Random;


/**
* @brief Manufactured solutions for the Poisson problem using P1 spaces.
*
* The system is given by:
* @f[
* \left\{
* \begin{aligned}
* -\Delta u &= f \quad \text{in } \Omega,\\
* u &= g \quad \text{on } \partial\Omega.
* \end{aligned}
* \right.
* @f]
*
* The weak formulation is: Find @f$ u \in V @f$ such that
* @f[
* \int_\Omega \nabla u \cdot \nabla v \,dx = \int_\Omega f \, v \,dx,
* @f]
* for all @f$ v \in V @f$, with the essential boundary condition
* @f[
* u = g \quad \text{on } \partial\Omega.
* @f]
*/
namespace Rodin::Tests::Manufactured::Poisson
{
template <size_t M>
Expand Down
Loading

0 comments on commit d2b35d4

Please sign in to comment.