From f9bf3b963f07c912088a3433a99f87722db92556 Mon Sep 17 00:00:00 2001
From: Matteo Cicuttin <datafl4sh@toxicnet.eu>
Date: Fri, 23 Apr 2021 22:08:33 +0200
Subject: [PATCH] saving stuff

---
 entity.cpp           |  31 +++++++++-
 physical_element.cpp |  13 ++--
 physical_element.h   |   1 +
 silo_output.hpp      |   5 ++
 test.cpp             |   2 +-
 test_lifting.cpp     | 144 ++++++++++++++++++++++++++++++++++++++-----
 6 files changed, 176 insertions(+), 20 deletions(-)

diff --git a/entity.cpp b/entity.cpp
index 1515448..361ebff 100644
--- a/entity.cpp
+++ b/entity.cpp
@@ -92,6 +92,13 @@ entity::project(const scalar_function& function) const
     return ret;
 }
 
+const reference_element&
+entity::cell_refelem(size_t iO) const
+{
+    assert(iO < reference_cells.size());
+    return reference_cells[iO];
+}
+
 const reference_element&
 entity::cell_refelem(const physical_element& pe) const
 {
@@ -458,7 +465,7 @@ entity::populate_lifting_matrices(entity_data_cpu& ed) const
 
             for (size_t i = 0; i < fnt.size(); i++)
                 for (size_t j = 0; j < cnt.size(); j++)
-                    if (cnt[j] == fnt[i])
+                    if (fnt[i] == cnt[j])
                     {
                         assert(f2c.size() == iF*num_face_bf + i);
                         f2c.push_back(j);
@@ -587,6 +594,28 @@ entity::populate_entity_data(entity_data_cpu& ed) const
             mass.inverse();
     }
 
+    ed.fluxdofs_mine.resize(4*ed.num_fluxes*num_cells());
+    for (size_t iT = 0; iT < num_cells(); iT++)
+    {
+        auto& pe = physical_cells[iT];
+        auto cell_keys = pe.bf_keys();
+
+        for (size_t iF = 0; iF < 4; iF++)
+        {
+            auto face_num = 4*iT+iF;
+            auto& pf = physical_faces[face_num];
+            auto face_keys = pf.bf_keys();
+
+            auto face_base = (4*iT + iF) * ed.num_fluxes;
+            auto cell_base = iT * ed.num_bf;
+
+            for (size_t i = 0; i < face_keys.size(); i++)
+                for (size_t j = 0; j < cell_keys.size(); j++)
+                    if ( face_keys.at(i) == cell_keys.at(j) )
+                        ed.fluxdofs_mine.at(face_base + i) = cell_base + j;
+        }
+    }
+
 }
 
 
diff --git a/physical_element.cpp b/physical_element.cpp
index 651a94b..5859b58 100644
--- a/physical_element.cpp
+++ b/physical_element.cpp
@@ -108,10 +108,11 @@ physical_element::jacobians(void) const
     return m_jacobians;
 }
 
-
-
-
-
+point_3d
+physical_element::barycenter(void) const
+{
+    return m_barycenter;
+}
 
 
 
@@ -127,6 +128,7 @@ physical_elements_factory::physical_elements_factory(const entity_params& ep)
     gmm::getBasisFunctionsOrientationForElements(elemType, basis_func_name(approx_order),
         cellOrientations, tag);
     assert(cellOrientations.size() == cellTags.size());
+    gmm::getBarycenters(elemType, tag, false, false, barycenters);
 
     std::vector<double>     coord;
     gmm::getKeysForElements(elemType, basis_func_name(approx_order),
@@ -161,6 +163,9 @@ physical_elements_factory::get_elements()
         new_pe.m_element_tag = cellTags[elem];
         new_pe.m_measure = 0.0;
         new_pe.m_gmsh_elemtype = elemType;
+        new_pe.m_barycenter = point_3d(barycenters[3*elem+0],
+                                       barycenters[3*elem+1],
+                                       barycenters[3*elem+2]);
 
         new_pe.m_bf_keys.resize(keys_per_elem);
         for (size_t i = 0; i < keys_per_elem; i++)
diff --git a/physical_element.h b/physical_element.h
index 1ee451e..4add250 100644
--- a/physical_element.h
+++ b/physical_element.h
@@ -92,6 +92,7 @@ class physical_elements_factory
     std::vector<double>     cellJacs;
     std::vector<double>     cellDets;
     std::vector<int>        cellOrientations;
+    std::vector<double>     barycenters;
     gmsh::vectorpair        keypairs;
     int                     keys_per_elem;
 
diff --git a/silo_output.hpp b/silo_output.hpp
index daac379..cfa006e 100644
--- a/silo_output.hpp
+++ b/silo_output.hpp
@@ -179,4 +179,9 @@ public:
 
         m_siloDb = nullptr;
     }
+
+    ~silo()
+    {
+        close_db();
+    }
 };
diff --git a/test.cpp b/test.cpp
index ed5506a..0fc9015 100644
--- a/test.cpp
+++ b/test.cpp
@@ -56,7 +56,7 @@ int main(void)
 #endif
 
     std::cout << Bmagentafg << " *** TESTING: LIFTING ***" << reset << std::endl;
-    for (size_t ao = 1; ao < 2; ao++)
+    for (size_t ao = 1; ao < 3; ao++)
             test_lifting(1, ao);
 
     gmsh::finalize();
diff --git a/test_lifting.cpp b/test_lifting.cpp
index 61158f1..154ccce 100644
--- a/test_lifting.cpp
+++ b/test_lifting.cpp
@@ -1,6 +1,6 @@
 #include <iostream>
 #include <iomanip>
-
+#include <sstream>
 #include <unistd.h>
 
 #include "test.h"
@@ -9,6 +9,7 @@
 #include "entity_data.h"
 #include "kernels_cpu.h"
 #include "timecounter.h"
+#include "silo_output.hpp"
 
 using namespace sgr;
 
@@ -25,6 +26,39 @@ make_geometry(int order, double mesh_h)
 }
 
 
+int test_lifting_xx(int geometric_order, int approximation_order)
+{
+    make_geometry(0, 0.25);
+    model mod(geometric_order, approximation_order);
+
+    auto& e0 = mod.entity_at(0);
+
+    entity_data_cpu ed;
+    e0.populate_entity_data(ed);
+
+    for (size_t iO = 0; iO < e0.num_cell_orientations(); iO++)
+    {
+        auto& re = e0.cell_refelem(iO);
+        auto num_bf = re.num_basis_functions();
+
+        auto lift_cols = ed.lifting_matrices.cols();
+
+        matxd mass = re.mass_matrix();
+        matxd curlift = mass * ed.lifting_matrices.block(iO*num_bf, 0, num_bf, lift_cols);
+
+        vecxd ones_cell = vecxd::Ones(num_bf);
+        vecxd ones_face = vecxd::Ones(lift_cols/4);
+
+        for (size_t iF = 0; iF < 4; iF++)
+        {
+            matxd liftblock = curlift.block(0,iF*lift_cols/4,num_bf,lift_cols/4);
+            std::cout << ones_cell.dot(liftblock*ones_face) << std::endl;
+        }
+    }
+
+    return 0;
+}
+
 int test_lifting(int geometric_order, int approximation_order)
 {
     std::vector<double> sizes({ 0.32, 0.16, 0.08, 0.04 });
@@ -34,14 +68,28 @@ int test_lifting(int geometric_order, int approximation_order)
     std::cout << ", approximation order = " << approximation_order << nofg;
     std::cout << std::endl;
 
-    auto F = [](const point_3d& pt) -> vecxd {
+    /* Test field */
+    auto Fx = [](const point_3d& pt) -> double {
+        return 1; //std::sin(M_PI*pt.x()); 
+    };
+
+    auto Fy = [](const point_3d& pt) -> double {
+        return 1; //std::sin(M_PI*pt.y());
+    };
+
+    auto Fz = [](const point_3d& pt) -> double {
+        return 1; //std::sin(M_PI*pt.z());
+    };
+
+    auto F = [&](const point_3d& pt) -> vecxd {
         vec3d Fret;
-        Fret(0) = std::sin(M_PI*pt.y());
-        Fret(1) = std::sin(M_PI*pt.z());
-        Fret(2) = std::sin(M_PI*pt.x());
+        Fret(0) = Fx(pt);
+        Fret(1) = Fy(pt);
+        Fret(2) = Fz(pt);
         return Fret;
     };
 
+    /* Expected divergence */
     auto div_F = [](const point_3d& pt) -> double {
         return 0;
         auto dFx_dx = M_PI*std::cos(M_PI*pt.x());
@@ -50,22 +98,61 @@ int test_lifting(int geometric_order, int approximation_order)
         return dFx_dx + dFy_dy + dFz_dz; 
     };
 
-    for (size_t i = 0; i < sizes.size(); i++)
+    for (size_t sz = 0; sz < sizes.size(); sz++)
     {
-        double h = sizes[i];
+        double h = sizes[sz];
         make_geometry(0,h);
         model mod(geometric_order, approximation_order);
 
+        std::stringstream ss;
+        ss << "lifting_test_" << sz << ".silo";
+
+        silo s;
+        s.create_db( ss.str() );
+        s.import_mesh_from_gmsh();
+        s.write_mesh();
+
         auto& e0 = mod.entity_at(0);
-        e0.sort_by_orientation();
 
         entity_data_cpu ed;
         e0.populate_entity_data(ed);
 
         vecxd exp_field = e0.project(div_F);
-        vecxd lift_field = vecxd::Zero( e0.num_cells() * ed.num_bf );
-        vecxd flux = vecxd::Zero( e0.num_cells() * 4*ed.num_fluxes );
+        vecxd Fx_proj = e0.project(Fx);
+        vecxd Fy_proj = e0.project(Fy);
+        vecxd Fz_proj = e0.project(Fz);
+
+        auto flx_size = e0.num_cells() * 4*ed.num_fluxes;
+        vecxd Fx_flux = vecxd::Zero( flx_size );
+        vecxd Fy_flux = vecxd::Zero( flx_size );
+        vecxd Fz_flux = vecxd::Zero( flx_size );
+
+        for (size_t i = 0; i < flx_size; i++)
+        {
+            Fx_flux(i) = Fx_proj( ed.fluxdofs_mine[i] );
+            Fy_flux(i) = Fy_proj( ed.fluxdofs_mine[i] );
+            Fz_flux(i) = Fz_proj( ed.fluxdofs_mine[i] );
+        }
+
+        vecxd flux = vecxd::Zero( flx_size );
 
+        for (size_t iT = 0; iT < e0.num_cells(); iT++)
+        {
+            for (size_t iF = 0; iF < 4; iF++)
+            {
+                vec3d n = ed.normals.row(4*iT+iF);
+                for (size_t k = 0; k < ed.num_fluxes; k++)
+                {
+                    auto dof_ofs = (4*iT+iF)*ed.num_fluxes + k;
+                    flux(dof_ofs) = Fx_flux(dof_ofs)*n(0) +
+                                    Fy_flux(dof_ofs)*n(1) +
+                                    Fz_flux(dof_ofs)*n(2);
+                }
+            }
+        }
+
+        vecxd lift_field = vecxd::Zero( e0.num_cells() * ed.num_bf );
+#if 0
         for (size_t iT = 0; iT < e0.num_cells(); iT++)
         {
             for (size_t iF = 0; iF < 4; iF++)
@@ -94,12 +181,19 @@ int test_lifting(int geometric_order, int approximation_order)
                 flux.segment(fluxofs, num_fluxes) = mass.ldlt().solve(rhs);
             }
         }
-        
+#endif   
         timecounter tc;
         tc.tic();
         compute_flux_lifting(ed, flux, lift_field);
         double time = tc.toc();
 
+        std::vector<double> var_div_F( e0.num_cells() );
+        std::vector<double> var_lift( e0.num_cells() );
+        std::vector<double> var_volp( e0.num_cells() );
+        std::vector<double> var_elift( e0.num_cells() );
+        std::vector<double> var_err( e0.num_cells() );
+        std::vector<double> var_orient( e0.num_cells() );
+
         double err = 0.0;
         for (size_t iT = 0; iT < e0.num_cells(); iT++)
         {
@@ -119,11 +213,33 @@ int test_lifting(int geometric_order, int approximation_order)
                 vol += pqp.weight() * dphi * F(pqp.point());
             }
 
-            vecxd comp_field = lift_field.segment(iT*num_bf, num_bf) - mass.ldlt().solve(vol);
-            vecxd diff = comp_field - exp_field.segment(iT*num_bf, num_bf);
-            err += diff.dot(mass*diff);
+            vecxd expected = exp_field.segment(iT*num_bf, num_bf);
+            vecxd lf = lift_field.segment(iT*num_bf, num_bf);
+            vecxd volp = mass.ldlt().solve(vol);
+
+            vecxd comp_field = lf - volp;
+            vecxd diff = comp_field - expected;
+            double loc_err = diff.dot(mass*diff);
+            err += loc_err;
+
+            auto bar = pe.barycenter();
+            vecxd phi_bar = re.basis_functions({1./3., 1./3., 1./3.});
+
+            var_div_F.at( pe.original_position() ) = expected.dot(phi_bar);
+            var_lift.at( pe.original_position() ) = lf.dot(phi_bar);
+            var_volp.at( pe.original_position() ) = volp.dot(phi_bar);
+            var_elift.at( pe.original_position() ) = (volp + expected).dot(phi_bar);
+            var_err.at( pe.original_position() ) = loc_err;
+            var_orient.at( pe.original_position() ) = pe.orientation();
         }
 
+        s.write_zonal_variable("div_F", var_div_F);
+        s.write_zonal_variable("lift", var_lift);
+        s.write_zonal_variable("vol", var_volp);
+        s.write_zonal_variable("exp_lift", var_elift);
+        s.write_zonal_variable("err", var_err);
+        s.write_zonal_variable("orient", var_orient);
+
         std::cout << std::sqrt(err) << std::endl;
 
         if (geometric_order == 1)
-- 
GitLab