342 constexpr
bool debug =
false;
344 constexpr
int numNodes = 4;
345 constexpr
int numEdges = 6;
346 constexpr
int refinementLevels = 4;
348 auto &m_field = fe_raw_ptr->
mField;
349 auto fe_ptr =
static_cast<Fe *
>(fe_raw_ptr);
350 auto fe_handle = fe_ptr->getFEEntityHandle();
352 auto set_base_quadrature = [&]() {
354 int rule = 2 * order_data + 1;
365 auto &gauss_pts = fe_ptr->gaussPts;
366 gauss_pts.resize(4, nb_gauss_pts,
false);
367 cblas_dcopy(nb_gauss_pts, &
QUAD_3D_TABLE[rule]->points[1], 4,
368 &gauss_pts(0, 0), 1);
369 cblas_dcopy(nb_gauss_pts, &
QUAD_3D_TABLE[rule]->points[2], 4,
370 &gauss_pts(1, 0), 1);
371 cblas_dcopy(nb_gauss_pts, &
QUAD_3D_TABLE[rule]->points[3], 4,
372 &gauss_pts(2, 0), 1);
374 &gauss_pts(3, 0), 1);
375 auto &data = fe_ptr->dataOnElement[
H1];
376 data->dataOnEntities[MBVERTEX][0].getN(
NOBASE).resize(nb_gauss_pts, 4,
379 &*data->dataOnEntities[MBVERTEX][0].getN(
NOBASE).data().begin();
380 cblas_dcopy(4 * nb_gauss_pts,
QUAD_3D_TABLE[rule]->points, 1, shape_ptr,
389 CHKERR set_base_quadrature();
393 auto get_singular_nodes = [&]() {
396 CHKERR m_field.get_moab().get_connectivity(fe_handle, conn, num_nodes,
398 std::bitset<numNodes> singular_nodes;
399 for (
auto nn = 0; nn != numNodes; ++nn) {
401 singular_nodes.set(nn);
403 singular_nodes.reset(nn);
406 return singular_nodes;
409 auto get_singular_edges = [&]() {
410 std::bitset<numEdges> singular_edges;
411 for (
int ee = 0; ee != numEdges; ee++) {
413 CHKERR m_field.get_moab().side_element(fe_handle, 1, ee, edge);
415 singular_edges.set(ee);
417 singular_edges.reset(ee);
420 return singular_edges;
423 auto set_gauss_pts = [&](
auto &ref_gauss_pts) {
425 fe_ptr->gaussPts.swap(ref_gauss_pts);
426 const size_t nb_gauss_pts = fe_ptr->gaussPts.size2();
427 auto &data = fe_ptr->dataOnElement[
H1];
428 data->dataOnEntities[MBVERTEX][0].getN(
NOBASE).resize(nb_gauss_pts, 4);
430 &*data->dataOnEntities[MBVERTEX][0].getN(
NOBASE).data().begin();
432 &fe_ptr->gaussPts(1, 0), &fe_ptr->gaussPts(2, 0),
437 auto singular_nodes = get_singular_nodes();
438 if (singular_nodes.count()) {
439 auto it_map_ref_coords =
mapRefCoords.find(singular_nodes.to_ulong());
441 CHKERR set_gauss_pts(it_map_ref_coords->second);
445 auto refine_quadrature = [&]() {
448 const int max_level = refinementLevels;
452 double base_coords[] = {0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1};
454 for (
int nn = 0; nn != 4; nn++)
455 CHKERR moab_ref.create_vertex(&base_coords[3 * nn], nodes[nn]);
456 CHKERR moab_ref.create_element(MBTET, nodes, 4, tet);
460 Range tets(tet, tet);
463 tets, 1,
true, edges, moab::Interface::UNION);
468 Range nodes_at_front;
469 for (
int nn = 0; nn != numNodes; nn++) {
470 if (singular_nodes[nn]) {
472 CHKERR moab_ref.side_element(tet, 0, nn, ent);
473 nodes_at_front.insert(ent);
477 auto singular_edges = get_singular_edges();
480 CHKERR moab_ref.create_meshset(MESHSET_SET, meshset);
481 for (
int ee = 0; ee != numEdges; ee++) {
482 if (singular_edges[ee]) {
484 CHKERR moab_ref.side_element(tet, 1, ee, ent);
485 CHKERR moab_ref.add_entities(meshset, &ent, 1);
491 for (
int ll = 0; ll != max_level; ll++) {
494 ->getEntitiesByTypeAndRefLevel(
BitRefLevel().set(ll),
498 CHKERR moab_ref.get_adjacencies(
499 nodes_at_front, 1,
true, ref_edges, moab::Interface::UNION);
500 ref_edges = intersect(ref_edges, edges);
502 CHKERR moab_ref.get_entities_by_type(meshset, MBEDGE, ents,
true);
503 ref_edges = intersect(ref_edges, ents);
506 ->getEntitiesByTypeAndRefLevel(
508 CHKERR m_ref->addVerticesInTheMiddleOfEdges(
512 ->updateMeshsetByEntitiesChildren(meshset,
514 meshset, MBEDGE,
true);
520 ->getEntitiesByTypeAndRefLevel(
BitRefLevel().set(max_level),
530 for (Range::iterator tit = tets.begin(); tit != tets.end();
534 CHKERR moab_ref.get_connectivity(*tit, conn, num_nodes,
false);
535 CHKERR moab_ref.get_coords(conn, num_nodes, &ref_coords(tt, 0));
538 auto &data = fe_ptr->dataOnElement[
H1];
539 const size_t nb_gauss_pts = fe_ptr->gaussPts.size2();
540 MatrixDouble ref_gauss_pts(4, nb_gauss_pts * ref_coords.size1());
542 data->dataOnEntities[MBVERTEX][0].getN(
NOBASE);
544 for (
size_t tt = 0; tt != ref_coords.size1(); tt++) {
545 double *tet_coords = &ref_coords(tt, 0);
546 double det = Tools::tetVolume(tet_coords);
548 for (
size_t ggg = 0; ggg != nb_gauss_pts; ++ggg, ++gg) {
549 for (
int dd = 0;
dd != 3;
dd++) {
550 ref_gauss_pts(
dd, gg) =
551 shape_n(ggg, 0) * tet_coords[3 * 0 +
dd] +
552 shape_n(ggg, 1) * tet_coords[3 * 1 +
dd] +
553 shape_n(ggg, 2) * tet_coords[3 * 2 +
dd] +
554 shape_n(ggg, 3) * tet_coords[3 * 3 +
dd];
556 ref_gauss_pts(3, gg) = fe_ptr->gaussPts(3, ggg) * det;
560 mapRefCoords[singular_nodes.to_ulong()].swap(ref_gauss_pts);
566 CHKERR refine_quadrature();