Skip to content
Snippets Groups Projects
test_basics.cpp 4.83 KiB
Newer Older
Matteo Cicuttin's avatar
Matteo Cicuttin committed
#include <iostream>

#include <unistd.h>

#include "test.h"
#include "gmsh_io.h"
#include "sgr.hpp"

using namespace sgr;

static void
make_geometry(int order, double mesh_h)
{
    gm::add("test");

    std::vector<std::pair<int,int>> objects;
    objects.push_back(
        std::make_pair(3, gmo::addBox(0.0, 0.0, 0.0, 1.0, 1.0, 1.0) )
        );
    objects.push_back(
        std::make_pair(3, gmo::addSphere(0.5, 0.5, 0.5, SPHERE_RADIUS) )
        );

    std::vector<std::pair<int, int>> tools;
    gmsh::vectorpair odt;
    std::vector<gmsh::vectorpair> odtm;
    gmo::fragment(objects, tools, odt, odtm);

    gmo::synchronize();

    gvp_t vp;
    gm::getEntities(vp);
    gmm::setSize(vp, mesh_h);
}

int
test_basics(int geometric_order, int approximation_order)
{
    make_geometry(0, 0.1);

    model mod(geometric_order, approximation_order);

    auto idx = geometric_order - 1;

    std::cout << cyanfg << "Testing geometric order " << geometric_order;
    std::cout << ", approximation order = " << approximation_order << nofg;
    std::cout << std::endl;

    double vol_e0 = (4.0/3.0)*M_PI*SPHERE_RADIUS*SPHERE_RADIUS*SPHERE_RADIUS;
    double vol_e1 = 1.0 - vol_e0;

    /*****************************************/
    std::cout << yellowfg << "Volumes by reference quadrature points and determinants";
    std::cout << nofg << std::endl;
    std::vector<double> t1_vals { 0.07, 0.00145, 0.00024, 1.83e-5 };
    COMPARE_VALUES_RELATIVE("Entity 0 vol r+d", mod.entity_at(0).measure(), vol_e0, t1_vals[idx]);
    std::vector<double> t2_vals { 0.0024, 5.02e-5, 8.21e-06, 6.35e-7 };
    COMPARE_VALUES_RELATIVE("Entity 1 vol r+d", mod.entity_at(1).measure(), vol_e1, t2_vals[idx]);

    /*****************************************/
    std::cout << yellowfg << "Volumes by physical quadrature points" << nofg << std::endl;
    double vol_e0_pqp = 0.0;
    auto& e0 = mod.entity_at(0);
    for (const auto& e : e0)
    {
        const auto& pqps = e.integration_points();
        for (const auto& qp : pqps)
            vol_e0_pqp += qp.weight(); 
    }
    COMPARE_VALUES_RELATIVE("Entity 0 vol pqp", vol_e0_pqp, vol_e0, t1_vals[idx]);

    double vol_e1_pqp = 0.0;
    auto& e1 = mod.entity_at(1);
    for (const auto& e : e1)
    {
        const auto& pqps = e.integration_points();
        for (const auto& qp : pqps)
            vol_e1_pqp += qp.weight(); 
    }
    COMPARE_VALUES_RELATIVE("Entity 1 vol pqp", vol_e1_pqp, vol_e1, t2_vals[idx]);

    /*****************************************/
    std::cout << yellowfg << "Volumes by jacobians" << nofg << std::endl;
    double vol_e0_j = 0.0;
    for (const auto& e : e0)
    {
        const auto& js = e.jacobians();
        auto& re = e0.refelem(e);
        auto rqps = re.integration_points();
        auto dets = e.determinants();
        for (size_t i = 0; i < js.size(); i++)
        {
            double dj = js[i].determinant();
            double dg = dets[i];
            auto relerr = dj/dg - 1;
            assert( std::abs(relerr) < 3e-14 );
            vol_e0_j += dj*rqps[i].weight();
        }
    }
    COMPARE_VALUES_RELATIVE("Entity 0 vol j", vol_e0_j, vol_e0, t1_vals[idx]);

    double vol_e1_j = 0.0;
    for (const auto& e : e1)
    {
        const auto& js = e.jacobians();
        auto& re = e1.refelem(e);
        auto rqps = re.integration_points();
        auto dets = e.determinants();
        for (size_t i = 0; i < js.size(); i++)
        {
            double dj = js[i].determinant();
            double dg = dets[i];
            auto relerr = dj/dg - 1;
            assert( std::abs(relerr) < 3e-14 );
            vol_e1_j += dj*rqps[i].weight();
        }
    }
    COMPARE_VALUES_RELATIVE("Entity 1 vol j", vol_e1_j, vol_e1, t2_vals[idx]);

    /*****************************************/
    std::cout << yellowfg << "Volumes by integrating f(x) = 1 over the domain";
    std::cout << nofg << std::endl;
    double vol_e0_mass = 0.0;
    auto f = [](const point_3d& pt) -> double { return 1; };
    vecxd f_e0 = e0.project(f);
    for (size_t iT = 0; iT < e0.num_elements(); iT++)
    {
        auto& pe = e0.elem(iT);
        auto& re = e0.refelem(pe);
        auto num_bf = re.num_basis_functions();
        matxd mass = e0.mass_matrix(iT);
        vecxd f_pe = f_e0.segment(num_bf*iT, num_bf);
        vol_e0_mass += f_pe.transpose() * mass * f_pe;
    }
    COMPARE_VALUES_RELATIVE("Entity 0 vol mass", vol_e0_mass, vol_e0, t1_vals[idx]);

    double vol_e1_mass = 0.0;
    vecxd f_e1 = e1.project(f);
    for (size_t iT = 0; iT < e1.num_elements(); iT++)
    {
        auto& pe = e1.elem(iT);
        auto& re = e1.refelem(pe);
        auto num_bf = re.num_basis_functions();
        matxd mass = e1.mass_matrix(iT);
        vecxd f_pe = f_e1.segment(num_bf*iT, num_bf);
        vol_e1_mass += f_pe.transpose() * mass * f_pe;
    }
    COMPARE_VALUES_RELATIVE("Entity 1 vol mass", vol_e1_mass, vol_e1, t2_vals[idx]);

    return 0;
}