Skip to content
Snippets Groups Projects
Commit 0c50ab25 authored by Matteo Cicuttin's avatar Matteo Cicuttin
Browse files

Updated lifting test to handle multiple entities.

parent 5ada2d11
No related branches found
No related tags found
No related merge requests found
...@@ -202,17 +202,7 @@ void compute_lifting_kernel_planar(const entity_data_cpu& ed, ...@@ -202,17 +202,7 @@ void compute_lifting_kernel_planar(const entity_data_cpu& ed,
size_t flux_ofs = flux_base + 4*iT*KS::num_fluxes; size_t flux_ofs = flux_base + 4*iT*KS::num_fluxes;
auto inv_det = 1./ed.cell_determinants[orient_elem_base+iT]; auto inv_det = 1./ed.cell_determinants[orient_elem_base+iT];
for (size_t i = 0; i < KS::num_bf; i++) field.segment<KS::num_bf>(dof_ofs) += (inv_det) * ed.lifting_matrices.block<KS::num_bf, 4*KS::num_fluxes>(iO*KS::num_bf, 0) * flux.segment<4*KS::num_fluxes>(flux_ofs);
{
auto facc = field(dof_ofs+i);
for (size_t iF = 0; iF < 4; iF++)
{
auto face_det = ed.face_determinants[4*(orient_elem_base+iT)+iF];
for (size_t k = 0; k < KS::num_fluxes; k++)
facc += face_det * inv_det * ed.lifting_matrices(iO*KS::num_bf+i, KS::num_fluxes*iF + k) * flux(flux_ofs+KS::num_fluxes*iF + k);
}
field(dof_ofs+i) = facc;
}
} }
orient_elem_base += num_elems; orient_elem_base += num_elems;
......
...@@ -97,7 +97,6 @@ class silo ...@@ -97,7 +97,6 @@ class silo
num_cells += elemTags.size(); num_cells += elemTags.size();
} }
} }
std::cout << nodelist.size() << " " << num_cells << std::endl;
assert(nodelist.size() == 4*num_cells); assert(nodelist.size() == 4*num_cells);
} }
......
...@@ -73,11 +73,11 @@ int test_differentiation_convergence(int geometric_order, int approximation_orde ...@@ -73,11 +73,11 @@ int test_differentiation_convergence(int geometric_order, int approximation_orde
make_geometry(0,h); make_geometry(0,h);
model mod(geometric_order, approximation_order); model mod(geometric_order, approximation_order);
#ifdef WRITE_TEST_OUTPUTS
std::stringstream ss; std::stringstream ss;
ss << "diff_go_" << geometric_order << "_ao_" << approximation_order; ss << "diff_go_" << geometric_order << "_ao_" << approximation_order;
ss << "_seq_" << i << ".silo"; ss << "_seq_" << i << ".silo";
#ifdef WRITE_TEST_OUTPUTS
silo silodb; silo silodb;
silodb.create_db(ss.str()); silodb.create_db(ss.str());
silodb.import_mesh_from_gmsh(); silodb.import_mesh_from_gmsh();
......
...@@ -17,47 +17,29 @@ static void ...@@ -17,47 +17,29 @@ static void
make_geometry(int order, double mesh_h) make_geometry(int order, double mesh_h)
{ {
gm::add("difftest"); gm::add("difftest");
gmo::addBox(0.0, 0.0, 0.0, 1.0, 1.0, 1.0);
gmo::synchronize();
gvp_t vp;
gm::getEntities(vp);
gmm::setSize(vp, mesh_h);
}
std::vector<std::pair<int,int>> objects;
int test_lifting_xx(int geometric_order, int approximation_order) objects.push_back(
{ std::make_pair(3, gmo::addBox(0.0, 0.0, 0.0, 1.0, 1.0, 0.5) )
make_geometry(0, 0.25); );
model mod(geometric_order, approximation_order); objects.push_back(
std::make_pair(3, gmo::addBox(0.0, 0.0, 0.5, 0.5, 0.5, 0.5) )
);
auto& e0 = mod.entity_at(0); std::vector<std::pair<int, int>> tools;
gmsh::vectorpair odt;
entity_data_cpu ed; std::vector<gmsh::vectorpair> odtm;
e0.populate_entity_data(ed); gmo::fragment(objects, tools, odt, odtm);
for (size_t iO = 0; iO < e0.num_cell_orientations(); iO++) gmo::synchronize();
{
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++) gvp_t vp;
{ gm::getEntities(vp);
matxd liftblock = curlift.block(0,iF*lift_cols/4,num_bf,lift_cols/4); gmm::setSize(vp, mesh_h);
std::cout << ones_cell.dot(liftblock*ones_face) << std::endl;
}
} }
return 0; #define WRITE_TEST_OUTPUTS
}
int test_lifting(int geometric_order, int approximation_order) int test_lifting(int geometric_order, int approximation_order)
{ {
...@@ -65,7 +47,7 @@ int test_lifting(int geometric_order, int approximation_order) ...@@ -65,7 +47,7 @@ int test_lifting(int geometric_order, int approximation_order)
std::vector<double> errors; std::vector<double> errors;
std::cout << cyanfg << "Testing geometric order " << geometric_order; std::cout << cyanfg << "Testing geometric order " << geometric_order;
std::cout << ", approximation order = " << approximation_order << nofg; std::cout << ", approximation order = " << approximation_order << reset;
std::cout << std::endl; std::cout << std::endl;
/* Test field */ /* Test field */
...@@ -91,7 +73,6 @@ int test_lifting(int geometric_order, int approximation_order) ...@@ -91,7 +73,6 @@ int test_lifting(int geometric_order, int approximation_order)
/* Expected divergence */ /* Expected divergence */
auto div_F = [](const point_3d& pt) -> double { auto div_F = [](const point_3d& pt) -> double {
//return 0;
auto dFx_dx = M_PI*std::cos(M_PI*pt.x()); auto dFx_dx = M_PI*std::cos(M_PI*pt.x());
auto dFy_dy = M_PI*std::cos(M_PI*pt.y()); auto dFy_dy = M_PI*std::cos(M_PI*pt.y());
auto dFz_dz = M_PI*std::cos(M_PI*pt.z()); auto dFz_dz = M_PI*std::cos(M_PI*pt.z());
...@@ -104,101 +85,99 @@ int test_lifting(int geometric_order, int approximation_order) ...@@ -104,101 +85,99 @@ int test_lifting(int geometric_order, int approximation_order)
make_geometry(0,h); make_geometry(0,h);
model mod(geometric_order, approximation_order); model mod(geometric_order, approximation_order);
#ifdef WRITE_TEST_OUTPUTS
std::stringstream ss; std::stringstream ss;
ss << "lifting_test_" << sz << ".silo"; ss << "lift_go_" << geometric_order << "_ao_" << approximation_order;
ss << "_seq_" << sz << ".silo";
silo s; silo silodb;
s.create_db( ss.str() ); silodb.create_db(ss.str());
s.import_mesh_from_gmsh(); silodb.import_mesh_from_gmsh();
s.write_mesh(); silodb.write_mesh();
#endif
auto& e0 = mod.entity_at(0);
entity_data_cpu ed; auto model_num_dofs = mod.num_dofs();
e0.populate_entity_data(ed); auto model_num_fluxes = mod.num_fluxes();
vecxd exp_field = e0.project(div_F); vecxd Pdiv_F = vecxd::Zero(model_num_dofs);
vecxd Fx_proj = e0.project(Fx); vecxd PFdotn = vecxd::Zero(model_num_fluxes);
vecxd Fy_proj = e0.project(Fy); vecxd LiftF = vecxd::Zero(model_num_dofs);
vecxd Fz_proj = e0.project(Fz);
auto flx_size = e0.num_cells() * 4*ed.num_fluxes; std::vector<entity_data_cpu> eds;
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++) for (auto& e : mod)
{ {
Fx_flux(i) = Fx_proj( ed.fluxdofs_mine[i] ); e.project(div_F, Pdiv_F);
Fy_flux(i) = Fy_proj( ed.fluxdofs_mine[i] ); entity_data_cpu ed;
Fz_flux(i) = Fz_proj( ed.fluxdofs_mine[i] ); e.populate_entity_data(ed);
}
vecxd flux = vecxd::Zero( flx_size ); vecxd PFx = e.project(Fx);
vecxd PFy = e.project(Fy);
vecxd PFz = e.project(Fz);
for (size_t iT = 0; iT < e0.num_cells(); iT++) for (size_t iT = 0; iT < e.num_cells(); iT++)
{ {
for (size_t iF = 0; iF < 4; iF++) for (size_t iF = 0; iF < 4; iF++)
{ {
auto face_det = ed.face_determinants[4*iT+iF];
vec3d n = ed.normals.row(4*iT+iF); vec3d n = ed.normals.row(4*iT+iF);
for (size_t k = 0; k < ed.num_fluxes; k++) for (size_t k = 0; k < ed.num_fluxes; k++)
{ {
auto dof_ofs = (4*iT+iF)*ed.num_fluxes + k; auto base = e.flux_base();
flux(dof_ofs) = Fx_flux(dof_ofs)*n(0) + auto ofs = (4*iT+iF)*ed.num_fluxes + k;
Fy_flux(dof_ofs)*n(1) + auto Fx = PFx( ed.fluxdofs_mine[ofs] );
Fz_flux(dof_ofs)*n(2); auto Fy = PFy( ed.fluxdofs_mine[ofs] );
auto Fz = PFz( ed.fluxdofs_mine[ofs] );
PFdotn(base+ofs) = face_det*Fx*n(0) +
face_det*Fy*n(1) +
face_det*Fz*n(2);
} }
} }
} }
vecxd lift_field = vecxd::Zero( e0.num_cells() * ed.num_bf ); eds.push_back( std::move(ed) );
#if 0 }
for (size_t iT = 0; iT < e0.num_cells(); iT++)
{
for (size_t iF = 0; iF < 4; iF++)
{
auto& pf = e0.face(4*iT+iF);
auto& rf = e0.face_refelem(pf);
auto num_fluxes = rf.num_basis_functions();
const auto pqps = pf.integration_points();
matxd mass = matxd::Zero(num_fluxes, num_fluxes);
vecxd rhs = vecxd::Zero(num_fluxes);
for (size_t iQp = 0; iQp < pqps.size(); iQp++) for (auto& ed : eds)
{ {
vec3d n; timecounter tc;
if (ed.g_order == 1) tc.tic();
n = ed.normals.row(4*iT+iF); compute_flux_lifting(ed, PFdotn, LiftF);
else double time = tc.toc();
n = ed.normals.row( (4*iT+iF)*pqps.size() + iQp );
const auto& pqp = pqps[iQp]; auto num_cells = num_elems_all_orientations(ed);
const vecxd phi = rf.basis_functions(iQp); if (geometric_order == 1)
mass += pqp.weight() * phi * phi.transpose(); {
rhs += pqp.weight() * F(pqp.point()).dot(n) * phi; std::cout << "Kernel runtime: " << time << " seconds. Estimated performance: ";
double flops = 3*(ed.num_bf)*4*ed.num_fluxes*num_cells;
std::cout << flops/(1e9*time) << " GFlops/s" << std::endl;
} }
auto fluxofs = (4*iT+iF)*num_fluxes; else
flux.segment(fluxofs, num_fluxes) = mass.ldlt().solve(rhs); {
std::cout << "Kernel runtime: " << time << " seconds. Estimated performance: ";
double flops = ((21*ed.num_bf+6)*ed.num_bf*ed.num_qp + 3*(2*ed.num_bf-1)*ed.num_bf)*num_cells;
std::cout << flops/(1e9*time) << " GFlops/s" << std::endl;
} }
} }
#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() ); #ifdef WRITE_TEST_OUTPUTS
std::vector<double> var_volp( e0.num_cells() ); std::vector<double> var_ediv_F( mod.num_cells() );
std::vector<double> var_elift( e0.num_cells() ); std::vector<double> var_div_F( mod.num_cells() );
std::vector<double> var_err( e0.num_cells() ); std::vector<double> var_lift( mod.num_cells() );
std::vector<double> var_orient( e0.num_cells() ); std::vector<double> var_vol( mod.num_cells() );
#endif
double err = 0.0; double err = 0.0;
for (size_t iT = 0; iT < e0.num_cells(); iT++)
for (auto& e : mod)
{
for (size_t iT = 0; iT < e.num_cells(); iT++)
{ {
auto& pe = e0.cell(iT); auto& pe = e.cell(iT);
auto& re = e0.cell_refelem(pe); auto& re = e.cell_refelem(pe);
auto num_bf = re.num_basis_functions(); auto num_bf = re.num_basis_functions();
matxd mass = matxd::Zero(num_bf, num_bf); matxd mass = matxd::Zero(num_bf, num_bf);
vecxd vol = vecxd::Zero(num_bf); vecxd vol = vecxd::Zero(num_bf);
...@@ -214,52 +193,38 @@ int test_lifting(int geometric_order, int approximation_order) ...@@ -214,52 +193,38 @@ int test_lifting(int geometric_order, int approximation_order)
vol += pqp.weight() * (dphi*J.inverse()) * F(pqp.point()); vol += pqp.weight() * (dphi*J.inverse()) * F(pqp.point());
} }
vecxd expected = exp_field.segment(iT*num_bf, num_bf); auto ofs = e.cell_global_dof_offset(iT);
vecxd lf = lift_field.segment(iT*num_bf, num_bf); vecxd excpected_div_F = Pdiv_F.segment(ofs, num_bf);
vecxd lfp = mass*lf; vecxd Plf = LiftF.segment(ofs, num_bf);
vecxd volp = mass.ldlt().solve(vol); vecxd Pvol = mass.ldlt().solve(vol);
//std::cout << "***" << std::endl;
//std::cout << lfp.transpose() << std::endl;
//std::cout << vol.transpose() << std::endl;
vecxd comp_field = lf - volp; vecxd computed_div_F = Plf - Pvol;
vecxd diff = comp_field - expected; vecxd diff = computed_div_F - excpected_div_F;
double loc_err = diff.dot(mass*diff); double loc_err = diff.dot(mass*diff);
err += loc_err; err += loc_err;
auto bar = pe.barycenter(); auto bar = pe.barycenter();
vecxd phi_bar = re.basis_functions({1./3., 1./3., 1./3.}); vecxd phi_bar = re.basis_functions({1./3., 1./3., 1./3.});
#ifdef WRITE_TEST_OUTPUTS
var_div_F.at( pe.original_position() ) = expected.dot(phi_bar); auto gi = e.cell_global_index_by_gmsh(iT);
var_lift.at( pe.original_position() ) = lf.dot(phi_bar); var_ediv_F[gi] = div_F(bar);
var_volp.at( pe.original_position() ) = volp.dot(phi_bar); var_div_F[gi] = computed_div_F.dot(phi_bar);
var_elift.at( pe.original_position() ) = (volp + expected).dot(phi_bar); var_lift[gi] = Plf.dot(phi_bar);
var_err.at( pe.original_position() ) = loc_err; var_vol[gi] = Pvol.dot(phi_bar);
var_orient.at( pe.original_position() ) = pe.orientation(); #endif
}
} }
s.write_zonal_variable("div_F", var_div_F); #ifdef WRITE_TEST_OUTPUTS
s.write_zonal_variable("lift", var_lift); silodb.write_zonal_variable("expected_div_F", var_ediv_F);
s.write_zonal_variable("vol", var_volp); silodb.write_zonal_variable("div_F", var_div_F);
s.write_zonal_variable("exp_lift", var_elift); silodb.write_zonal_variable("lift", var_lift);
s.write_zonal_variable("err", var_err); silodb.write_zonal_variable("vol", var_vol);
s.write_zonal_variable("orient", var_orient); #endif
std::cout << std::sqrt(err) << std::endl; std::cout << std::sqrt(err) << std::endl;
if (geometric_order == 1)
{
std::cout << "Kernel runtime: " << time << " seconds. Estimated performance: ";
double flops = 3*(ed.num_bf)*4*ed.num_fluxes*e0.num_cells();
std::cout << flops/(1e9*time) << " GFlops/s" << std::endl;
}
else
{
std::cout << "Kernel runtime: " << time << " seconds. Estimated performance: ";
double flops = ((21*ed.num_bf+6)*ed.num_bf*ed.num_qp + 3*(2*ed.num_bf-1)*ed.num_bf)*e0.num_cells();
std::cout << flops/(1e9*time) << " GFlops/s" << std::endl;
}
} }
return 0; return 0;
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment