#include "quadrature/tetrahedron/tetrahedron_jinyun.hpp"

#include <algorithm>

namespace neon
{
tetrahedron_jinyun::tetrahedron_jinyun(int const minimum_degree)
{
    switch (minimum_degree)
    {
        case 1:
        {
            m_degree = 1;
            m_weights = {1.0};
            m_coordinates = {{0, 0.25, 0.25, 0.25}};
            break;
        }
        case 2:
        {
            m_degree = 2;
            m_weights = {0.25, 0.25, 0.25, 0.25};
            constexpr auto c0 = 0.585410196624969;
            constexpr auto c1 = 0.138196601125011;
            m_coordinates = {{0, c0, c1, c1}, {1, c1, c0, c1}, {2, c1, c1, c0}, {3, c1, c1, c1}};
            break;
        }
        case 3:
        {
            m_degree = 3;
            m_weights = {-4.0 / 5.0, 9.0 / 20.0, 9.0 / 20.0, 9.0 / 20.0, 9.0 / 20.0};
            m_coordinates = {{0, 0.25, 0.25, 0.25},
                             {1, 0.5, 1.0 / 6.0, 1.0 / 6.0},
                             {2, 1.0 / 6.0, 0.5, 1.0 / 6.0},
                             {3, 1.0 / 6.0, 1.0 / 6.0, 0.5},
                             {4, 1.0 / 6.0, 1.0 / 6.0, 1.0 / 6.0}};
            break;
        }
        case 4:
        {
            m_degree = 4;
            m_weights = {0.05037379410012282,
                         0.05037379410012282,
                         0.05037379410012282,
                         0.05037379410012282,
                         0.06654206863329239,
                         0.06654206863329239,
                         0.06654206863329239,
                         0.06654206863329239,
                         0.06654206863329239,
                         0.06654206863329239,
                         0.06654206863329239,
                         0.06654206863329239,
                         0.06654206863329239,
                         0.06654206863329239,
                         0.06654206863329239,
                         0.06654206863329239};

            m_coordinates = {{0, 0.0761190326442543, 0.0761190326442543, 0.7716429020672371},
                             {1, 0.0761190326442543, 0.7716429020672371, 0.0761190326442543},
                             {2, 0.7716429020672371, 0.0761190326442543, 0.0761190326442543},
                             {3, 0.0761190326442543, 0.0761190326442543, 0.0761190326442543},
                             {4, 0.4042339134672644, 0.1197005277978019, 0.07183164526766932},
                             {5, 0.1197005277978019, 0.4042339134672644, 0.07183164526766932},
                             {6, 0.4042339134672644, 0.4042339134672644, 0.07183164526766932},
                             {7, 0.1197005277978019, 0.07183164526766932, 0.4042339134672644},
                             {8, 0.4042339134672644, 0.07183164526766932, 0.4042339134672644},
                             {9, 0.07183164526766932, 0.4042339134672644, 0.4042339134672644},
                             {10, 0.4042339134672644, 0.07183164526766932, 0.1197005277978019},
                             {11, 0.07183164526766932, 0.4042339134672644, 0.1197005277978019},
                             {12, 0.4042339134672644, 0.4042339134672644, 0.1197005277978019},
                             {13, 0.07183164526766932, 0.1197005277978019, 0.4042339134672644},
                             {14, 0.4042339134672644, 0.1197005277978019, 0.4042339134672644},
                             {15, 0.1197005277978019, 0.4042339134672644, 0.4042339134672644}};
            break;
        }
        case 5:
        {
            m_degree = 5;
            m_weights = {0.1884185567365411,
                         0.06703858372604275,
                         0.06703858372604275,
                         0.06703858372604275,
                         0.06703858372604275,
                         0.04528559236327399,
                         0.04528559236327399,
                         0.04528559236327399,
                         0.04528559236327399,
                         0.04528559236327399,
                         0.04528559236327399,
                         0.04528559236327399,
                         0.04528559236327399,
                         0.04528559236327399,
                         0.04528559236327399,
                         0.04528559236327399,
                         0.04528559236327399};

            m_coordinates = {{0, 0.25, 0.25, 0.25},
                             {1, 0.08945436401412733, 0.08945436401412733, 0.7316369079576179},
                             {2, 0.08945436401412733, 0.7316369079576179, 0.08945436401412733},
                             {3, 0.7316369079576179, 0.08945436401412733, 0.08945436401412733},
                             {4, 0.08945436401412733, 0.08945436401412733, 0.08945436401412733},
                             {5, 0.4214394310662522, 0.1325810999384657, 0.024540037929029895},
                             {6, 0.1325810999384657, 0.4214394310662522, 0.024540037929029895},
                             {7, 0.4214394310662522, 0.4214394310662522, 0.024540037929029895},
                             {8, 0.1325810999384657, 0.024540037929029895, 0.4214394310662522},
                             {9, 0.4214394310662522, 0.024540037929029895, 0.4214394310662522},
                             {10, 0.024540037929029895, 0.4214394310662522, 0.4214394310662522},
                             {11, 0.4214394310662522, 0.024540037929029895, 0.1325810999384657},
                             {12, 0.024540037929029895, 0.4214394310662522, 0.1325810999384657},
                             {13, 0.4214394310662522, 0.4214394310662522, 0.1325810999384657},
                             {14, 0.024540037929029895, 0.1325810999384657, 0.4214394310662522},
                             {15, 0.4214394310662522, 0.1325810999384657, 0.4214394310662522},
                             {16, 0.1325810999384657, 0.4214394310662522, 0.4214394310662522}};
        }
        case 6:
        {
            m_degree = 6;

            m_weights = {0.0904012904601475,  0.01911983427899124, 0.01911983427899124,
                         0.01911983427899124, 0.01911983427899124, 0.04361493840666568,
                         0.02581167596199161, 0.04361493840666568, 0.02581167596199161,
                         0.04361493840666568, 0.02581167596199161, 0.04361493840666568,
                         0.02581167596199161, 0.04361493840666568, 0.02581167596199161,
                         0.04361493840666568, 0.02581167596199161, 0.04361493840666568,
                         0.02581167596199161, 0.04361493840666568, 0.02581167596199161,
                         0.04361493840666568, 0.02581167596199161, 0.04361493840666568,
                         0.02581167596199161, 0.04361493840666568, 0.02581167596199161,
                         0.04361493840666568, 0.02581167596199161};

            m_coordinates = {{0, 0.25, 0.25, 0.25},
                             {1, 0.05742691731735682, 0.05742691731735682, 0.8277192480479295},
                             {2, 0.05742691731735682, 0.8277192480479295, 0.05742691731735682},
                             {3, 0.8277192480479295, 0.05742691731735682, 0.05742691731735682},
                             {4, 0.05742691731735682, 0.05742691731735682, 0.05742691731735682},
                             {5, 0.2312985436519147, 0.05135188412556341, 0.48605102857060717},
                             {6, 0.0475690988147229, 0.296753812969026, 0.6081079894015282},
                             {7, 0.05135188412556341, 0.2312985436519147, 0.48605102857060717},
                             {8, 0.296753812969026, 0.0475690988147229, 0.6081079894015282},
                             {9, 0.2312985436519147, 0.2312985436519147, 0.48605102857060717},
                             {10, 0.0475690988147229, 0.0475690988147229, 0.6081079894015282},
                             {11, 0.05135188412556341, 0.48605102857060717, 0.2312985436519147},
                             {12, 0.296753812969026, 0.6081079894015282, 0.0475690988147229},
                             {13, 0.2312985436519147, 0.48605102857060717, 0.2312985436519147},
                             {14, 0.0475690988147229, 0.6081079894015282, 0.0475690988147229},
                             {15, 0.48605102857060717, 0.2312985436519147, 0.2312985436519147},
                             {16, 0.6081079894015282, 0.0475690988147229, 0.0475690988147229},
                             {17, 0.2312985436519147, 0.48605102857060717, 0.05135188412556341},
                             {18, 0.0475690988147229, 0.6081079894015282, 0.296753812969026},
                             {19, 0.48605102857060717, 0.2312985436519147, 0.05135188412556341},
                             {20, 0.6081079894015282, 0.0475690988147229, 0.296753812969026},
                             {21, 0.2312985436519147, 0.2312985436519147, 0.05135188412556341},
                             {22, 0.0475690988147229, 0.0475690988147229, 0.296753812969026},
                             {23, 0.48605102857060717, 0.05135188412556341, 0.2312985436519147},
                             {24, 0.6081079894015282, 0.296753812969026, 0.0475690988147229},
                             {25, 0.2312985436519147, 0.05135188412556341, 0.2312985436519147},
                             {26, 0.0475690988147229, 0.296753812969026, 0.0475690988147229},
                             {27, 0.05135188412556341, 0.2312985436519147, 0.2312985436519147},
                             {28, 0.296753812969026, 0.0475690988147229, 0.0475690988147229}};
        }
        default:
        {
            throw std::domain_error("This is not the scheme you are looking for.");
        }
    }

    std::transform(begin(m_weights), end(m_weights), begin(m_weights), [](auto const weight) {
        return weight / 6.0;
    });
}
}

#include "quadrature/tetrahedron/tetrahedron_jinyun.hpp"

#include <algorithm>

namespace neon
{
tetrahedron_jinyun::tetrahedron_jinyun(int const minimum_degree)
{
    switch (minimum_degree)
    {
        case 1:
        {
            m_degree = 1;
            m_weights = {1.0};
            m_coordinates = {{0, 0.25, 0.25, 0.25}};
            break;
        }
        case 2:
        {
            m_degree = 2;
            m_weights = {0.25, 0.25, 0.25, 0.25};
            constexpr auto c0 = 0.585410196624969;
            constexpr auto c1 = 0.138196601125011;
            m_coordinates = {{0, c0, c1, c1}, {1, c1, c0, c1}, {2, c1, c1, c0}, {3, c1, c1, c1}};
            break;
        }
        case 3:
        {
            m_degree = 3;
            m_weights = {-4.0 / 5.0, 9.0 / 20.0, 9.0 / 20.0, 9.0 / 20.0, 9.0 / 20.0};
            m_coordinates = {{0, 0.25, 0.25, 0.25},
                             {1, 0.5, 1.0 / 6.0, 1.0 / 6.0},
                             {2, 1.0 / 6.0, 0.5, 1.0 / 6.0},
                             {3, 1.0 / 6.0, 1.0 / 6.0, 0.5},
                             {4, 1.0 / 6.0, 1.0 / 6.0, 1.0 / 6.0}};
            break;
        }
        case 4:
        {
            m_degree = 4;
            m_weights = {0.05037379410012282,
                         0.05037379410012282,
                         0.05037379410012282,
                         0.05037379410012282,
                         0.06654206863329239,
                         0.06654206863329239,
                         0.06654206863329239,
                         0.06654206863329239,
                         0.06654206863329239,
                         0.06654206863329239,
                         0.06654206863329239,
                         0.06654206863329239,
                         0.06654206863329239,
                         0.06654206863329239,
                         0.06654206863329239,
                         0.06654206863329239};

            m_coordinates = {{0, 0.0761190326442543, 0.0761190326442543, 0.7716429020672371},
                             {1, 0.0761190326442543, 0.7716429020672371, 0.0761190326442543},
                             {2, 0.7716429020672371, 0.0761190326442543, 0.0761190326442543},
                             {3, 0.0761190326442543, 0.0761190326442543, 0.0761190326442543},
                             {4, 0.4042339134672644, 0.1197005277978019, 0.07183164526766932},
                             {5, 0.1197005277978019, 0.4042339134672644, 0.07183164526766932},
                             {6, 0.4042339134672644, 0.4042339134672644, 0.07183164526766932},
                             {7, 0.1197005277978019, 0.07183164526766932, 0.4042339134672644},
                             {8, 0.4042339134672644, 0.07183164526766932, 0.4042339134672644},
                             {9, 0.07183164526766932, 0.4042339134672644, 0.4042339134672644},
                             {10, 0.4042339134672644, 0.07183164526766932, 0.1197005277978019},
                             {11, 0.07183164526766932, 0.4042339134672644, 0.1197005277978019},
                             {12, 0.4042339134672644, 0.4042339134672644, 0.1197005277978019},
                             {13, 0.07183164526766932, 0.1197005277978019, 0.4042339134672644},
                             {14, 0.4042339134672644, 0.1197005277978019, 0.4042339134672644},
                             {15, 0.1197005277978019, 0.4042339134672644, 0.4042339134672644}};
            break;
        }
        case 5:
        {
            m_degree = 5;
            m_weights = {0.1884185567365411,
                         0.06703858372604275,
                         0.06703858372604275,
                         0.06703858372604275,
                         0.06703858372604275,
                         0.04528559236327399,
                         0.04528559236327399,
                         0.04528559236327399,
                         0.04528559236327399,
                         0.04528559236327399,
                         0.04528559236327399,
                         0.04528559236327399,
                         0.04528559236327399,
                         0.04528559236327399,
                         0.04528559236327399,
                         0.04528559236327399,
                         0.04528559236327399};

            m_coordinates = {{0, 0.25, 0.25, 0.25},
                             {1, 0.08945436401412733, 0.08945436401412733, 0.7316369079576179},
                             {2, 0.08945436401412733, 0.7316369079576179, 0.08945436401412733},
                             {3, 0.7316369079576179, 0.08945436401412733, 0.08945436401412733},
                             {4, 0.08945436401412733, 0.08945436401412733, 0.08945436401412733},
                             {5, 0.4214394310662522, 0.1325810999384657, 0.024540037929029895},
                             {6, 0.1325810999384657, 0.4214394310662522, 0.024540037929029895},
                             {7, 0.4214394310662522, 0.4214394310662522, 0.024540037929029895},
                             {8, 0.1325810999384657, 0.024540037929029895, 0.4214394310662522},
                             {9, 0.4214394310662522, 0.024540037929029895, 0.4214394310662522},
                             {10, 0.024540037929029895, 0.4214394310662522, 0.4214394310662522},
                             {11, 0.4214394310662522, 0.024540037929029895, 0.1325810999384657},
                             {12, 0.024540037929029895, 0.4214394310662522, 0.1325810999384657},
                             {13, 0.4214394310662522, 0.4214394310662522, 0.1325810999384657},
                             {14, 0.024540037929029895, 0.1325810999384657, 0.4214394310662522},
                             {15, 0.4214394310662522, 0.1325810999384657, 0.4214394310662522},
                             {16, 0.1325810999384657, 0.4214394310662522, 0.4214394310662522}};
        }
        case 6:
        {
            m_degree = 6;

            m_weights = {0.0904012904601475,  0.01911983427899124, 0.01911983427899124,
                         0.01911983427899124, 0.01911983427899124, 0.04361493840666568,
                         0.02581167596199161, 0.04361493840666568, 0.02581167596199161,
                         0.04361493840666568, 0.02581167596199161, 0.04361493840666568,
                         0.02581167596199161, 0.04361493840666568, 0.02581167596199161,
                         0.04361493840666568, 0.02581167596199161, 0.04361493840666568,
                         0.02581167596199161, 0.04361493840666568, 0.02581167596199161,
                         0.04361493840666568, 0.02581167596199161, 0.04361493840666568,
                         0.02581167596199161, 0.04361493840666568, 0.02581167596199161,
                         0.04361493840666568, 0.02581167596199161};

            m_coordinates = {{0, 0.25, 0.25, 0.25},
                             {1, 0.05742691731735682, 0.05742691731735682, 0.8277192480479295},
                             {2, 0.05742691731735682, 0.8277192480479295, 0.05742691731735682},
                             {3, 0.8277192480479295, 0.05742691731735682, 0.05742691731735682},
                             {4, 0.05742691731735682, 0.05742691731735682, 0.05742691731735682},
                             {5, 0.2312985436519147, 0.05135188412556341, 0.48605102857060717},
                             {6, 0.0475690988147229, 0.296753812969026, 0.6081079894015282},
                             {7, 0.05135188412556341, 0.2312985436519147, 0.48605102857060717},
                             {8, 0.296753812969026, 0.0475690988147229, 0.6081079894015282},
                             {9, 0.2312985436519147, 0.2312985436519147, 0.48605102857060717},
                             {10, 0.0475690988147229, 0.0475690988147229, 0.6081079894015282},
                             {11, 0.05135188412556341, 0.48605102857060717, 0.2312985436519147},
                             {12, 0.296753812969026, 0.6081079894015282, 0.0475690988147229},
                             {13, 0.2312985436519147, 0.48605102857060717, 0.2312985436519147},
                             {14, 0.0475690988147229, 0.6081079894015282, 0.0475690988147229},
                             {15, 0.48605102857060717, 0.2312985436519147, 0.2312985436519147},
                             {16, 0.6081079894015282, 0.0475690988147229, 0.0475690988147229},
                             {17, 0.2312985436519147, 0.48605102857060717, 0.05135188412556341},
                             {18, 0.0475690988147229, 0.6081079894015282, 0.296753812969026},
                             {19, 0.48605102857060717, 0.2312985436519147, 0.05135188412556341},
                             {20, 0.6081079894015282, 0.0475690988147229, 0.296753812969026},
                             {21, 0.2312985436519147, 0.2312985436519147, 0.05135188412556341},
                             {22, 0.0475690988147229, 0.0475690988147229, 0.296753812969026},
                             {23, 0.48605102857060717, 0.05135188412556341, 0.2312985436519147},
                             {24, 0.6081079894015282, 0.296753812969026, 0.0475690988147229},
                             {25, 0.2312985436519147, 0.05135188412556341, 0.2312985436519147},
                             {26, 0.0475690988147229, 0.296753812969026, 0.0475690988147229},
                             {27, 0.05135188412556341, 0.2312985436519147, 0.2312985436519147},
                             {28, 0.296753812969026, 0.0475690988147229, 0.0475690988147229}};
        }
        default:
        {
            throw std::domain_error("This is not the scheme you are looking for.");
        }
    }

    // Convert the weightings to proper quadrature format
    std::transform(begin(m_weights), end(m_weights), begin(m_weights), [](auto const weight) {
        return weight / 6.0;
    });
}
}
