Skip to content
Snippets Groups Projects
Select Git revision
  • 6a9f3e72ac873cacaa2ecfe5e980a9141f548239
  • develop default protected
  • save_clemence
  • feature/composite-scheme-other-fluxes
  • feature/advection
  • origin/stage/bouguettaia
  • feature/local-dt-fsi
  • feature/variational-hydro
  • feature/gmsh-reader
  • feature/reconstruction
  • feature/kinetic-schemes
  • feature/composite-scheme-sources
  • feature/serraille
  • feature/composite-scheme
  • hyperplastic
  • feature/polynomials
  • feature/gks
  • feature/implicit-solver-o2
  • feature/coupling_module
  • feature/implicit-solver
  • feature/merge-local-dt-fsi
  • v0.5.0 protected
  • v0.4.1 protected
  • v0.4.0 protected
  • v0.3.0 protected
  • v0.2.0 protected
  • v0.1.0 protected
  • Kidder
  • v0.0.4 protected
  • v0.0.3 protected
  • v0.0.2 protected
  • v0 protected
  • v0.0.1 protected
33 results

test_CubeTransformation.cpp

Blame
  • Stéphane Del Pino's avatar
    Stéphane Del Pino authored
    It avoids some spurious automatic conversion (especially from
    arithmetic types to TinyVector<1> or TinyMatrix<1>) and could reduce
    stress on the compiler.
    47096170
    History
    test_CubeTransformation.cpp 9.60 KiB
    #include <catch2/catch_approx.hpp>
    #include <catch2/catch_test_macros.hpp>
    
    #include <analysis/GaussLegendreQuadratureDescriptor.hpp>
    #include <analysis/GaussLobattoQuadratureDescriptor.hpp>
    #include <analysis/GaussQuadratureDescriptor.hpp>
    #include <analysis/QuadratureManager.hpp>
    #include <geometry/CubeTransformation.hpp>
    
    // clazy:excludeall=non-pod-global-static
    
    TEST_CASE("CubeTransformation", "[geometry]")
    {
      using R3 = TinyVector<3>;
    
      SECTION("invertible transformation")
      {
        const R3 a_hat{-1, -1, -1};
        const R3 b_hat{+1, -1, -1};
        const R3 c_hat{+1, +1, -1};
        const R3 d_hat{-1, +1, -1};
        const R3 e_hat{-1, -1, +1};
        const R3 f_hat{+1, -1, +1};
        const R3 g_hat{+1, +1, +1};
        const R3 h_hat{-1, +1, +1};
    
        const R3 m_hat = zero;
    
        const R3 a{0, 0, 0};
        const R3 b{3, 1, 3};
        const R3 c{2, 5, 2};
        const R3 d{0, 3, 1};
        const R3 e{1, 2, 5};
        const R3 f{3, 1, 7};
        const R3 g{2, 5, 5};
        const R3 h{0, 3, 6};
    
        const R3 m = 0.125 * (a + b + c + d + e + f + g + h);
    
        const CubeTransformation t(a, b, c, d, e, f, g, h);
    
        SECTION("values")
        {
          REQUIRE(l2Norm(t(a_hat) - a) == Catch::Approx(0));
          REQUIRE(l2Norm(t(b_hat) - b) == Catch::Approx(0));
          REQUIRE(l2Norm(t(c_hat) - c) == Catch::Approx(0));
          REQUIRE(l2Norm(t(d_hat) - d) == Catch::Approx(0));
          REQUIRE(l2Norm(t(e_hat) - e) == Catch::Approx(0));
          REQUIRE(l2Norm(t(f_hat) - f) == Catch::Approx(0));
          REQUIRE(l2Norm(t(g_hat) - g) == Catch::Approx(0));
          REQUIRE(l2Norm(t(h_hat) - h) == Catch::Approx(0));
    
          REQUIRE(l2Norm(t(m_hat) - m) == Catch::Approx(0));
        }
    
        SECTION("Jacobian determinant")
        {
          SECTION("at points")
          {
            auto detJ = [](const R3& X) {
              const double x = X[0];
              const double y = X[1];
              const double z = X[2];
    
              return -(3 * x * y * y * z + 9 * y * y * z - 6 * x * x * y * z + 6 * x * y * z - 96 * y * z + 14 * x * x * z -
                       49 * x * z + 119 * z - 21 * x * y * y + 21 * y * y + 90 * x * y - 10 * y + 40 * x * x - 109 * x -
                       491) /
                     128;
            };
    
            REQUIRE(t.jacobianDeterminant(a_hat) == Catch::Approx(detJ(a_hat)));
            REQUIRE(t.jacobianDeterminant(b_hat) == Catch::Approx(detJ(b_hat)));
            REQUIRE(t.jacobianDeterminant(c_hat) == Catch::Approx(detJ(c_hat)));
            REQUIRE(t.jacobianDeterminant(d_hat) == Catch::Approx(detJ(d_hat)));
            REQUIRE(t.jacobianDeterminant(e_hat) == Catch::Approx(detJ(e_hat)));
            REQUIRE(t.jacobianDeterminant(f_hat) == Catch::Approx(detJ(f_hat)));
            REQUIRE(t.jacobianDeterminant(g_hat) == Catch::Approx(detJ(g_hat)));
            REQUIRE(t.jacobianDeterminant(h_hat) == Catch::Approx(detJ(h_hat)));
    
            REQUIRE(t.jacobianDeterminant(m_hat) == Catch::Approx(detJ(m_hat)));
          }
    
          SECTION("Gauss order 3")
          {
            // The jacobian determinant is of maximal degree 2 in each variable
            const QuadratureFormula<3>& gauss =
              QuadratureManager::instance().getCubeFormula(GaussLegendreQuadratureDescriptor(2));
    
            double volume = 0;
            for (size_t i = 0; i < gauss.numberOfPoints(); ++i) {
              volume += gauss.weight(i) * t.jacobianDeterminant(gauss.point(i));
            }
    
            // 353. / 12 is actually the volume of the hexahedron
            REQUIRE(volume == Catch::Approx(353. / 12));
          }
    
          auto p = [](const R3& X) {
            const double& x = X[0];
            const double& y = X[1];
            const double& z = X[2];
    
            return 2 * x * x + 3 * y * z + z * z + 2 * x - 3 * y + 0.5 * z + 3;
          };
    
          SECTION("Gauss order 6")
          {
            // Jacbian determinant is a degree 2 polynomial, so the
            // following formula is required to reach exactness
            const QuadratureFormula<3>& gauss = QuadratureManager::instance().getCubeFormula(GaussQuadratureDescriptor(6));
    
            double integral = 0;
            for (size_t i = 0; i < gauss.numberOfPoints(); ++i) {
              integral += gauss.weight(i) * t.jacobianDeterminant(gauss.point(i)) * p(t(gauss.point(i)));
            }
    
            REQUIRE(integral == Catch::Approx(488879. / 360));
          }
    
          SECTION("Gauss-Legendre order 4")
          {
            // Jacbian determinant is a degree 2 polynomial, so the
            // following formula is required to reach exactness
            const QuadratureFormula<3>& gauss =
              QuadratureManager::instance().getCubeFormula(GaussLegendreQuadratureDescriptor(4));
    
            double integral = 0;
            for (size_t i = 0; i < gauss.numberOfPoints(); ++i) {
              integral += gauss.weight(i) * t.jacobianDeterminant(gauss.point(i)) * p(t(gauss.point(i)));
            }
    
            REQUIRE(integral == Catch::Approx(488879. / 360));
          }
    
          SECTION("Gauss-Lobatto order 4")
          {
            // Jacbian determinant is a degree 2 polynomial, so the
            // following formula is required to reach exactness
            const QuadratureFormula<3>& gauss =
              QuadratureManager::instance().getCubeFormula(GaussLobattoQuadratureDescriptor(4));
    
            double integral = 0;
            for (size_t i = 0; i < gauss.numberOfPoints(); ++i) {
              integral += gauss.weight(i) * t.jacobianDeterminant(gauss.point(i)) * p(t(gauss.point(i)));
            }
    
            REQUIRE(integral == Catch::Approx(488879. / 360));
          }
        }
      }
    
      SECTION("degenerate to tetrahedron")
      {
        using R3 = TinyVector<3>;
    
        const R3 a{1, 2, 1};
        const R3 b{3, 1, 3};
        const R3 c{2, 5, 2};
        const R3 d{2, 3, 4};
    
        const CubeTransformation t(a, b, c, c, d, d, d, d);
    
        auto p = [](const R3& X) {
          const double x = X[0];
          const double y = X[1];
          const double z = X[2];
          return 2 * x * x + 3 * x * y + y * y + 3 * y - z * z + 2 * x * z + 2 * z;
        };
    
        SECTION("Polynomial Gauss integral")
        {
          QuadratureFormula<3> qf = QuadratureManager::instance().getCubeFormula(GaussQuadratureDescriptor(6));
    
          double sum = 0;
          for (size_t i = 0; i < qf.numberOfPoints(); ++i) {
            const R3 xi = qf.point(i);
            sum += qf.weight(i) * t.jacobianDeterminant(xi) * p(t(xi));
          }
    
          REQUIRE(sum == Catch::Approx(231. / 2));
        }
    
        SECTION("Polynomial Gauss-Lobatto integral")
        {
          QuadratureFormula<3> qf = QuadratureManager::instance().getCubeFormula(GaussLobattoQuadratureDescriptor(4));
    
          double sum = 0;
          for (size_t i = 0; i < qf.numberOfPoints(); ++i) {
            const R3 xi = qf.point(i);
            sum += qf.weight(i) * t.jacobianDeterminant(xi) * p(t(xi));
          }
    
          REQUIRE(sum == Catch::Approx(231. / 2));
        }
    
        SECTION("Polynomial Gauss-Legendre integral")
        {
          QuadratureFormula<3> qf = QuadratureManager::instance().getCubeFormula(GaussLegendreQuadratureDescriptor(4));
    
          double sum = 0;
          for (size_t i = 0; i < qf.numberOfPoints(); ++i) {
            const R3 xi = qf.point(i);
            sum += qf.weight(i) * t.jacobianDeterminant(xi) * p(t(xi));
          }
    
          REQUIRE(sum == Catch::Approx(231. / 2));
        }
      }
    
      SECTION("degenerate to prism")
      {
        const R3 a{1, 2, 0};
        const R3 b{3, 1, 3};
        const R3 c{2, 5, 2};
        const R3 d{0, 3, 1};
        const R3 e{1, 2, 5};
        const R3 f{3, 1, 7};
    
        const CubeTransformation t(a, b, c, c, d, e, f, f);
    
        auto p = [](const R3& X) {
          const double x = X[0];
          const double y = X[1];
          const double z = X[2];
    
          return 3 * x * x + 2 * y * y + 3 * z * z + 4 * x + 3 * y + 2 * z + 1;
        };
    
        SECTION("Polynomial Gauss integral")
        {
          // 8 is the minimum quadrature rule to integrate the polynomial
          // on the prism due to the jacobian determinant expression
          const QuadratureFormula<3>& gauss = QuadratureManager::instance().getCubeFormula(GaussQuadratureDescriptor(8));
    
          double integral = 0;
          for (size_t i = 0; i < gauss.numberOfPoints(); ++i) {
            integral += gauss.weight(i) * t.jacobianDeterminant(gauss.point(i)) * p(t(gauss.point(i)));
          }
    
          REQUIRE(integral == Catch::Approx(30377. / 90));
        }
    
        SECTION("Polynomial Gauss-Legendre integral")
        {
          const QuadratureFormula<3>& gauss =
            QuadratureManager::instance().getCubeFormula(GaussLegendreQuadratureDescriptor(4));
    
          double integral = 0;
          for (size_t i = 0; i < gauss.numberOfPoints(); ++i) {
            integral += gauss.weight(i) * t.jacobianDeterminant(gauss.point(i)) * p(t(gauss.point(i)));
          }
    
          REQUIRE(integral == Catch::Approx(30377. / 90));
        }
    
        SECTION("Polynomial Gauss-Lobatto integral")
        {
          const QuadratureFormula<3>& gauss =
            QuadratureManager::instance().getCubeFormula(GaussLobattoQuadratureDescriptor(4));
    
          double integral = 0;
          for (size_t i = 0; i < gauss.numberOfPoints(); ++i) {
            integral += gauss.weight(i) * t.jacobianDeterminant(gauss.point(i)) * p(t(gauss.point(i)));
          }
    
          REQUIRE(integral == Catch::Approx(30377. / 90));
        }
      }
    
      SECTION("degenerate to pyramid")
      {
        const R3 a{1, 2, 0};
        const R3 b{3, 1, 3};
        const R3 c{2, 5, 2};
        const R3 d{0, 3, 1};
        const R3 e{1, 2, 5};
    
        const CubeTransformation t(a, b, c, d, e, e, e, e);
    
        auto p = [](const R3& X) {
          const double x = X[0];
          const double y = X[1];
          const double z = X[2];
    
          return 3 * x * x + 2 * y * y + 3 * z * z + 4 * x + 3 * y + 2 * z + 1;
        };
    
        // 4 is the minimum quadrature rule to integrate the polynomial on the pyramid
        const QuadratureFormula<3>& gauss =
          QuadratureManager::instance().getCubeFormula(GaussLegendreQuadratureDescriptor(20));
        double integral = 0;
        for (size_t i = 0; i < gauss.numberOfPoints(); ++i) {
          integral += gauss.weight(i) * t.jacobianDeterminant(gauss.point(i)) * p(t(gauss.point(i)));
        }
    
        REQUIRE(integral == Catch::Approx(7238. / 15));
      }
    }